mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-01-01 20:32:27 +00:00
Compare commits
140 Commits
saghul-pat
...
android-sd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbdd1d2f38 | ||
|
|
53ebab33b3 | ||
|
|
a36965e908 | ||
|
|
9bf859ee50 | ||
|
|
24ff6f58a5 | ||
|
|
6338624095 | ||
|
|
9634d58d4e | ||
|
|
ad0064993d | ||
|
|
458d4acd22 | ||
|
|
8ebc99175c | ||
|
|
9889cb2b69 | ||
|
|
95a6f1355f | ||
|
|
191e530071 | ||
|
|
ae30d39b4d | ||
|
|
c354e46846 | ||
|
|
5da4e43e50 | ||
|
|
eae6f7760f | ||
|
|
00161212c8 | ||
|
|
8976b92842 | ||
|
|
c3a6a8fb17 | ||
|
|
fd3fb7ef55 | ||
|
|
391e5ca483 | ||
|
|
36654cb808 | ||
|
|
6d16e087d9 | ||
|
|
fe90e5aa8f | ||
|
|
3c22cd8ef4 | ||
|
|
5429b8568e | ||
|
|
0eccaf9a21 | ||
|
|
be0950c1ec | ||
|
|
6ecd150f75 | ||
|
|
02fb37189b | ||
|
|
8fe2536996 | ||
|
|
4b9e156c5d | ||
|
|
9265e1ffec | ||
|
|
d11735b04c | ||
|
|
d33b700477 | ||
|
|
6909c6a0f4 | ||
|
|
97d75c2cb9 | ||
|
|
287115f4c3 | ||
|
|
63a221212b | ||
|
|
6a916fd0e1 | ||
|
|
220691d61d | ||
|
|
5cafc4bcbd | ||
|
|
b3a78dc2e6 | ||
|
|
bebc6eabe5 | ||
|
|
26dc6a4ac2 | ||
|
|
ff2626723a | ||
|
|
72bb897269 | ||
|
|
f46387a226 | ||
|
|
a4cbbccb2a | ||
|
|
3e1a008399 | ||
|
|
7e70a8c1de | ||
|
|
8efee04a10 | ||
|
|
a35099f949 | ||
|
|
8be02f9ca1 | ||
|
|
3c25a4c08c | ||
|
|
5ade0cad8b | ||
|
|
0fa6ffc439 | ||
|
|
c2ed296178 | ||
|
|
febd12b871 | ||
|
|
0a06e256b7 | ||
|
|
f295f60bea | ||
|
|
4a8f787519 | ||
|
|
d85b869934 | ||
|
|
35130f0736 | ||
|
|
1feff9709c | ||
|
|
1010f53a84 | ||
|
|
f7a526f488 | ||
|
|
245eb89b85 | ||
|
|
99de9d0bfa | ||
|
|
98698ba89a | ||
|
|
19d1e3829d | ||
|
|
612586ed1f | ||
|
|
2609e43f29 | ||
|
|
c5cd4f534c | ||
|
|
6e10ca5dd2 | ||
|
|
0fff1c3534 | ||
|
|
42271b1b89 | ||
|
|
f270b50972 | ||
|
|
ab4b6be9d7 | ||
|
|
c45ee0230f | ||
|
|
d210f2f2e7 | ||
|
|
13d78d6b49 | ||
|
|
34a71042c6 | ||
|
|
47ecf7d035 | ||
|
|
bbe8c52778 | ||
|
|
2011421e9d | ||
|
|
ce55952ca9 | ||
|
|
f93482e815 | ||
|
|
761ac6a730 | ||
|
|
11d3a343e5 | ||
|
|
9666bf836e | ||
|
|
a6d3b09796 | ||
|
|
bb0036fdab | ||
|
|
8dc0f30a49 | ||
|
|
1aed08f460 | ||
|
|
afccf6f06d | ||
|
|
5cd351a46f | ||
|
|
51f257e894 | ||
|
|
ac06892bb4 | ||
|
|
fd8473cb52 | ||
|
|
3f40257f89 | ||
|
|
14509adff2 | ||
|
|
c472537ecf | ||
|
|
d40fce741a | ||
|
|
944e8f8353 | ||
|
|
7d972a50f2 | ||
|
|
92e7be34e3 | ||
|
|
f5dba929a5 | ||
|
|
64d2885233 | ||
|
|
4ce65ae7a7 | ||
|
|
07bf95f838 | ||
|
|
3469d5dc4f | ||
|
|
8c0f942ae1 | ||
|
|
b8aa74f212 | ||
|
|
2a7c6681ad | ||
|
|
324a9eba91 | ||
|
|
fb1ed22c6c | ||
|
|
00c8409e31 | ||
|
|
1b43c22940 | ||
|
|
efddb36164 | ||
|
|
385e1c1047 | ||
|
|
3cc181a2e5 | ||
|
|
bcc1be675f | ||
|
|
d1be5742ba | ||
|
|
1b27e331da | ||
|
|
c1f7bf75c1 | ||
|
|
382ec011eb | ||
|
|
8a3ddd8596 | ||
|
|
738a199b4c | ||
|
|
40a1af5302 | ||
|
|
be5dba7eea | ||
|
|
eb15f73e59 | ||
|
|
2f7b485b8f | ||
|
|
3a885c893a | ||
|
|
6c4901a826 | ||
|
|
91c1c91950 | ||
|
|
1091ac7e7d | ||
|
|
0c0bd001e5 | ||
|
|
256994e1f8 |
@@ -11,6 +11,9 @@ node_modules/react-native/Libraries/react-native/React.js
|
||||
; "node_modules/react-native" but in the source repo it is in the root
|
||||
node_modules/react-native/Libraries/react-native/React.js
|
||||
|
||||
; Flow doesn't support platforms
|
||||
.*/Libraries/Utilities/LoadingView.js
|
||||
|
||||
; Ignore polyfills
|
||||
node_modules/react-native/Libraries/polyfills/.*
|
||||
|
||||
@@ -112,4 +115,4 @@ untyped-import
|
||||
untyped-type-import
|
||||
|
||||
[version]
|
||||
^0.98.0
|
||||
^0.104.0
|
||||
|
||||
11
.github/ISSUE_TEMPLATE/4-security-issues.md
vendored
Normal file
11
.github/ISSUE_TEMPLATE/4-security-issues.md
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
name: Security issues
|
||||
about: Please email security@jitsi.org
|
||||
|
||||
---
|
||||
|
||||
We take security very seriously and develop all Jitsi projects to be secure and safe.
|
||||
|
||||
If you find (or simply suspect) a security issue in any of the Jitsi projects, please send us an email to security@jitsi.org.
|
||||
|
||||
We encourage responsible disclosure for the sake of our users, so please reach out before posting in a public space.
|
||||
@@ -1,4 +1,4 @@
|
||||
osx_image: xcode10.2
|
||||
osx_image: xcode11.1
|
||||
language: objective-c
|
||||
script:
|
||||
- "./ios/travis-ci/build-ipa.sh"
|
||||
|
||||
12
Makefile
12
Makefile
@@ -3,6 +3,7 @@ CLEANCSS = ./node_modules/.bin/cleancss
|
||||
DEPLOY_DIR = libs
|
||||
LIBJITSIMEET_DIR = node_modules/lib-jitsi-meet/
|
||||
LIBFLAC_DIR = node_modules/libflacjs/dist/min/
|
||||
RNNOISE_WASM_DIR = node_modules/rnnoise-wasm/dist/
|
||||
NODE_SASS = ./node_modules/.bin/node-sass
|
||||
NPM = npm
|
||||
OUTPUT_DIR = .
|
||||
@@ -20,7 +21,7 @@ compile:
|
||||
clean:
|
||||
rm -fr $(BUILD_DIR)
|
||||
|
||||
deploy: deploy-init deploy-appbundle deploy-lib-jitsi-meet deploy-libflac deploy-css deploy-local
|
||||
deploy: deploy-init deploy-appbundle deploy-rnnoise-binary deploy-lib-jitsi-meet deploy-libflac deploy-css deploy-local
|
||||
|
||||
deploy-init:
|
||||
rm -fr $(DEPLOY_DIR)
|
||||
@@ -47,6 +48,8 @@ deploy-appbundle:
|
||||
$(BUILD_DIR)/analytics-ga.min.map \
|
||||
$(BUILD_DIR)/video-blur-effect.min.js \
|
||||
$(BUILD_DIR)/video-blur-effect.min.map \
|
||||
$(BUILD_DIR)/rnnoise-processor.min.js \
|
||||
$(BUILD_DIR)/rnnoise-processor.min.map \
|
||||
$(DEPLOY_DIR)
|
||||
|
||||
deploy-lib-jitsi-meet:
|
||||
@@ -63,6 +66,11 @@ deploy-libflac:
|
||||
$(LIBFLAC_DIR)/libflac4-1.3.2.min.js.mem \
|
||||
$(DEPLOY_DIR)
|
||||
|
||||
deploy-rnnoise-binary:
|
||||
cp \
|
||||
$(RNNOISE_WASM_DIR)/rnnoise.wasm \
|
||||
$(DEPLOY_DIR)
|
||||
|
||||
deploy-css:
|
||||
$(NODE_SASS) $(STYLES_MAIN) $(STYLES_BUNDLE) && \
|
||||
$(CLEANCSS) $(STYLES_BUNDLE) > $(STYLES_DESTINATION) ; \
|
||||
@@ -71,7 +79,7 @@ deploy-css:
|
||||
deploy-local:
|
||||
([ ! -x deploy-local.sh ] || ./deploy-local.sh)
|
||||
|
||||
dev: deploy-init deploy-css deploy-lib-jitsi-meet deploy-libflac
|
||||
dev: deploy-init deploy-css deploy-rnnoise-binary deploy-lib-jitsi-meet deploy-libflac
|
||||
$(WEBPACK_DEV_SERVER)
|
||||
|
||||
source-package:
|
||||
|
||||
90
README.md
90
README.md
@@ -31,82 +31,9 @@ You can get our mobile versions from here:
|
||||
* [Android](https://play.google.com/store/apps/details?id=org.jitsi.meet)
|
||||
* [iOS](https://itunes.apple.com/us/app/jitsi-meet/id1165103905)
|
||||
|
||||
## Building the sources
|
||||
## Development
|
||||
|
||||
Node.js >= 10 and npm >= 6 are required.
|
||||
|
||||
On Debian/Ubuntu systems, the required packages can be installed with:
|
||||
```
|
||||
sudo apt-get install npm nodejs
|
||||
cd jitsi-meet
|
||||
npm install
|
||||
```
|
||||
|
||||
To build the Jitsi Meet application, just type
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
### Working with the library sources (lib-jitsi-meet)
|
||||
|
||||
By default the library is build from its git repository sources. The default dependency path in package.json is :
|
||||
```json
|
||||
"lib-jitsi-meet": "jitsi/lib-jitsi-meet",
|
||||
```
|
||||
|
||||
To work with local copy you must change the path to:
|
||||
```json
|
||||
"lib-jitsi-meet": "file:///Users/name/local-lib-jitsi-meet-copy",
|
||||
```
|
||||
|
||||
To make the project you must force it to take the sources as 'npm update':
|
||||
```
|
||||
npm install lib-jitsi-meet --force && make
|
||||
```
|
||||
|
||||
Or if you are making only changes to the library:
|
||||
```
|
||||
npm install lib-jitsi-meet --force && make deploy-lib-jitsi-meet
|
||||
```
|
||||
|
||||
Alternative way is to use [npm link](https://docs.npmjs.com/cli/link).
|
||||
It allows to link `lib-jitsi-meet` dependency to local source in few steps:
|
||||
|
||||
```bash
|
||||
cd lib-jitsi-meet
|
||||
|
||||
#### create global symlink for lib-jitsi-meet package
|
||||
npm link
|
||||
|
||||
cd ../jitsi-meet
|
||||
|
||||
#### create symlink from the local node_modules folder to the global lib-jitsi-meet symlink
|
||||
npm link lib-jitsi-meet
|
||||
```
|
||||
|
||||
After changes in local `lib-jitsi-meet` repository, you can rebuild it with `npm run install` and your `jitsi-meet` repository will use that modified library.
|
||||
Note: when using node version 4.x, the make file of jitsi-meet do npm update which will delete the link. It is no longer the case with version 6.x.
|
||||
|
||||
If you do not want to use local repository anymore you should run
|
||||
```bash
|
||||
cd jitsi-meet
|
||||
npm unlink lib-jitsi-meet
|
||||
npm install
|
||||
```
|
||||
### Running with webpack-dev-server for development
|
||||
|
||||
Use it at the CLI, type
|
||||
```
|
||||
make dev
|
||||
```
|
||||
|
||||
By default the backend deployment used is `beta.meet.jit.si`. You can point the Jitsi-Meet app at a different backend by using a proxy server. To do this, set the WEBPACK_DEV_SERVER_PROXY_TARGET variable:
|
||||
```
|
||||
export WEBPACK_DEV_SERVER_PROXY_TARGET=https://your-example-server.com
|
||||
make dev
|
||||
```
|
||||
|
||||
The app should be running at https://localhost:8080/
|
||||
For web development see [here](doc/development.md), and for mobile see [here](doc/mobile.md).
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -118,7 +45,8 @@ see our [guidelines for contributing](CONTRIBUTING.md).
|
||||
Jitsi Meet provides a very flexible way of embedding in external applications by using the [Jitsi Meet API](doc/api.md).
|
||||
|
||||
## Security
|
||||
WebRTC does not provide a way of conducting multi-party conversations with end-to-end encryption.
|
||||
|
||||
WebRTC does not (yet) provide a way of conducting multi-party conversations with end-to-end encryption.
|
||||
Unless you consistently compare DTLS fingerprints with your peers vocally, the same goes for one-to-one calls.
|
||||
As a result, your stream is encrypted on the network but decrypted on the machine that hosts the bridge when using Jitsi Meet.
|
||||
|
||||
@@ -130,9 +58,13 @@ Jitsi Meet in terms of security.
|
||||
The [meet.jit.si](https://meet.jit.si) service is maintained by the Jitsi team
|
||||
at [8x8](https://8x8.com).
|
||||
|
||||
## Mobile app
|
||||
Jitsi Meet is also available as a React Native app for Android and iOS.
|
||||
Instructions on how to build it can be found [here](doc/mobile.md).
|
||||
## Security issues
|
||||
|
||||
We take security very seriously and develop all Jitsi projects to be secure and safe.
|
||||
|
||||
If you find (or simply suspect) a security issue in any of the Jitsi projects, please send us an email to security@jitsi.org.
|
||||
|
||||
**We encourage responsible disclosure for the sake of our users, so please reach out before posting in a public space.**
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
|
||||
@@ -34,8 +34,6 @@ android {
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-debug.pro'
|
||||
buildConfigField "boolean", "GOOGLE_SERVICES_ENABLED", "${googleServicesEnabled}"
|
||||
buildConfigField "boolean", "LIBRE_BUILD", "${rootProject.ext.libreBuild}"
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
-include proguard-rules.pro
|
||||
|
||||
# Disabling obfuscation is useful if you collect stack traces from production crashes
|
||||
# (unless you are using a system that supports de-obfuscate the stack traces).
|
||||
-dontobfuscate
|
||||
3
android/app/proguard-rules.pro
vendored
3
android/app/proguard-rules.pro
vendored
@@ -83,3 +83,6 @@
|
||||
-dontwarn javax.servlet.**
|
||||
|
||||
# ^^^ We added the above when we switched minifyEnabled on.
|
||||
|
||||
# Rule to avoid build errors related to SVGs.
|
||||
-keep public class com.horcrux.svg.** {*;}
|
||||
@@ -20,5 +20,5 @@
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
||||
appVersion=19.3.0
|
||||
sdkVersion=2.2.2
|
||||
appVersion=19.4.0
|
||||
sdkVersion=2.4.0
|
||||
|
||||
@@ -10,7 +10,7 @@ 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)
|
||||
JSC_VERSION="r"$(jq -r '.dependencies."jsc-android"' ${THIS_DIR}/../../node_modules/react-native/package.json | cut -d . -f 1)
|
||||
JSC_VERSION="r"$(jq -r '.dependencies."jsc-android"' ${THIS_DIR}/../../node_modules/react-native/package.json | cut -d . -f 1 | cut -c 2-)
|
||||
DO_GIT_TAG=${GIT_TAG:-0}
|
||||
|
||||
if [[ $THE_MVN_REPO == http* ]]; then
|
||||
|
||||
@@ -45,6 +45,7 @@ dependencies {
|
||||
|
||||
implementation 'com.dropbox.core:dropbox-core-sdk:3.0.8'
|
||||
implementation 'com.jakewharton.timber:timber:4.7.1'
|
||||
implementation 'com.squareup.duktape:duktape-android:1.3.0'
|
||||
|
||||
if (!rootProject.ext.libreBuild) {
|
||||
implementation 'com.amplitude:android-sdk:2.14.1'
|
||||
@@ -62,7 +63,7 @@ dependencies {
|
||||
implementation project(':react-native-keep-awake')
|
||||
implementation project(':react-native-linear-gradient')
|
||||
implementation project(':react-native-sound')
|
||||
implementation project(':react-native-vector-icons')
|
||||
implementation project(':react-native-svg')
|
||||
implementation project(':react-native-webrtc')
|
||||
implementation project(':react-native-webview')
|
||||
|
||||
@@ -140,13 +141,6 @@ android.libraryVariants.all { def variant ->
|
||||
mergeAssetsTask.doLast {
|
||||
def assetsDir = mergeAssetsTask.outputDir
|
||||
|
||||
// Bundle fonts
|
||||
//
|
||||
copy {
|
||||
from("${projectDir}/../../fonts/jitsi.ttf")
|
||||
into("${assetsDir}/fonts")
|
||||
}
|
||||
|
||||
// Bundle sounds
|
||||
//
|
||||
copy {
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright @ 2017-present 8x8, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.telecom.CallAudioState;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
|
||||
/**
|
||||
* {@link AudioModeModule.AudioDeviceHandlerInterface} module implementing device handling for
|
||||
* Android versions >= O when ConnectionService is enabled.
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
class AudioDeviceHandlerConnectionService implements
|
||||
AudioModeModule.AudioDeviceHandlerInterface,
|
||||
RNConnectionService.CallAudioStateListener {
|
||||
|
||||
private final static String TAG = AudioDeviceHandlerConnectionService.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Reference to the main {@code AudioModeModule}.
|
||||
*/
|
||||
private AudioModeModule module;
|
||||
|
||||
/**
|
||||
* Converts any of the "DEVICE_" constants into the corresponding
|
||||
* {@link android.telecom.CallAudioState} "ROUTE_" number.
|
||||
*
|
||||
* @param audioDevice one of the "DEVICE_" constants.
|
||||
* @return a route number {@link android.telecom.CallAudioState#ROUTE_EARPIECE} if
|
||||
* no match is found.
|
||||
*/
|
||||
private static int audioDeviceToRouteInt(String audioDevice) {
|
||||
if (audioDevice == null) {
|
||||
return CallAudioState.ROUTE_EARPIECE;
|
||||
}
|
||||
switch (audioDevice) {
|
||||
case AudioModeModule.DEVICE_BLUETOOTH:
|
||||
return CallAudioState.ROUTE_BLUETOOTH;
|
||||
case AudioModeModule.DEVICE_EARPIECE:
|
||||
return CallAudioState.ROUTE_EARPIECE;
|
||||
case AudioModeModule.DEVICE_HEADPHONES:
|
||||
return CallAudioState.ROUTE_WIRED_HEADSET;
|
||||
case AudioModeModule.DEVICE_SPEAKER:
|
||||
return CallAudioState.ROUTE_SPEAKER;
|
||||
default:
|
||||
JitsiMeetLogger.e(TAG + " Unsupported device name: " + audioDevice);
|
||||
return CallAudioState.ROUTE_EARPIECE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates given route mask into the "DEVICE_" list.
|
||||
*
|
||||
* @param supportedRouteMask an integer coming from
|
||||
* {@link android.telecom.CallAudioState#getSupportedRouteMask()}.
|
||||
* @return a list of device names.
|
||||
*/
|
||||
private static Set<String> routesToDeviceNames(int supportedRouteMask) {
|
||||
Set<String> devices = new HashSet<>();
|
||||
if ((supportedRouteMask & CallAudioState.ROUTE_EARPIECE) == CallAudioState.ROUTE_EARPIECE) {
|
||||
devices.add(AudioModeModule.DEVICE_EARPIECE);
|
||||
}
|
||||
if ((supportedRouteMask & CallAudioState.ROUTE_BLUETOOTH) == CallAudioState.ROUTE_BLUETOOTH) {
|
||||
devices.add(AudioModeModule.DEVICE_BLUETOOTH);
|
||||
}
|
||||
if ((supportedRouteMask & CallAudioState.ROUTE_SPEAKER) == CallAudioState.ROUTE_SPEAKER) {
|
||||
devices.add(AudioModeModule.DEVICE_SPEAKER);
|
||||
}
|
||||
if ((supportedRouteMask & CallAudioState.ROUTE_WIRED_HEADSET) == CallAudioState.ROUTE_WIRED_HEADSET) {
|
||||
devices.add(AudioModeModule.DEVICE_HEADPHONES);
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to store the most recently reported audio devices.
|
||||
* Makes it easier to compare for a change, because the devices are stored
|
||||
* as a mask in the {@link android.telecom.CallAudioState}. The mask is populated into
|
||||
* the {@code availableDevices} on each update.
|
||||
*/
|
||||
private int supportedRouteMask = -1;
|
||||
|
||||
public AudioDeviceHandlerConnectionService() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCallAudioStateChange(final CallAudioState state) {
|
||||
module.runInAudioThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
boolean audioRouteChanged
|
||||
= audioDeviceToRouteInt(module.getSelectedDevice()) != state.getRoute();
|
||||
int newSupportedRoutes = state.getSupportedRouteMask();
|
||||
boolean audioDevicesChanged = supportedRouteMask != newSupportedRoutes;
|
||||
if (audioDevicesChanged) {
|
||||
supportedRouteMask = newSupportedRoutes;
|
||||
Set<String> devices = routesToDeviceNames(supportedRouteMask);
|
||||
module.replaceDevices(devices);
|
||||
JitsiMeetLogger.i(TAG + " Available audio devices: " + devices.toString());
|
||||
}
|
||||
|
||||
if (audioRouteChanged || audioDevicesChanged) {
|
||||
module.resetSelectedDevice();
|
||||
module.updateAudioRoute();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Context context, AudioModeModule audioModeModule) {
|
||||
JitsiMeetLogger.i("Using " + TAG + " as the audio device handler");
|
||||
|
||||
module = audioModeModule;
|
||||
RNConnectionService rcs = ReactInstanceManagerHolder.getNativeModule(RNConnectionService.class);
|
||||
if (rcs != null) {
|
||||
rcs.setCallAudioStateListener(this);
|
||||
} else {
|
||||
JitsiMeetLogger.w(TAG + " Couldn't set call audio state listener, module is null");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
RNConnectionService rcs = ReactInstanceManagerHolder.getNativeModule(RNConnectionService.class);
|
||||
if (rcs != null) {
|
||||
rcs.setCallAudioStateListener(null);
|
||||
} else {
|
||||
JitsiMeetLogger.w(TAG + " Couldn't set call audio state listener, module is null");
|
||||
}
|
||||
}
|
||||
|
||||
public void setAudioRoute(String audioDevice) {
|
||||
int newAudioRoute = audioDeviceToRouteInt(audioDevice);
|
||||
|
||||
RNConnectionService.setAudioRoute(newAudioRoute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setMode(int mode) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Copyright @ 2017-present 8x8, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.AudioDeviceInfo;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
|
||||
/**
|
||||
* {@link AudioModeModule.AudioDeviceHandlerInterface} module implementing device handling for
|
||||
* all post-M Android versions. This handler can be used on any Android versions >= M, but by
|
||||
* default it's only used on versions < O, since versions >= O use ConnectionService, but it
|
||||
* can be disabled.
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.M)
|
||||
class AudioDeviceHandlerGeneric implements
|
||||
AudioModeModule.AudioDeviceHandlerInterface,
|
||||
AudioManager.OnAudioFocusChangeListener {
|
||||
|
||||
private final static String TAG = AudioDeviceHandlerGeneric.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Reference to the main {@code AudioModeModule}.
|
||||
*/
|
||||
private AudioModeModule module;
|
||||
|
||||
/**
|
||||
* Constant defining a USB headset. Only available on API level >= 26.
|
||||
* The value of: AudioDeviceInfo.TYPE_USB_HEADSET
|
||||
*/
|
||||
private static final int TYPE_USB_HEADSET = 22;
|
||||
|
||||
/**
|
||||
* Indicator that we have lost audio focus.
|
||||
*/
|
||||
private boolean audioFocusLost = false;
|
||||
|
||||
/**
|
||||
* {@link AudioManager} instance used to interact with the Android audio
|
||||
* subsystem.
|
||||
*/
|
||||
private AudioManager audioManager;
|
||||
|
||||
/**
|
||||
* {@link Runnable} for running audio device detection the main thread.
|
||||
* This is only used on Android >= M.
|
||||
*/
|
||||
private final Runnable onAudioDeviceChangeRunner = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Set<String> devices = new HashSet<>();
|
||||
AudioDeviceInfo[] deviceInfos = audioManager.getDevices(AudioManager.GET_DEVICES_ALL);
|
||||
|
||||
for (AudioDeviceInfo info: deviceInfos) {
|
||||
switch (info.getType()) {
|
||||
case AudioDeviceInfo.TYPE_BLUETOOTH_SCO:
|
||||
devices.add(AudioModeModule.DEVICE_BLUETOOTH);
|
||||
break;
|
||||
case AudioDeviceInfo.TYPE_BUILTIN_EARPIECE:
|
||||
devices.add(AudioModeModule.DEVICE_EARPIECE);
|
||||
break;
|
||||
case AudioDeviceInfo.TYPE_BUILTIN_SPEAKER:
|
||||
devices.add(AudioModeModule.DEVICE_SPEAKER);
|
||||
break;
|
||||
case AudioDeviceInfo.TYPE_WIRED_HEADPHONES:
|
||||
case AudioDeviceInfo.TYPE_WIRED_HEADSET:
|
||||
case TYPE_USB_HEADSET:
|
||||
devices.add(AudioModeModule.DEVICE_HEADPHONES);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
module.replaceDevices(devices);
|
||||
|
||||
JitsiMeetLogger.i(TAG + " Available audio devices: " + devices.toString());
|
||||
|
||||
module.updateAudioRoute();
|
||||
}
|
||||
};
|
||||
|
||||
private final android.media.AudioDeviceCallback audioDeviceCallback =
|
||||
new android.media.AudioDeviceCallback() {
|
||||
@Override
|
||||
public void onAudioDevicesAdded(
|
||||
AudioDeviceInfo[] addedDevices) {
|
||||
JitsiMeetLogger.d(TAG + " Audio devices added");
|
||||
onAudioDeviceChange();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAudioDevicesRemoved(
|
||||
AudioDeviceInfo[] removedDevices) {
|
||||
JitsiMeetLogger.d(TAG + " Audio devices removed");
|
||||
onAudioDeviceChange();
|
||||
}
|
||||
};
|
||||
|
||||
public AudioDeviceHandlerGeneric() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to trigger an audio route update when devices change. It
|
||||
* makes sure the operation is performed on the audio thread.
|
||||
*/
|
||||
private void onAudioDeviceChange() {
|
||||
module.runInAudioThread(onAudioDeviceChangeRunner);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link AudioManager.OnAudioFocusChangeListener} interface method. Called
|
||||
* when the audio focus of the system is updated.
|
||||
*
|
||||
* @param focusChange - The type of focus change.
|
||||
*/
|
||||
@Override
|
||||
public void onAudioFocusChange(final int focusChange) {
|
||||
module.runInAudioThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
switch (focusChange) {
|
||||
case AudioManager.AUDIOFOCUS_GAIN: {
|
||||
JitsiMeetLogger.d(TAG + " Audio focus gained");
|
||||
// Some other application potentially stole our audio focus
|
||||
// temporarily. Restore our mode.
|
||||
if (audioFocusLost) {
|
||||
module.updateAudioRoute();
|
||||
}
|
||||
audioFocusLost = false;
|
||||
break;
|
||||
}
|
||||
case AudioManager.AUDIOFOCUS_LOSS:
|
||||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
|
||||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: {
|
||||
JitsiMeetLogger.d(TAG + " Audio focus lost");
|
||||
audioFocusLost = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to set the output route to a Bluetooth device.
|
||||
*
|
||||
* @param enabled true if Bluetooth should use used, false otherwise.
|
||||
*/
|
||||
private void setBluetoothAudioRoute(boolean enabled) {
|
||||
if (enabled) {
|
||||
audioManager.startBluetoothSco();
|
||||
audioManager.setBluetoothScoOn(true);
|
||||
} else {
|
||||
audioManager.setBluetoothScoOn(false);
|
||||
audioManager.stopBluetoothSco();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Context context, AudioModeModule audioModeModule) {
|
||||
JitsiMeetLogger.i("Using " + TAG + " as the audio device handler");
|
||||
|
||||
module = audioModeModule;
|
||||
audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
|
||||
|
||||
// Setup runtime device change detection.
|
||||
audioManager.registerAudioDeviceCallback(audioDeviceCallback, null);
|
||||
|
||||
// Do an initial detection.
|
||||
onAudioDeviceChange();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
audioManager.unregisterAudioDeviceCallback(audioDeviceCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAudioRoute(String device) {
|
||||
// Turn speaker on / off
|
||||
audioManager.setSpeakerphoneOn(device.equals(AudioModeModule.DEVICE_SPEAKER));
|
||||
|
||||
// Turn bluetooth on / off
|
||||
setBluetoothAudioRoute(device.equals(AudioModeModule.DEVICE_BLUETOOTH));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setMode(int mode) {
|
||||
if (mode == AudioModeModule.DEFAULT) {
|
||||
audioFocusLost = false;
|
||||
audioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
audioManager.abandonAudioFocus(this);
|
||||
audioManager.setSpeakerphoneOn(false);
|
||||
setBluetoothAudioRoute(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
|
||||
audioManager.setMicrophoneMute(false);
|
||||
|
||||
if (audioManager.requestAudioFocus(this, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN)
|
||||
== AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
|
||||
JitsiMeetLogger.w(TAG + " Audio focus request failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright @ 2017-present 8x8, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.AudioManager;
|
||||
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
|
||||
/**
|
||||
* {@link AudioModeModule.AudioDeviceHandlerInterface} module implementing device handling for
|
||||
* legacy (pre-M) Android versions.
|
||||
*/
|
||||
class AudioDeviceHandlerLegacy implements
|
||||
AudioModeModule.AudioDeviceHandlerInterface,
|
||||
AudioManager.OnAudioFocusChangeListener,
|
||||
BluetoothHeadsetMonitor.Listener {
|
||||
|
||||
private final static String TAG = AudioDeviceHandlerLegacy.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Reference to the main {@code AudioModeModule}.
|
||||
*/
|
||||
private AudioModeModule module;
|
||||
|
||||
/**
|
||||
* Indicator that we have lost audio focus.
|
||||
*/
|
||||
private boolean audioFocusLost = false;
|
||||
|
||||
/**
|
||||
* {@link AudioManager} instance used to interact with the Android audio
|
||||
* subsystem.
|
||||
*/
|
||||
private AudioManager audioManager;
|
||||
|
||||
/**
|
||||
* {@link BluetoothHeadsetMonitor} for detecting Bluetooth device changes in
|
||||
* old (< M) Android versions.
|
||||
*/
|
||||
private BluetoothHeadsetMonitor bluetoothHeadsetMonitor;
|
||||
|
||||
public AudioDeviceHandlerLegacy() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to trigger an audio route update when Bluetooth devices are
|
||||
* connected / disconnected.
|
||||
*/
|
||||
@Override
|
||||
public void onBluetoothDeviceChange(final boolean deviceAvailable) {
|
||||
module.runInAudioThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (deviceAvailable) {
|
||||
module.addDevice(AudioModeModule.DEVICE_BLUETOOTH);
|
||||
} else {
|
||||
module.removeDevice(AudioModeModule.DEVICE_BLUETOOTH);
|
||||
}
|
||||
|
||||
module.updateAudioRoute();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to trigger an audio route update when a headset is plugged
|
||||
* or unplugged.
|
||||
*/
|
||||
private void onHeadsetDeviceChange() {
|
||||
module.runInAudioThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// XXX: isWiredHeadsetOn is not deprecated when used just for
|
||||
// knowing if there is a wired headset connected, regardless of
|
||||
// audio being routed to it.
|
||||
//noinspection deprecation
|
||||
if (audioManager.isWiredHeadsetOn()) {
|
||||
module.addDevice(AudioModeModule.DEVICE_HEADPHONES);
|
||||
} else {
|
||||
module.removeDevice(AudioModeModule.DEVICE_HEADPHONES);
|
||||
}
|
||||
|
||||
module.updateAudioRoute();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link AudioManager.OnAudioFocusChangeListener} interface method. Called
|
||||
* when the audio focus of the system is updated.
|
||||
*
|
||||
* @param focusChange - The type of focus change.
|
||||
*/
|
||||
@Override
|
||||
public void onAudioFocusChange(final int focusChange) {
|
||||
module.runInAudioThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
switch (focusChange) {
|
||||
case AudioManager.AUDIOFOCUS_GAIN: {
|
||||
JitsiMeetLogger.d(TAG + " Audio focus gained");
|
||||
// Some other application potentially stole our audio focus
|
||||
// temporarily. Restore our mode.
|
||||
if (audioFocusLost) {
|
||||
module.updateAudioRoute();
|
||||
}
|
||||
audioFocusLost = false;
|
||||
break;
|
||||
}
|
||||
case AudioManager.AUDIOFOCUS_LOSS:
|
||||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
|
||||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: {
|
||||
JitsiMeetLogger.d(TAG + " Audio focus lost");
|
||||
audioFocusLost = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to set the output route to a Bluetooth device.
|
||||
*
|
||||
* @param enabled true if Bluetooth should use used, false otherwise.
|
||||
*/
|
||||
private void setBluetoothAudioRoute(boolean enabled) {
|
||||
if (enabled) {
|
||||
audioManager.startBluetoothSco();
|
||||
audioManager.setBluetoothScoOn(true);
|
||||
} else {
|
||||
audioManager.setBluetoothScoOn(false);
|
||||
audioManager.stopBluetoothSco();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Context context, AudioModeModule audioModeModule) {
|
||||
JitsiMeetLogger.i("Using " + TAG + " as the audio device handler");
|
||||
|
||||
module = audioModeModule;
|
||||
audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
|
||||
|
||||
// Setup runtime device change detection.
|
||||
//
|
||||
|
||||
// Detect changes in wired headset connections.
|
||||
IntentFilter wiredHeadSetFilter = new IntentFilter(AudioManager.ACTION_HEADSET_PLUG);
|
||||
BroadcastReceiver wiredHeadsetReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
JitsiMeetLogger.d(TAG + " Wired headset added / removed");
|
||||
onHeadsetDeviceChange();
|
||||
}
|
||||
};
|
||||
context.registerReceiver(wiredHeadsetReceiver, wiredHeadSetFilter);
|
||||
|
||||
// Detect Bluetooth device changes.
|
||||
bluetoothHeadsetMonitor = new BluetoothHeadsetMonitor(context, this);
|
||||
|
||||
// On Android < M, detect if we have an earpiece.
|
||||
PackageManager pm = context.getPackageManager();
|
||||
if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
|
||||
module.addDevice(AudioModeModule.DEVICE_EARPIECE);
|
||||
}
|
||||
|
||||
// Always assume there is a speaker.
|
||||
module.addDevice(AudioModeModule.DEVICE_SPEAKER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
bluetoothHeadsetMonitor.stop();
|
||||
bluetoothHeadsetMonitor = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAudioRoute(String device) {
|
||||
// Turn speaker on / off
|
||||
audioManager.setSpeakerphoneOn(device.equals(AudioModeModule.DEVICE_SPEAKER));
|
||||
|
||||
// Turn bluetooth on / off
|
||||
setBluetoothAudioRoute(device.equals(AudioModeModule.DEVICE_BLUETOOTH));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setMode(int mode) {
|
||||
if (mode == AudioModeModule.DEFAULT) {
|
||||
audioFocusLost = false;
|
||||
audioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
audioManager.abandonAudioFocus(this);
|
||||
audioManager.setSpeakerphoneOn(false);
|
||||
setBluetoothAudioRoute(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
|
||||
audioManager.setMicrophoneMute(false);
|
||||
|
||||
if (audioManager.requestAudioFocus(this, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN)
|
||||
== AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
|
||||
JitsiMeetLogger.w(TAG + " Audio focus request failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright @ 2017-present Atlassian Pty Ltd
|
||||
* Copyright @ 2017-present 8x8, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,16 +16,8 @@
|
||||
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.AudioDeviceInfo;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.Promise;
|
||||
@@ -61,9 +53,7 @@ import java.util.concurrent.Executors;
|
||||
* {@code AudioModeModule.DEFAULT} mode should be used.
|
||||
*/
|
||||
@ReactModule(name = AudioModeModule.NAME)
|
||||
class AudioModeModule extends ReactContextBaseJavaModule
|
||||
implements AudioManager.OnAudioFocusChangeListener {
|
||||
|
||||
class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
public static final String NAME = "AudioMode";
|
||||
|
||||
/**
|
||||
@@ -75,174 +65,33 @@ class AudioModeModule extends ReactContextBaseJavaModule
|
||||
* - VIDEO_CALL: Used for video calls. It will use the speaker by default,
|
||||
* unless a wired or Bluetooth headset is connected.
|
||||
*/
|
||||
private static final int DEFAULT = 0;
|
||||
private static final int AUDIO_CALL = 1;
|
||||
private static final int VIDEO_CALL = 2;
|
||||
|
||||
/**
|
||||
* Constant defining the action for plugging in a headset. This is used on
|
||||
* our device detection system for API < 23.
|
||||
*/
|
||||
private static final String ACTION_HEADSET_PLUG
|
||||
= (Build.VERSION.SDK_INT >= 21)
|
||||
? AudioManager.ACTION_HEADSET_PLUG
|
||||
: Intent.ACTION_HEADSET_PLUG;
|
||||
|
||||
/**
|
||||
* Constant defining a USB headset. Only available on API level >= 26.
|
||||
* The value of: AudioDeviceInfo.TYPE_USB_HEADSET
|
||||
*/
|
||||
private static final int TYPE_USB_HEADSET = 22;
|
||||
static final int DEFAULT = 0;
|
||||
static final int AUDIO_CALL = 1;
|
||||
static final int VIDEO_CALL = 2;
|
||||
|
||||
/**
|
||||
* The {@code Log} tag {@code AudioModeModule} is to log messages with.
|
||||
*/
|
||||
static final String TAG = NAME;
|
||||
|
||||
/**
|
||||
* Converts any of the "DEVICE_" constants into the corresponding
|
||||
* {@link android.telecom.CallAudioState} "ROUTE_" number.
|
||||
*
|
||||
* @param audioDevice one of the "DEVICE_" constants.
|
||||
* @return a route number {@link android.telecom.CallAudioState#ROUTE_EARPIECE} if
|
||||
* no match is found.
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||
private static int audioDeviceToRouteInt(String audioDevice) {
|
||||
if (audioDevice == null) {
|
||||
return android.telecom.CallAudioState.ROUTE_EARPIECE;
|
||||
}
|
||||
switch (audioDevice) {
|
||||
case DEVICE_BLUETOOTH:
|
||||
return android.telecom.CallAudioState.ROUTE_BLUETOOTH;
|
||||
case DEVICE_EARPIECE:
|
||||
return android.telecom.CallAudioState.ROUTE_EARPIECE;
|
||||
case DEVICE_HEADPHONES:
|
||||
return android.telecom.CallAudioState.ROUTE_WIRED_HEADSET;
|
||||
case DEVICE_SPEAKER:
|
||||
return android.telecom.CallAudioState.ROUTE_SPEAKER;
|
||||
default:
|
||||
JitsiMeetLogger.e(TAG + " Unsupported device name: " + audioDevice);
|
||||
return android.telecom.CallAudioState.ROUTE_EARPIECE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates given route mask into the "DEVICE_" list.
|
||||
*
|
||||
* @param supportedRouteMask an integer coming from
|
||||
* {@link android.telecom.CallAudioState#getSupportedRouteMask()}.
|
||||
* @return a list of device names.
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||
private static Set<String> routesToDeviceNames(int supportedRouteMask) {
|
||||
Set<String> devices = new HashSet<>();
|
||||
if ((supportedRouteMask & android.telecom.CallAudioState.ROUTE_EARPIECE)
|
||||
== android.telecom.CallAudioState.ROUTE_EARPIECE) {
|
||||
devices.add(DEVICE_EARPIECE);
|
||||
}
|
||||
if ((supportedRouteMask & android.telecom.CallAudioState.ROUTE_BLUETOOTH)
|
||||
== android.telecom.CallAudioState.ROUTE_BLUETOOTH) {
|
||||
devices.add(DEVICE_BLUETOOTH);
|
||||
}
|
||||
if ((supportedRouteMask & android.telecom.CallAudioState.ROUTE_SPEAKER)
|
||||
== android.telecom.CallAudioState.ROUTE_SPEAKER) {
|
||||
devices.add(DEVICE_SPEAKER);
|
||||
}
|
||||
if ((supportedRouteMask & android.telecom.CallAudioState.ROUTE_WIRED_HEADSET)
|
||||
== android.telecom.CallAudioState.ROUTE_WIRED_HEADSET) {
|
||||
devices.add(DEVICE_HEADPHONES);
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the ConnectionService is used for selecting audio devices.
|
||||
*/
|
||||
|
||||
private static final boolean supportsConnectionService = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
|
||||
private static boolean useConnectionService_ = supportsConnectionService;
|
||||
|
||||
static boolean useConnectionService() {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
|
||||
return supportsConnectionService && useConnectionService_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicator that we have lost audio focus.
|
||||
*/
|
||||
private boolean audioFocusLost = false;
|
||||
|
||||
/**
|
||||
* {@link AudioManager} instance used to interact with the Android audio
|
||||
* subsystem.
|
||||
*/
|
||||
private final AudioManager audioManager;
|
||||
|
||||
/**
|
||||
* {@link BluetoothHeadsetMonitor} for detecting Bluetooth device changes in
|
||||
* old (< M) Android versions.
|
||||
*/
|
||||
private BluetoothHeadsetMonitor bluetoothHeadsetMonitor;
|
||||
private AudioDeviceHandlerInterface audioDeviceHandler;
|
||||
|
||||
/**
|
||||
* {@link ExecutorService} for running all audio operations on a dedicated
|
||||
* thread.
|
||||
*/
|
||||
private static final ExecutorService executor
|
||||
= Executors.newSingleThreadExecutor();
|
||||
|
||||
/**
|
||||
* {@link Runnable} for running audio device detection the main thread.
|
||||
* This is only used on Android >= M.
|
||||
*/
|
||||
private final Runnable onAudioDeviceChangeRunner = new Runnable() {
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
@Override
|
||||
public void run() {
|
||||
Set<String> devices = new HashSet<>();
|
||||
AudioDeviceInfo[] deviceInfos
|
||||
= audioManager.getDevices(AudioManager.GET_DEVICES_ALL);
|
||||
|
||||
for (AudioDeviceInfo info: deviceInfos) {
|
||||
switch (info.getType()) {
|
||||
case AudioDeviceInfo.TYPE_BLUETOOTH_SCO:
|
||||
devices.add(DEVICE_BLUETOOTH);
|
||||
break;
|
||||
case AudioDeviceInfo.TYPE_BUILTIN_EARPIECE:
|
||||
devices.add(DEVICE_EARPIECE);
|
||||
break;
|
||||
case AudioDeviceInfo.TYPE_BUILTIN_SPEAKER:
|
||||
devices.add(DEVICE_SPEAKER);
|
||||
break;
|
||||
case AudioDeviceInfo.TYPE_WIRED_HEADPHONES:
|
||||
case AudioDeviceInfo.TYPE_WIRED_HEADSET:
|
||||
case TYPE_USB_HEADSET:
|
||||
devices.add(DEVICE_HEADPHONES);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
availableDevices = devices;
|
||||
JitsiMeetLogger.i(TAG + " Available audio devices: " +
|
||||
availableDevices.toString());
|
||||
|
||||
// Reset user selection
|
||||
userSelectedDevice = null;
|
||||
|
||||
if (mode != -1) {
|
||||
updateAudioRoute(mode);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* {@link Runnable} for running update operation on the main thread.
|
||||
*/
|
||||
private final Runnable updateAudioRouteRunner
|
||||
= new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mode != -1) {
|
||||
updateAudioRoute(mode);
|
||||
}
|
||||
}
|
||||
};
|
||||
private static final ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
|
||||
/**
|
||||
* Audio mode currently in use.
|
||||
@@ -252,10 +101,10 @@ class AudioModeModule extends ReactContextBaseJavaModule
|
||||
/**
|
||||
* Audio device types.
|
||||
*/
|
||||
private static final String DEVICE_BLUETOOTH = "BLUETOOTH";
|
||||
private static final String DEVICE_EARPIECE = "EARPIECE";
|
||||
private static final String DEVICE_HEADPHONES = "HEADPHONES";
|
||||
private static final String DEVICE_SPEAKER = "SPEAKER";
|
||||
static final String DEVICE_BLUETOOTH = "BLUETOOTH";
|
||||
static final String DEVICE_EARPIECE = "EARPIECE";
|
||||
static final String DEVICE_HEADPHONES = "HEADPHONES";
|
||||
static final String DEVICE_SPEAKER = "SPEAKER";
|
||||
|
||||
/**
|
||||
* Device change event.
|
||||
@@ -272,15 +121,6 @@ class AudioModeModule extends ReactContextBaseJavaModule
|
||||
*/
|
||||
private String selectedDevice;
|
||||
|
||||
/**
|
||||
* Used on API >= 26 to store the most recently reported audio devices.
|
||||
* Makes it easier to compare for a change, because the devices are stored
|
||||
* as a mask in the {@link android.telecom.CallAudioState}. The mask is populated into
|
||||
* the {@link #availableDevices} on each update.
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
private int supportedRouteMask;
|
||||
|
||||
/**
|
||||
* User selected device. When null the default is used depending on the
|
||||
* mode.
|
||||
@@ -296,31 +136,6 @@ class AudioModeModule extends ReactContextBaseJavaModule
|
||||
*/
|
||||
public AudioModeModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
|
||||
audioManager
|
||||
= (AudioManager)
|
||||
reactContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
|
||||
// Starting Oreo the ConnectionImpl from ConnectionService is used to
|
||||
// detect the available devices.
|
||||
if (!useConnectionService()) {
|
||||
// Setup runtime device change detection.
|
||||
setupAudioRouteChangeDetection();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
// Do an initial detection on Android >= M.
|
||||
onAudioDeviceChange();
|
||||
} else {
|
||||
// On Android < M, detect if we have an earpiece.
|
||||
PackageManager pm = reactContext.getPackageManager();
|
||||
if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
|
||||
availableDevices.add(DEVICE_EARPIECE);
|
||||
}
|
||||
|
||||
// Always assume there is a speaker.
|
||||
availableDevices.add(DEVICE_SPEAKER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,132 +192,36 @@ class AudioModeModule extends ReactContextBaseJavaModule
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to trigger an audio route update when devices change. It
|
||||
* makes sure the operation is performed on the main thread.
|
||||
*
|
||||
* Only used on Android >= M.
|
||||
*/
|
||||
void onAudioDeviceChange() {
|
||||
runInAudioThread(onAudioDeviceChangeRunner);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to trigger an audio route update when Bluetooth devices are
|
||||
* connected / disconnected.
|
||||
*
|
||||
* Only used on Android < M. Runs on the main thread.
|
||||
*/
|
||||
void onBluetoothDeviceChange() {
|
||||
if (bluetoothHeadsetMonitor != null && bluetoothHeadsetMonitor.isHeadsetAvailable()) {
|
||||
availableDevices.add(DEVICE_BLUETOOTH);
|
||||
} else {
|
||||
availableDevices.remove(DEVICE_BLUETOOTH);
|
||||
}
|
||||
|
||||
if (mode != -1) {
|
||||
updateAudioRoute(mode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to trigger an audio route update when a headset is plugged
|
||||
* or unplugged.
|
||||
*
|
||||
* Only used on Android < M.
|
||||
*/
|
||||
void onHeadsetDeviceChange() {
|
||||
runInAudioThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// XXX: isWiredHeadsetOn is not deprecated when used just for
|
||||
// knowing if there is a wired headset connected, regardless of
|
||||
// audio being routed to it.
|
||||
//noinspection deprecation
|
||||
if (audioManager.isWiredHeadsetOn()) {
|
||||
availableDevices.add(DEVICE_HEADPHONES);
|
||||
} else {
|
||||
availableDevices.remove(DEVICE_HEADPHONES);
|
||||
}
|
||||
|
||||
if (mode != -1) {
|
||||
updateAudioRoute(mode);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
void onCallAudioStateChange(Object callAudioState_) {
|
||||
final android.telecom.CallAudioState callAudioState
|
||||
= (android.telecom.CallAudioState)callAudioState_;
|
||||
runInAudioThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int newSupportedRoutes = callAudioState.getSupportedRouteMask();
|
||||
boolean audioDevicesChanged
|
||||
= supportedRouteMask != newSupportedRoutes;
|
||||
if (audioDevicesChanged) {
|
||||
supportedRouteMask = newSupportedRoutes;
|
||||
availableDevices = routesToDeviceNames(supportedRouteMask);
|
||||
JitsiMeetLogger.i(TAG + " Available audio devices: "
|
||||
+ availableDevices.toString());
|
||||
}
|
||||
|
||||
boolean audioRouteChanged
|
||||
= audioDeviceToRouteInt(selectedDevice)
|
||||
!= callAudioState.getRoute();
|
||||
|
||||
if (audioRouteChanged || audioDevicesChanged) {
|
||||
// Reset user selection
|
||||
userSelectedDevice = null;
|
||||
|
||||
// If the OS changes the Audio Route or Devices we could have lost
|
||||
// the selected audio device
|
||||
selectedDevice = null;
|
||||
|
||||
if (mode != -1) {
|
||||
updateAudioRoute(mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link AudioManager.OnAudioFocusChangeListener} interface method. Called
|
||||
* when the audio focus of the system is updated.
|
||||
*
|
||||
* @param focusChange - The type of focus change.
|
||||
* Initializes the audio device handler module. This function is called *after* all Catalyst
|
||||
* modules have been created, and that's why we use it, because {@link AudioDeviceHandlerConnectionService}
|
||||
* needs access to another Catalyst module, so doing this in the constructor would be too early.
|
||||
*/
|
||||
@Override
|
||||
public void onAudioFocusChange(int focusChange) {
|
||||
switch (focusChange) {
|
||||
case AudioManager.AUDIOFOCUS_GAIN: {
|
||||
JitsiMeetLogger.d(TAG + " Audio focus gained");
|
||||
// Some other application potentially stole our audio focus
|
||||
// temporarily. Restore our mode.
|
||||
if (audioFocusLost) {
|
||||
updateAudioRoute(mode);
|
||||
}
|
||||
audioFocusLost = false;
|
||||
break;
|
||||
}
|
||||
case AudioManager.AUDIOFOCUS_LOSS:
|
||||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
|
||||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: {
|
||||
JitsiMeetLogger.d(TAG + " Audio focus lost");
|
||||
audioFocusLost = true;
|
||||
break;
|
||||
public void initialize() {
|
||||
setAudioDeviceHandler();
|
||||
}
|
||||
|
||||
private void setAudioDeviceHandler() {
|
||||
if (audioDeviceHandler != null) {
|
||||
audioDeviceHandler.stop();
|
||||
}
|
||||
|
||||
if (useConnectionService()) {
|
||||
audioDeviceHandler = new AudioDeviceHandlerConnectionService();
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
audioDeviceHandler = new AudioDeviceHandlerGeneric();
|
||||
} else {
|
||||
audioDeviceHandler = new AudioDeviceHandlerLegacy();
|
||||
}
|
||||
|
||||
audioDeviceHandler.start(getReactApplicationContext(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to run operations on a dedicated thread.
|
||||
* @param runnable
|
||||
*/
|
||||
public void runInAudioThread(Runnable runnable) {
|
||||
void runInAudioThread(Runnable runnable) {
|
||||
executor.execute(runnable);
|
||||
}
|
||||
|
||||
@@ -531,46 +250,6 @@ class AudioModeModule extends ReactContextBaseJavaModule
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The API >= 26 way of adjusting the audio route.
|
||||
*
|
||||
* @param audioDevice one of the "DEVICE_" names to set as the audio route.
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
private void setAudioRoute(String audioDevice) {
|
||||
int newAudioRoute = audioDeviceToRouteInt(audioDevice);
|
||||
|
||||
RNConnectionService.setAudioRoute(newAudioRoute);
|
||||
}
|
||||
|
||||
/**
|
||||
* The API < 26 way of adjusting the audio route.
|
||||
*
|
||||
* @param audioDevice one of the "DEVICE_" names to set as the audio route.
|
||||
*/
|
||||
private void setAudioRoutePreO(String audioDevice) {
|
||||
// Turn bluetooth on / off
|
||||
setBluetoothAudioRoute(audioDevice.equals(DEVICE_BLUETOOTH));
|
||||
|
||||
// Turn speaker on / off
|
||||
audioManager.setSpeakerphoneOn(audioDevice.equals(DEVICE_SPEAKER));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to set the output route to a Bluetooth device.
|
||||
*
|
||||
* @param enabled true if Bluetooth should use used, false otherwise.
|
||||
*/
|
||||
private void setBluetoothAudioRoute(boolean enabled) {
|
||||
if (enabled) {
|
||||
audioManager.startBluetoothSco();
|
||||
audioManager.setBluetoothScoOn(true);
|
||||
} else {
|
||||
audioManager.setBluetoothScoOn(false);
|
||||
audioManager.stopBluetoothSco();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Public method to set the current audio mode.
|
||||
*
|
||||
@@ -600,70 +279,22 @@ class AudioModeModule extends ReactContextBaseJavaModule
|
||||
AudioModeModule.this.mode = mode;
|
||||
promise.resolve(null);
|
||||
} else {
|
||||
promise.reject(
|
||||
"setMode",
|
||||
"Failed to set audio mode to " + mode);
|
||||
promise.reject("setMode", "Failed to set audio mode to " + mode);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the audio route change detection mechanism. We use the
|
||||
* {@link android.media.AudioDeviceCallback} on 23 >= Android API < 26.
|
||||
* Sets whether ConnectionService should be used (if available) for setting the audio mode
|
||||
* or not.
|
||||
*
|
||||
* @param use Boolean indicator of where it should be used or not.
|
||||
*/
|
||||
private void setupAudioRouteChangeDetection() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
setupAudioRouteChangeDetectionM();
|
||||
} else {
|
||||
setupAudioRouteChangeDetectionPreM();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Audio route change detection mechanism for 23 >= Android API < 26.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
private void setupAudioRouteChangeDetectionM() {
|
||||
android.media.AudioDeviceCallback audioDeviceCallback =
|
||||
new android.media.AudioDeviceCallback() {
|
||||
@Override
|
||||
public void onAudioDevicesAdded(
|
||||
AudioDeviceInfo[] addedDevices) {
|
||||
JitsiMeetLogger.d(TAG + " Audio devices added");
|
||||
onAudioDeviceChange();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAudioDevicesRemoved(
|
||||
AudioDeviceInfo[] removedDevices) {
|
||||
JitsiMeetLogger.d(TAG + " Audio devices removed");
|
||||
onAudioDeviceChange();
|
||||
}
|
||||
};
|
||||
|
||||
audioManager.registerAudioDeviceCallback(audioDeviceCallback, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Audio route change detection mechanism for Android API < 23.
|
||||
*/
|
||||
private void setupAudioRouteChangeDetectionPreM() {
|
||||
Context context = getReactApplicationContext();
|
||||
|
||||
// Detect changes in wired headset connections.
|
||||
IntentFilter wiredHeadSetFilter = new IntentFilter(ACTION_HEADSET_PLUG);
|
||||
BroadcastReceiver wiredHeadsetReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
JitsiMeetLogger.d(TAG + " Wired headset added / removed");
|
||||
onHeadsetDeviceChange();
|
||||
}
|
||||
};
|
||||
context.registerReceiver(wiredHeadsetReceiver, wiredHeadSetFilter);
|
||||
|
||||
// Detect Bluetooth device changes.
|
||||
bluetoothHeadsetMonitor = new BluetoothHeadsetMonitor(this, context);
|
||||
@ReactMethod
|
||||
public void setUseConnectionService(boolean use) {
|
||||
useConnectionService_ = use;
|
||||
setAudioDeviceHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -676,14 +307,11 @@ class AudioModeModule extends ReactContextBaseJavaModule
|
||||
private boolean updateAudioRoute(int mode) {
|
||||
JitsiMeetLogger.i(TAG + " Update audio route for mode: " + mode);
|
||||
|
||||
if (!audioDeviceHandler.setMode(mode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mode == DEFAULT) {
|
||||
if (!useConnectionService()) {
|
||||
audioFocusLost = false;
|
||||
audioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
audioManager.abandonAudioFocus(this);
|
||||
audioManager.setSpeakerphoneOn(false);
|
||||
setBluetoothAudioRoute(false);
|
||||
}
|
||||
selectedDevice = null;
|
||||
userSelectedDevice = null;
|
||||
|
||||
@@ -691,20 +319,6 @@ class AudioModeModule extends ReactContextBaseJavaModule
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!useConnectionService()) {
|
||||
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
|
||||
audioManager.setMicrophoneMute(false);
|
||||
|
||||
if (audioManager.requestAudioFocus(
|
||||
this,
|
||||
AudioManager.STREAM_VOICE_CALL,
|
||||
AudioManager.AUDIOFOCUS_GAIN)
|
||||
== AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
|
||||
JitsiMeetLogger.w(TAG + " Audio focus request failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean bluetoothAvailable = availableDevices.contains(DEVICE_BLUETOOTH);
|
||||
boolean headsetAvailable = availableDevices.contains(DEVICE_HEADPHONES);
|
||||
|
||||
@@ -719,8 +333,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
|
||||
}
|
||||
|
||||
// Consider the user's selection
|
||||
if (userSelectedDevice != null
|
||||
&& availableDevices.contains(userSelectedDevice)) {
|
||||
if (userSelectedDevice != null && availableDevices.contains(userSelectedDevice)) {
|
||||
audioDevice = userSelectedDevice;
|
||||
}
|
||||
|
||||
@@ -733,13 +346,97 @@ class AudioModeModule extends ReactContextBaseJavaModule
|
||||
selectedDevice = audioDevice;
|
||||
JitsiMeetLogger.i(TAG + " Selected audio device: " + audioDevice);
|
||||
|
||||
if (useConnectionService()) {
|
||||
setAudioRoute(audioDevice);
|
||||
} else {
|
||||
setAudioRoutePreO(audioDevice);
|
||||
}
|
||||
audioDeviceHandler.setAudioRoute(audioDevice);
|
||||
|
||||
notifyDevicesChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the currently selected audio device.
|
||||
*
|
||||
* @return The selected audio device.
|
||||
*/
|
||||
String getSelectedDevice() {
|
||||
return selectedDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the current device selection.
|
||||
*/
|
||||
void resetSelectedDevice() {
|
||||
selectedDevice = null;
|
||||
userSelectedDevice = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new device to the list of available devices.
|
||||
*
|
||||
* @param device The new device.
|
||||
*/
|
||||
void addDevice(String device) {
|
||||
availableDevices.add(device);
|
||||
resetSelectedDevice();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a device from the list of available devices.
|
||||
*
|
||||
* @param device The old device to the removed.
|
||||
*/
|
||||
void removeDevice(String device) {
|
||||
availableDevices.remove(device);
|
||||
resetSelectedDevice();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the current list of available devices with a new one.
|
||||
*
|
||||
* @param devices The new devices list.
|
||||
*/
|
||||
void replaceDevices(Set<String> devices) {
|
||||
availableDevices = devices;
|
||||
resetSelectedDevice();
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-sets the current audio route. Needed when devices changes have happened.
|
||||
*/
|
||||
void updateAudioRoute() {
|
||||
if (mode != -1) {
|
||||
updateAudioRoute(mode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for the modules implementing the actual audio device management.
|
||||
*/
|
||||
interface AudioDeviceHandlerInterface {
|
||||
/**
|
||||
* Start detecting audio device changes.
|
||||
* @param context Android {@link Context} where detection should take place.
|
||||
* @param audioModeModule Reference to the main {@link AudioModeModule}.
|
||||
*/
|
||||
void start(Context context, AudioModeModule audioModeModule);
|
||||
|
||||
/**
|
||||
* Stop audio device detection.
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* Set the appropriate route for the given audio device.
|
||||
*
|
||||
* @param device Audio device for which the route must be set.
|
||||
*/
|
||||
void setAudioRoute(String device);
|
||||
|
||||
/**
|
||||
* Set the given audio mode.
|
||||
*
|
||||
* @param mode The new audio mode to be used.
|
||||
* @return Whether the operation was successful or not.
|
||||
*/
|
||||
boolean setMode(int mode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright @ 2017-present Atlassian Pty Ltd
|
||||
* Copyright @ 2017-present 8x8, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,68 +33,43 @@ import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
* about device changes when this occurs.
|
||||
*/
|
||||
class BluetoothHeadsetMonitor {
|
||||
/**
|
||||
* {@link AudioModeModule} where this monitor reports.
|
||||
*/
|
||||
private final AudioModeModule audioModeModule;
|
||||
private final static String TAG = BluetoothHeadsetMonitor.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* The {@link Context} in which {@link #audioModeModule} executes.
|
||||
* The {@link Context} in which this module executes.
|
||||
*/
|
||||
private final Context context;
|
||||
|
||||
/**
|
||||
* Reference to the {@link BluetoothAdapter} object, used to access Bluetooth functionality.
|
||||
*/
|
||||
private BluetoothAdapter adapter;
|
||||
|
||||
/**
|
||||
* Reference to a proxy object which allows us to query connected devices.
|
||||
*/
|
||||
private BluetoothHeadset headset;
|
||||
|
||||
/**
|
||||
* Flag indicating if there are any Bluetooth headset devices currently
|
||||
* available.
|
||||
* receiver registered for receiving Bluetooth connection state changes.
|
||||
*/
|
||||
private boolean headsetAvailable = false;
|
||||
private BroadcastReceiver receiver;
|
||||
|
||||
/**
|
||||
* Helper for running Bluetooth operations on the main thread.
|
||||
* Listener for receiving Bluetooth device change events.
|
||||
*/
|
||||
private final Runnable updateDevicesRunnable
|
||||
= new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
headsetAvailable
|
||||
= (headset != null)
|
||||
&& !headset.getConnectedDevices().isEmpty();
|
||||
audioModeModule.onBluetoothDeviceChange();
|
||||
}
|
||||
};
|
||||
private Listener listener;
|
||||
|
||||
public BluetoothHeadsetMonitor(
|
||||
AudioModeModule audioModeModule,
|
||||
Context context) {
|
||||
this.audioModeModule = audioModeModule;
|
||||
public BluetoothHeadsetMonitor(Context context, Listener listener) {
|
||||
this.context = context;
|
||||
|
||||
AudioManager audioManager
|
||||
= (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
||||
|
||||
if (!audioManager.isBluetoothScoAvailableOffCall()) {
|
||||
JitsiMeetLogger.w(AudioModeModule.TAG + " Bluetooth SCO is not available");
|
||||
return;
|
||||
}
|
||||
|
||||
if (getBluetoothHeadsetProfileProxy()) {
|
||||
registerBluetoothReceiver();
|
||||
|
||||
// Initial detection.
|
||||
updateDevices();
|
||||
}
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
private boolean getBluetoothHeadsetProfileProxy() {
|
||||
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
|
||||
adapter = BluetoothAdapter.getDefaultAdapter();
|
||||
|
||||
if (adapter == null) {
|
||||
JitsiMeetLogger.w(AudioModeModule.TAG + " Device doesn't support Bluetooth");
|
||||
JitsiMeetLogger.w(TAG + " Device doesn't support Bluetooth");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -104,9 +79,7 @@ class BluetoothHeadsetMonitor {
|
||||
BluetoothProfile.ServiceListener listener
|
||||
= new BluetoothProfile.ServiceListener() {
|
||||
@Override
|
||||
public void onServiceConnected(
|
||||
int profile,
|
||||
BluetoothProfile proxy) {
|
||||
public void onServiceConnected(int profile, BluetoothProfile proxy) {
|
||||
if (profile == BluetoothProfile.HEADSET) {
|
||||
headset = (BluetoothHeadset) proxy;
|
||||
updateDevices();
|
||||
@@ -120,21 +93,7 @@ class BluetoothHeadsetMonitor {
|
||||
}
|
||||
};
|
||||
|
||||
return
|
||||
adapter.getProfileProxy(
|
||||
context,
|
||||
listener,
|
||||
BluetoothProfile.HEADSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current headset availability.
|
||||
*
|
||||
* @return {@code true} if there is a Bluetooth headset connected;
|
||||
* {@code false}, otherwise.
|
||||
*/
|
||||
public boolean isHeadsetAvailable() {
|
||||
return headsetAvailable;
|
||||
return adapter.getProfileProxy(context, listener, BluetoothProfile.HEADSET);
|
||||
}
|
||||
|
||||
private void onBluetoothReceiverReceive(Context context, Intent intent) {
|
||||
@@ -149,7 +108,7 @@ class BluetoothHeadsetMonitor {
|
||||
switch (state) {
|
||||
case BluetoothHeadset.STATE_CONNECTED:
|
||||
case BluetoothHeadset.STATE_DISCONNECTED:
|
||||
JitsiMeetLogger.d(AudioModeModule.TAG + " BT headset connection state changed: " + state);
|
||||
JitsiMeetLogger.d(TAG + " BT headset connection state changed: " + state);
|
||||
updateDevices();
|
||||
break;
|
||||
}
|
||||
@@ -157,13 +116,12 @@ class BluetoothHeadsetMonitor {
|
||||
// XXX: This action will be fired when the connection established
|
||||
// with a Bluetooth headset (called a SCO connection) changes state.
|
||||
// When the SCO connection is active we route audio to it.
|
||||
int state
|
||||
= intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -99);
|
||||
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -99);
|
||||
|
||||
switch (state) {
|
||||
case AudioManager.SCO_AUDIO_STATE_CONNECTED:
|
||||
case AudioManager.SCO_AUDIO_STATE_DISCONNECTED:
|
||||
JitsiMeetLogger.d(AudioModeModule.TAG + " BT SCO connection state changed: " + state);
|
||||
JitsiMeetLogger.d(TAG + " BT SCO connection state changed: " + state);
|
||||
updateDevices();
|
||||
break;
|
||||
}
|
||||
@@ -171,24 +129,63 @@ class BluetoothHeadsetMonitor {
|
||||
}
|
||||
|
||||
private void registerBluetoothReceiver() {
|
||||
BroadcastReceiver receiver = new BroadcastReceiver() {
|
||||
receiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
onBluetoothReceiverReceive(context, intent);
|
||||
}
|
||||
};
|
||||
IntentFilter filter = new IntentFilter();
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
|
||||
filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
|
||||
|
||||
context.registerReceiver(receiver, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects if there are new devices connected / disconnected and fires the
|
||||
* {@link AudioModeModule#onAudioDeviceChange()} callback.
|
||||
* {@link Listener} registered event.
|
||||
*/
|
||||
private void updateDevices() {
|
||||
audioModeModule.runInAudioThread(updateDevicesRunnable);
|
||||
boolean headsetAvailable = (headset != null) && !headset.getConnectedDevices().isEmpty();
|
||||
listener.onBluetoothDeviceChange(headsetAvailable);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
||||
|
||||
if (!audioManager.isBluetoothScoAvailableOffCall()) {
|
||||
JitsiMeetLogger.w(TAG + " Bluetooth SCO is not available");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!getBluetoothHeadsetProfileProxy()) {
|
||||
JitsiMeetLogger.w(TAG + " Couldn't get BT profile proxy");
|
||||
return;
|
||||
}
|
||||
|
||||
registerBluetoothReceiver();
|
||||
|
||||
// Initial detection.
|
||||
updateDevices();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (receiver != null) {
|
||||
context.unregisterReceiver(receiver);
|
||||
}
|
||||
|
||||
if (adapter != null && headset != null) {
|
||||
adapter.closeProfileProxy(BluetoothProfile.HEADSET, headset);
|
||||
}
|
||||
|
||||
receiver = null;
|
||||
headset = null;
|
||||
adapter = null;
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
void onBluetoothDeviceChange(boolean deviceAvailable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ public class ConnectionService extends android.telecom.ConnectionService {
|
||||
if (connection != null) {
|
||||
connection.setActive();
|
||||
} else {
|
||||
JitsiMeetLogger.e("% setConnectionActive - no connection for UUID: %s", TAG, callUUID);
|
||||
JitsiMeetLogger.e("%s setConnectionActive - no connection for UUID: %s", TAG, callUUID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ public class ConnectionService extends android.telecom.ConnectionService {
|
||||
: VideoProfile.STATE_AUDIO_ONLY);
|
||||
}
|
||||
} else {
|
||||
JitsiMeetLogger.e(TAG + " updateCall no connection for UUID: " + callUUID);
|
||||
JitsiMeetLogger.e(TAG + " updateCall no connection for UUID: " + callUUID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,7 +292,7 @@ public class ConnectionService extends android.telecom.ConnectionService {
|
||||
JitsiMeetLogger.e(TAG + " unregisterPhoneAccount - account handle is null");
|
||||
}
|
||||
} else {
|
||||
JitsiMeetLogger.e(TAG + "unregisterPhoneAccount - telecom is null");
|
||||
JitsiMeetLogger.e(TAG + " unregisterPhoneAccount - telecom is null");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,11 +403,9 @@ public class ConnectionService extends android.telecom.ConnectionService {
|
||||
@Override
|
||||
public void onCallAudioStateChanged(CallAudioState state) {
|
||||
JitsiMeetLogger.d(TAG + " onCallAudioStateChanged: " + state);
|
||||
AudioModeModule audioModeModule
|
||||
= ReactInstanceManagerHolder
|
||||
.getNativeModule(AudioModeModule.class);
|
||||
if (audioModeModule != null) {
|
||||
audioModeModule.onCallAudioStateChange(state);
|
||||
RNConnectionService module = ReactInstanceManagerHolder.getNativeModule(RNConnectionService.class);
|
||||
if (module != null) {
|
||||
module.onCallAudioStateChange(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright @ 2019-present 8x8, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.squareup.duktape.Duktape;
|
||||
|
||||
@ReactModule(name = JavaScriptSandboxModule.NAME)
|
||||
class JavaScriptSandboxModule extends ReactContextBaseJavaModule {
|
||||
public static final String NAME = "JavaScriptSandbox";
|
||||
|
||||
public JavaScriptSandboxModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates the given code in a Duktape VM.
|
||||
* @param code - The code that needs to evaluated.
|
||||
* @param promise - Resolved with the output in case of success or rejected with an exception
|
||||
* in case of failure.
|
||||
*/
|
||||
@ReactMethod
|
||||
public void evaluate(String code, Promise promise) {
|
||||
Duktape vm = Duktape.create();
|
||||
try {
|
||||
Object res = vm.evaluate(code);
|
||||
promise.resolve(res.toString());
|
||||
} catch (Throwable tr) {
|
||||
promise.reject(tr);
|
||||
} finally {
|
||||
vm.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,9 @@ public class JitsiMeet {
|
||||
}
|
||||
|
||||
public static void setDefaultConferenceOptions(JitsiMeetConferenceOptions options) {
|
||||
if (options != null && options.getRoom() != null) {
|
||||
throw new RuntimeException("'room' must be null in the default conference options");
|
||||
}
|
||||
defaultConferenceOptions = options;
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ public class JitsiMeetActivityDelegate {
|
||||
// https://github.com/facebook/react-native/blob/df4e67fe75d781d1eb264128cadf079989542755/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java#L512
|
||||
// Why this happens is a mystery wrapped in an enigma.
|
||||
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
|
||||
if (activity == reactContext.getCurrentActivity()) {
|
||||
if (reactContext != null && activity == reactContext.getCurrentActivity()) {
|
||||
reactInstanceManager.onHostPause(activity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,46 @@ public class JitsiMeetConferenceOptions implements Parcelable {
|
||||
*/
|
||||
private JitsiMeetUserInfo userInfo;
|
||||
|
||||
public URL getServerURL() {
|
||||
return serverURL;
|
||||
}
|
||||
|
||||
public String getRoom() {
|
||||
return room;
|
||||
}
|
||||
|
||||
public String getSubject() {
|
||||
return subject;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public Bundle getColorScheme() {
|
||||
return colorScheme;
|
||||
}
|
||||
|
||||
public Bundle getFeatureFlags() {
|
||||
return featureFlags;
|
||||
}
|
||||
|
||||
public boolean getAudioMuted() {
|
||||
return audioMuted;
|
||||
}
|
||||
|
||||
public boolean getAudioOnly() {
|
||||
return audioOnly;
|
||||
}
|
||||
|
||||
public boolean getVideoMuted() {
|
||||
return videoMuted;
|
||||
}
|
||||
|
||||
public JitsiMeetUserInfo getUserInfo() {
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class used to build the immutable {@link JitsiMeetConferenceOptions} object.
|
||||
*/
|
||||
|
||||
@@ -87,7 +87,7 @@ public class JitsiMeetOngoingConferenceService extends Service
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
final String action = intent.getAction();
|
||||
if (action.equals(Actions.START)) {
|
||||
if (Actions.START.equals(action)) {
|
||||
Notification notification = OngoingNotification.buildOngoingConferenceNotification();
|
||||
if (notification == null) {
|
||||
stopSelf();
|
||||
@@ -96,7 +96,7 @@ public class JitsiMeetOngoingConferenceService extends Service
|
||||
startForeground(OngoingNotification.NOTIFICATION_ID, notification);
|
||||
JitsiMeetLogger.i(TAG + " Service started");
|
||||
}
|
||||
} else if (action.equals(Actions.HANGUP)) {
|
||||
} else if (Actions.HANGUP.equals(action)) {
|
||||
JitsiMeetLogger.i(TAG + " Hangup requested");
|
||||
// Abort all ongoing calls
|
||||
if (AudioModeModule.useConnectionService()) {
|
||||
|
||||
@@ -29,13 +29,18 @@ import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
@ReactModule(name = RNConnectionService.NAME)
|
||||
class RNConnectionService
|
||||
extends ReactContextBaseJavaModule {
|
||||
class RNConnectionService extends ReactContextBaseJavaModule {
|
||||
|
||||
public static final String NAME = "ConnectionService";
|
||||
|
||||
private static final String TAG = ConnectionService.TAG;
|
||||
|
||||
/**
|
||||
* Handler for dealing with call state changes. We are acting as a proxy between ConnectionService
|
||||
* and other modules such as {@link AudioModeModule}.
|
||||
*/
|
||||
private CallAudioStateListener callAudioStateListener;
|
||||
|
||||
/**
|
||||
* Sets the audio route on all existing {@link android.telecom.Connection}s
|
||||
*
|
||||
@@ -75,7 +80,7 @@ class RNConnectionService
|
||||
String handle,
|
||||
boolean hasVideo,
|
||||
Promise promise) {
|
||||
JitsiMeetLogger.d("%d startCall UUID=%s, h=%s, v=%s",
|
||||
JitsiMeetLogger.d("%s startCall UUID=%s, h=%s, v=%s",
|
||||
TAG,
|
||||
callUUID,
|
||||
handle,
|
||||
@@ -144,9 +149,10 @@ class RNConnectionService
|
||||
* @param callUUID - the call's UUID.
|
||||
*/
|
||||
@ReactMethod
|
||||
public void reportConnectedOutgoingCall(String callUUID) {
|
||||
public void reportConnectedOutgoingCall(String callUUID, Promise promise) {
|
||||
JitsiMeetLogger.d(TAG + " reportConnectedOutgoingCall " + callUUID);
|
||||
ConnectionService.setConnectionActive(callUUID);
|
||||
promise.resolve(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -167,4 +173,28 @@ class RNConnectionService
|
||||
public void updateCall(String callUUID, ReadableMap callState) {
|
||||
ConnectionService.updateCall(callUUID, callState);
|
||||
}
|
||||
|
||||
public CallAudioStateListener getCallAudioStateListener() {
|
||||
return callAudioStateListener;
|
||||
}
|
||||
|
||||
public void setCallAudioStateListener(CallAudioStateListener callAudioStateListener) {
|
||||
this.callAudioStateListener = callAudioStateListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for call state changes. {@code ConnectionServiceImpl} will call this handler when the
|
||||
* call audio state changes.
|
||||
*
|
||||
* @param callAudioState The current call's audio state.
|
||||
*/
|
||||
void onCallAudioStateChange(android.telecom.CallAudioState callAudioState) {
|
||||
if (callAudioStateListener != null) {
|
||||
callAudioStateListener.onCallAudioStateChange(callAudioState);
|
||||
}
|
||||
}
|
||||
|
||||
interface CallAudioStateListener {
|
||||
void onCallAudioStateChange(android.telecom.CallAudioState callAudioState);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ class ReactInstanceManagerHolder {
|
||||
new AudioModeModule(reactContext),
|
||||
new DropboxModule(reactContext),
|
||||
new ExternalAPIModule(reactContext),
|
||||
new JavaScriptSandboxModule(reactContext),
|
||||
new LocaleDetector(reactContext),
|
||||
new LogBridgeModule(reactContext),
|
||||
new PictureInPictureModule(reactContext),
|
||||
@@ -192,7 +193,7 @@ class ReactInstanceManagerHolder {
|
||||
new com.calendarevents.CalendarEventsPackage(),
|
||||
new com.corbt.keepawake.KCKeepAwakePackage(),
|
||||
new com.facebook.react.shell.MainReactPackage(),
|
||||
new com.oblador.vectoricons.VectorIconsPackage(),
|
||||
new com.horcrux.svg.SvgPackage(),
|
||||
new com.ocetnik.timer.BackgroundTimerPackage(),
|
||||
new com.reactnativecommunity.asyncstorage.AsyncStoragePackage(),
|
||||
new com.reactnativecommunity.netinfo.NetInfoPackage(),
|
||||
|
||||
@@ -37,13 +37,13 @@ public abstract class JitsiMeetBaseLogHandler extends Timber.Tree {
|
||||
protected void log(int priority, @Nullable String tag, @NotNull String msg, @Nullable Throwable t) {
|
||||
String errmsg = Log.getStackTraceString(t);
|
||||
if (errmsg.isEmpty()) {
|
||||
doLog(priority, getTag(), msg);
|
||||
doLog(priority, getDefaultTag(), msg);
|
||||
} else {
|
||||
doLog(priority, getTag(), MessageFormat.format("{0}\n{1}", msg, errmsg));
|
||||
doLog(priority, getDefaultTag(), MessageFormat.format("{0}\n{1}", msg, errmsg));
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void doLog(int priority, @NotNull String tag, @NotNull String msg);
|
||||
|
||||
protected abstract String getTag();
|
||||
protected abstract String getDefaultTag();
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public class JitsiMeetDefaultLogHandler extends JitsiMeetBaseLogHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTag() {
|
||||
protected String getDefaultTag() {
|
||||
return TAG;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public class NAT64AddrInfoModule
|
||||
* The host for which the module wil try to resolve both IPv4 and IPv6
|
||||
* addresses in order to figure out the NAT64 prefix.
|
||||
*/
|
||||
private final static String HOST = "nat64.jitsi.net";
|
||||
private final static String HOST = "ipv4only.arpa";
|
||||
|
||||
/**
|
||||
* How long is the {@link NAT64AddrInfo} instance valid.
|
||||
|
||||
@@ -10,7 +10,7 @@ project(':react-native-community-async-storage').projectDir = new File(rootProje
|
||||
include ':react-native-community_netinfo'
|
||||
project(':react-native-community_netinfo').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/netinfo/android')
|
||||
include ':react-native-google-signin'
|
||||
project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-google-signin/android')
|
||||
project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/google-signin/android')
|
||||
include ':react-native-immersive'
|
||||
project(':react-native-immersive').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-immersive/android')
|
||||
include ':react-native-keep-awake'
|
||||
@@ -19,8 +19,8 @@ include ':react-native-linear-gradient'
|
||||
project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android')
|
||||
include ':react-native-sound'
|
||||
project(':react-native-sound').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-sound/android')
|
||||
include ':react-native-vector-icons'
|
||||
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')
|
||||
include ':react-native-svg'
|
||||
project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-svg/android')
|
||||
include ':react-native-webrtc'
|
||||
project(':react-native-webrtc').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webrtc/android')
|
||||
include ':react-native-webview'
|
||||
|
||||
@@ -104,7 +104,6 @@ import {
|
||||
trackRemoved
|
||||
} from './react/features/base/tracks';
|
||||
import { getJitsiMeetGlobalNS } from './react/features/base/util';
|
||||
import { addMessage } from './react/features/chat';
|
||||
import { showDesktopPicker } from './react/features/desktop-picker';
|
||||
import { appendSuffix } from './react/features/display-name';
|
||||
import {
|
||||
@@ -114,7 +113,6 @@ import {
|
||||
import { mediaPermissionPromptVisibilityChanged } from './react/features/overlay';
|
||||
import { suspendDetected } from './react/features/power-monitor';
|
||||
import { setSharedVideoStatus } from './react/features/shared-video';
|
||||
import { isButtonEnabled } from './react/features/toolbox';
|
||||
import { endpointMessageReceived } from './react/features/subtitles';
|
||||
|
||||
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||
@@ -244,8 +242,6 @@ class ConferenceConnector {
|
||||
this._handleConferenceJoined.bind(this));
|
||||
room.on(JitsiConferenceEvents.CONFERENCE_FAILED,
|
||||
this._onConferenceFailed.bind(this));
|
||||
room.on(JitsiConferenceEvents.CONFERENCE_ERROR,
|
||||
this._onConferenceError.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -348,31 +344,6 @@ class ConferenceConnector {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
_onConferenceError(err, ...params) {
|
||||
logger.error('CONFERENCE Error:', err, params);
|
||||
switch (err) {
|
||||
case JitsiConferenceErrors.CHAT_ERROR:
|
||||
logger.error('Chat error.', err);
|
||||
if (isButtonEnabled('chat') && !interfaceConfig.filmStripOnly) {
|
||||
const [ code, msg ] = params;
|
||||
|
||||
APP.store.dispatch(addMessage({
|
||||
hasRead: true,
|
||||
error: code,
|
||||
message: msg,
|
||||
messageType: 'error',
|
||||
timestamp: Date.now()
|
||||
}));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logger.error('Unknown error.', err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
28
config.js
28
config.js
@@ -1,16 +1,6 @@
|
||||
/* eslint-disable no-unused-vars, no-var */
|
||||
|
||||
var config = {
|
||||
// Configuration
|
||||
//
|
||||
|
||||
// Alternative location for the configuration.
|
||||
// configLocation: './config.json',
|
||||
|
||||
// Custom function which given the URL path should return a room name.
|
||||
// getroomnode: function (path) { return 'someprefixpossiblybasedonpath'; },
|
||||
|
||||
|
||||
// Connection
|
||||
//
|
||||
|
||||
@@ -60,6 +50,10 @@ var config = {
|
||||
|
||||
// Enables the test specific features consumed by jitsi-meet-torture
|
||||
// testMode: false
|
||||
|
||||
// Disables the auto-play behavior of *all* newly created video element.
|
||||
// This is useful when the client runs on a host with limited resources.
|
||||
// noAutoPlayVideo: false
|
||||
},
|
||||
|
||||
// Disables ICE/UDP by filtering out local and remote UDP candidates in
|
||||
@@ -123,10 +117,6 @@ var config = {
|
||||
// are requested again.
|
||||
// enableLayerSuspension: false,
|
||||
|
||||
// Suspend sending video if bandwidth estimation is too low. This may cause
|
||||
// problems with audio playback. Disabled until these are fixed.
|
||||
disableSuspendVideo: true,
|
||||
|
||||
// Every participant after the Nth will start video muted.
|
||||
// startVideoMuted: 10,
|
||||
|
||||
@@ -429,6 +419,16 @@ var config = {
|
||||
// the menu has option to flip the locally seen video for local presentations
|
||||
// disableLocalVideoFlip: false
|
||||
|
||||
// Deployment specific URLs.
|
||||
// deploymentUrls: {
|
||||
// // If specified a 'Help' button will be displayed in the overflow menu with a link to the specified URL for
|
||||
// // user documentation.
|
||||
// userDocumentationURL: 'https://docs.example.com/video-meetings.html',
|
||||
// // If specified a 'Download our apps' button will be displayed in the overflow menu with a link
|
||||
// // to the specified URL for an app download page.
|
||||
// downloadAppsUrl: 'https://docs.example.com/our-apps.html'
|
||||
// }
|
||||
|
||||
// List of undocumented settings used in jitsi-meet
|
||||
/**
|
||||
_immediateReloadThreshold
|
||||
|
||||
@@ -33,6 +33,10 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
.jitsi-icon svg {
|
||||
fill: white;
|
||||
}
|
||||
|
||||
/**
|
||||
* AtlasKitThemeProvider sets a background color on an app-wrapping div, thereby
|
||||
* preventing transparency in filmstrip-only mode. The selector chosen to
|
||||
|
||||
@@ -80,6 +80,28 @@
|
||||
}
|
||||
}
|
||||
|
||||
#chat-recipient {
|
||||
align-items: center;
|
||||
background-color: $chatPrivateMessageBackgroundColor;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
font-weight: 100;
|
||||
padding: 10px;
|
||||
|
||||
span {
|
||||
color: white;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
div {
|
||||
svg {
|
||||
cursor: pointer;
|
||||
fill: white
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chat-header {
|
||||
background-color: $chatHeaderBackgroundColor;
|
||||
height: 70px;
|
||||
@@ -111,6 +133,7 @@
|
||||
#chat-input {
|
||||
border-top: 1px solid $chatInputSeparatorColor;
|
||||
display: flex;
|
||||
padding: 5px 10px;
|
||||
|
||||
* {
|
||||
background-color: transparent;
|
||||
@@ -131,8 +154,7 @@
|
||||
box-shadow: none;
|
||||
color: white;
|
||||
font-size: 15px;
|
||||
line-height: 30px;
|
||||
padding: 5px;
|
||||
padding: 10px;
|
||||
overflow-y: auto;
|
||||
resize: none;
|
||||
width: 100%;
|
||||
@@ -162,6 +184,7 @@
|
||||
.display-name {
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
@@ -175,7 +198,6 @@
|
||||
color: white;
|
||||
margin-top: 3px;
|
||||
max-width: 100%;
|
||||
padding-bottom: 3px;
|
||||
position: relative;
|
||||
|
||||
&.localuser {
|
||||
@@ -196,6 +218,15 @@
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.privatemessagenotice {
|
||||
font-size: 11px;
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
.messagecontent {
|
||||
margin: 5px 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.smiley {
|
||||
@@ -228,6 +259,7 @@
|
||||
.smileys-panel {
|
||||
bottom: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: rgba(0, 0, 0, .6) !important;
|
||||
height: auto;
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
@@ -270,10 +302,6 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#usermsg::-webkit-input-placeholder {
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
#usermsg::-webkit-scrollbar-track-piece {
|
||||
background: #3a3a3a;
|
||||
}
|
||||
@@ -288,6 +316,10 @@
|
||||
.chatmessage {
|
||||
background-color: $chatLocalMessageBackgroundColor;
|
||||
border-radius: 6px 0px 6px 6px;
|
||||
|
||||
&.privatemessage {
|
||||
background-color: $chatPrivateMessageBackgroundColor;
|
||||
}
|
||||
}
|
||||
|
||||
.display-name {
|
||||
@@ -301,8 +333,9 @@
|
||||
|
||||
&.error {
|
||||
.chatmessage {
|
||||
background-color: $defaultWarningColor;
|
||||
border-radius: 0px;
|
||||
color: red;
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
.display-name {
|
||||
@@ -312,6 +345,25 @@
|
||||
|
||||
.chatmessage-wrapper {
|
||||
max-width: 100%;
|
||||
|
||||
.replywrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.messageactions {
|
||||
align-self: stretch;
|
||||
border-left: 1px solid $chatActionsSeparatorColor;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 5px;
|
||||
|
||||
.toolbox-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chatmessage {
|
||||
@@ -320,6 +372,9 @@
|
||||
display: inline-block;
|
||||
margin-top: 3px;
|
||||
color: white;
|
||||
padding: 8px;
|
||||
|
||||
&.privatemessage {
|
||||
background-color: $chatPrivateMessageBackgroundColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
235
css/_font.scss
235
css/_font.scss
@@ -1,235 +0,0 @@
|
||||
@font-face {
|
||||
font-family: 'jitsi';
|
||||
src: url('../fonts/jitsi.eot?icrce1');
|
||||
src: url('../fonts/jitsi.eot?icrce1#iefix') format('embedded-opentype'),
|
||||
url('../fonts/jitsi.ttf?icrce1') format('truetype'),
|
||||
url('../fonts/jitsi.woff?icrce1') format('woff'),
|
||||
url('../fonts/jitsi.svg?icrce1#jitsi') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
[class^="icon-"], [class*=" icon-"] {
|
||||
font-family: 'jitsi';
|
||||
speak: none;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
line-height: 1.22em;
|
||||
font-size: 1.22em;
|
||||
cursor: default;
|
||||
|
||||
/* Better Font Rendering =========== */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-cancel:before {
|
||||
content: "\e91c";
|
||||
}
|
||||
.icon-check:before {
|
||||
content: "\e91b";
|
||||
}
|
||||
.icon-send:before {
|
||||
content: "\e911";
|
||||
}
|
||||
.icon-blur-background:before {
|
||||
content: "\e90f";
|
||||
color: #a4b8d1;
|
||||
}
|
||||
.icon-speaker:before {
|
||||
content: "\e92d";
|
||||
}
|
||||
.icon-rec:before {
|
||||
content: "\e92b";
|
||||
}
|
||||
.icon-camera-take-picture:before {
|
||||
content: "\e92a";
|
||||
}
|
||||
.icon-AUD:before {
|
||||
content: "\e900";
|
||||
}
|
||||
.icon-HD:before {
|
||||
content: "\e927";
|
||||
}
|
||||
.icon-LD:before {
|
||||
content: "\e928";
|
||||
}
|
||||
.icon-SD:before {
|
||||
content: "\e929";
|
||||
}
|
||||
.icon-gsm-bars:before {
|
||||
content: "\e926";
|
||||
}
|
||||
.icon-info:before {
|
||||
content: "\e922";
|
||||
}
|
||||
.icon-mic-camera-combined:before {
|
||||
content: "\e903";
|
||||
}
|
||||
.icon-feedback:before {
|
||||
content: "\e91d";
|
||||
}
|
||||
.icon-hangup:before {
|
||||
content: "\e905";
|
||||
}
|
||||
.icon-chat:before {
|
||||
content: "\e906";
|
||||
}
|
||||
.icon-share-doc:before {
|
||||
content: "\e908";
|
||||
}
|
||||
.icon-kick:before {
|
||||
content: "\e904";
|
||||
}
|
||||
.icon-menu-up:before {
|
||||
content: "\e91f";
|
||||
}
|
||||
.icon-menu-down:before {
|
||||
content: "\e920";
|
||||
}
|
||||
.icon-full-screen:before {
|
||||
content: "\e90b";
|
||||
}
|
||||
.icon-exit-full-screen:before {
|
||||
content: "\e90c";
|
||||
}
|
||||
.icon-security:before {
|
||||
content: "\e90d";
|
||||
}
|
||||
.icon-security-locked:before {
|
||||
content: "\e90e";
|
||||
}
|
||||
.icon-microphone:before {
|
||||
content: "\e910";
|
||||
}
|
||||
.icon-mic-disabled:before {
|
||||
content: "\e912";
|
||||
}
|
||||
.icon-raised-hand:before {
|
||||
content: "\e91e";
|
||||
}
|
||||
.icon-link:before {
|
||||
content: "\e913";
|
||||
}
|
||||
.icon-shared-video:before {
|
||||
content: "\e914";
|
||||
}
|
||||
.icon-settings:before {
|
||||
content: "\e915";
|
||||
}
|
||||
.icon-star:before {
|
||||
content: "\e916";
|
||||
}
|
||||
.icon-switch-camera:before {
|
||||
content: "\e921";
|
||||
}
|
||||
.icon-share-desktop:before {
|
||||
content: "\e917";
|
||||
}
|
||||
.icon-camera:before {
|
||||
content: "\e918";
|
||||
}
|
||||
.icon-camera-disabled:before {
|
||||
content: "\e919";
|
||||
}
|
||||
.icon-volume:before {
|
||||
content: "\e91a";
|
||||
}
|
||||
.icon-presentation:before {
|
||||
content: "\e603";
|
||||
}
|
||||
.icon-visibility:before {
|
||||
content: "\e923";
|
||||
}
|
||||
.icon-visibility-off:before {
|
||||
content: "\e924";
|
||||
}
|
||||
.icon-enlarge:before {
|
||||
content: "\e90a";
|
||||
}
|
||||
.icon-signal_cellular_0:before {
|
||||
content: "\e901";
|
||||
}
|
||||
.icon-signal_cellular_1:before {
|
||||
content: "\e902";
|
||||
}
|
||||
.icon-signal_cellular_2:before {
|
||||
content: "\e907";
|
||||
}
|
||||
.icon-phone:before {
|
||||
content: "\e0cd";
|
||||
}
|
||||
.icon-radio_button_unchecked:before {
|
||||
content: "\e836";
|
||||
}
|
||||
.icon-radio_button_checked:before {
|
||||
content: "\e837";
|
||||
}
|
||||
.icon-search:before {
|
||||
content: "\e8b6";
|
||||
}
|
||||
.icon-chat-unread:before {
|
||||
content: "\e0b7";
|
||||
}
|
||||
.icon-closed_caption:before {
|
||||
content: "\e930";
|
||||
}
|
||||
.icon-tiles-many:before {
|
||||
content: "\e92e";
|
||||
}
|
||||
.icon-close:before {
|
||||
content: "\e5cd";
|
||||
}
|
||||
.icon-open_in_new:before {
|
||||
content: "\e89e";
|
||||
}
|
||||
.icon-restore:before {
|
||||
content: "\e8b3";
|
||||
}
|
||||
.icon-navigate_next:before {
|
||||
content: "\e409";
|
||||
}
|
||||
.icon-menu:before {
|
||||
content: "\e5d2";
|
||||
}
|
||||
.icon-arrow_back:before {
|
||||
content: "\e5c4";
|
||||
}
|
||||
.icon-public:before {
|
||||
content: "\e80b";
|
||||
}
|
||||
.icon-event_note:before {
|
||||
content: "\e616";
|
||||
}
|
||||
.icon-bluetooth:before {
|
||||
content: "\e1aa";
|
||||
}
|
||||
.icon-headset:before {
|
||||
content: "\e310";
|
||||
}
|
||||
.icon-phone-talk:before {
|
||||
content: "\e61d";
|
||||
}
|
||||
.icon-thumb-menu:before {
|
||||
content: "\e5d4";
|
||||
}
|
||||
.icon-ninja:before {
|
||||
content: "\e909";
|
||||
}
|
||||
.icon-invite:before {
|
||||
content: "\e145";
|
||||
}
|
||||
.icon-add:before {
|
||||
content: "\e146";
|
||||
}
|
||||
.icon-play:before {
|
||||
content: "\f04b";
|
||||
}
|
||||
.icon-stop:before {
|
||||
content: "\f04d";
|
||||
}
|
||||
.icon-dominant-speaker:before {
|
||||
content: "\f0a1";
|
||||
}
|
||||
66
css/_mini_toolbox.scss
Normal file
66
css/_mini_toolbox.scss
Normal file
@@ -0,0 +1,66 @@
|
||||
.filmstrip-toolbox,
|
||||
.always-on-top-toolbox {
|
||||
background-color: $newToolbarBackgroundColor;
|
||||
border-radius: 3px;
|
||||
display: flex;
|
||||
z-index: $toolbarZ;
|
||||
|
||||
.toolbox-icon {
|
||||
cursor: pointer;
|
||||
padding: 7px;
|
||||
|
||||
&.toggled {
|
||||
background: $AOTToolbarButtonToggleColor;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
cursor: initial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.always-on-top-toolbox {
|
||||
flex-direction: row;
|
||||
left: 50%;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
transform: translateX(-50%);
|
||||
|
||||
.toolbox-button {
|
||||
&:first-child {
|
||||
.toolbox-icon {
|
||||
border-top-left-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
svg {
|
||||
fill: $hangupColor;
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
.toolbox-icon {
|
||||
border-top-right-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.filmstrip-toolbox {
|
||||
flex-direction: column;
|
||||
|
||||
.toolbox-button {
|
||||
&:nth-child(1) {
|
||||
svg {
|
||||
fill: $hangupColor;
|
||||
}
|
||||
}
|
||||
|
||||
.toolbox-icon {
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
26
css/_participants-count.scss
Normal file
26
css/_participants-count.scss
Normal file
@@ -0,0 +1,26 @@
|
||||
.participants-count {
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
color: #5e6d7a;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
margin-left: 16px;
|
||||
padding: 4px 8px;
|
||||
pointer-events: auto;
|
||||
|
||||
&-number {
|
||||
margin-right: 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
&-icon {
|
||||
background: url('../images/user-groups.svg');
|
||||
background-repeat: no-repeat;
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
min-width: 75px;
|
||||
text-align: left;
|
||||
padding: 0px;
|
||||
width: 150px;
|
||||
width: 180px;
|
||||
white-space: nowrap;
|
||||
|
||||
&__item {
|
||||
@@ -87,6 +87,7 @@
|
||||
display: inline-block;
|
||||
min-width: 20px;
|
||||
height: 100%;
|
||||
padding-right: 10px;
|
||||
|
||||
> * {
|
||||
@include absoluteAligning();
|
||||
|
||||
1
css/_promotional-footer.scss
Normal file
1
css/_promotional-footer.scss
Normal file
@@ -0,0 +1 @@
|
||||
/** Insert custom CSS for any additional content in the promotional footer **/
|
||||
@@ -9,7 +9,7 @@
|
||||
text-align: center;
|
||||
font-size: 17px;
|
||||
color: #fff;
|
||||
z-index: $toolbarBackgroundZ;
|
||||
z-index: $zindex10;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
box-sizing: border-box;
|
||||
@@ -19,4 +19,8 @@
|
||||
&.visible {
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
&-text {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,8 +73,62 @@
|
||||
|
||||
.button-group-center {
|
||||
justify-content: center;
|
||||
.toolbox-icon {
|
||||
margin: 0px 4px;
|
||||
|
||||
.toolbox-button {
|
||||
|
||||
.toolbox-icon {
|
||||
background-color: #fff;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #d1dbe8;
|
||||
margin: 0px 4px;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
|
||||
&:hover {
|
||||
background-color: #daebfa;
|
||||
border: 1px solid #daebfa;
|
||||
}
|
||||
|
||||
&.toggled {
|
||||
background: #2a3a4b;
|
||||
border: 1px solid #5e6d7a;
|
||||
|
||||
svg {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #5e6d7a;
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled, .disabled & {
|
||||
cursor: initial;
|
||||
color: #fff;
|
||||
background-color: #a4b8d1;
|
||||
}
|
||||
|
||||
svg {
|
||||
fill: #5e6d7a;
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
.toolbox-icon {
|
||||
background-color: $hangupColor;
|
||||
border: 1px solid $hangupColor;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
|
||||
&:hover {
|
||||
background-color: $hangupColor;
|
||||
}
|
||||
|
||||
svg {
|
||||
fill: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,75 +136,6 @@
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
i {
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
font-size: inherit;
|
||||
height: 100%;
|
||||
line-height: inherit;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
i:hover {
|
||||
background: $newToolbarButtonHoverColor;
|
||||
}
|
||||
|
||||
i.toggled {
|
||||
background: $newToolbarButtonToggleColor;
|
||||
}
|
||||
|
||||
i.toggled:hover {
|
||||
background: $newToolbarButtonHoverColor;
|
||||
}
|
||||
|
||||
.icon-hangup {
|
||||
background-color: #e12d2d;
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
|
||||
&:hover {
|
||||
background-color: #e54b4b;
|
||||
}
|
||||
}
|
||||
i.disabled, .disabled i {
|
||||
cursor: initial !important;
|
||||
color: #fff !important;
|
||||
background-color: #a4b8d1 !important;
|
||||
}
|
||||
|
||||
.icon-mic-disabled, .icon-microphone, .icon-camera-disabled, .icon-camera {
|
||||
background-color: #fff;
|
||||
color: #5e6d7a;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #d1dbe8;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
|
||||
&:hover {
|
||||
background-color: #daebfa;
|
||||
border: 1px solid #daebfa;
|
||||
}
|
||||
|
||||
&.toggled {
|
||||
background: #2a3a4b;
|
||||
color: #fff;
|
||||
border: 1px solid #5e6d7a;
|
||||
|
||||
&:hover {
|
||||
background-color: #5e6d7a;
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled, .disabled & {
|
||||
cursor: initial;
|
||||
color: #fff;
|
||||
background-color: #a4b8d1;
|
||||
}
|
||||
}
|
||||
|
||||
.overflow-menu {
|
||||
font-size: 1.2em;
|
||||
list-style-type: none;
|
||||
@@ -191,14 +176,6 @@
|
||||
cursor: initial;
|
||||
color: #3b475c;
|
||||
}
|
||||
|
||||
i.toggled {
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
i.toggled:hover {
|
||||
background: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.beta-tag {
|
||||
@@ -227,6 +204,10 @@
|
||||
max-width: 24px;
|
||||
max-height: 24px;
|
||||
}
|
||||
|
||||
svg {
|
||||
fill: #B8C7E0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.profile-text {
|
||||
@@ -265,104 +246,30 @@
|
||||
}
|
||||
|
||||
.toolbox-icon {
|
||||
height: $newToolbarSize;
|
||||
display: flex;
|
||||
border-radius: 5px;
|
||||
flex-direction: column;
|
||||
font-size: 24px;
|
||||
height: $newToolbarSize;
|
||||
justify-content: center;
|
||||
width: $newToolbarSize;
|
||||
|
||||
&:hover, &.toggled {
|
||||
background: $newToolbarButtonHoverColor;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
cursor: initial !important;
|
||||
background-color: #a4b8d1 !important;
|
||||
|
||||
svg {
|
||||
fill: #fff !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.always-on-top-toolbox,
|
||||
.filmstrip-toolbox {
|
||||
background-color: $newToolbarBackgroundColor;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: $toolbarZ;
|
||||
|
||||
i {
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
}
|
||||
|
||||
i:hover {
|
||||
background-color: $AOTToolbarButtonHoverColor;
|
||||
}
|
||||
|
||||
i.toggled {
|
||||
background: $AOTToolbarButtonToggleColor;
|
||||
}
|
||||
|
||||
i.toggled:hover:not(.disabled) {
|
||||
background-color: $AOTToolbarButtonHoverColor;
|
||||
}
|
||||
|
||||
.icon-hangup {
|
||||
color: $hangupColor;
|
||||
}
|
||||
|
||||
.toolbox-button {
|
||||
color: $toolbarButtonColor;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.always-on-top-toolbox {
|
||||
flex-direction: row;
|
||||
left: 50%;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
transform: translateX(-50%);
|
||||
z-index: $toolbarZ;
|
||||
|
||||
i {
|
||||
font-size: $newToolbarFontSize;
|
||||
height: $newToolbarSize;
|
||||
line-height: $newToolbarSize;
|
||||
width: $newToolbarSize;
|
||||
}
|
||||
|
||||
.icon-hangup {
|
||||
font-size: $newToolbarHangupFontSize;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
cursor: initial;
|
||||
}
|
||||
|
||||
.toolbox-button:first-child i {
|
||||
border-top-left-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
}
|
||||
|
||||
.toolbox-button:last-child i {
|
||||
border-top-right-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.filmstrip-toolbox {
|
||||
i {
|
||||
font-size: 1.9em;
|
||||
height: 37px;
|
||||
line-height: 37px;
|
||||
width: 37px;
|
||||
}
|
||||
|
||||
.toolbox-button:first-child i {
|
||||
border-top-left-radius: 3px;
|
||||
border-top-right-radius: 3px;
|
||||
}
|
||||
|
||||
.toolbox-button:last-child i {
|
||||
border-bottom-left-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* START of fade in animation for main toolbar
|
||||
*/
|
||||
|
||||
@@ -28,6 +28,7 @@ $defaultColor: #F1F1F1;
|
||||
$defaultSideBarFontColor: #44A5FF;
|
||||
$defaultSemiDarkColor: #ACACAC;
|
||||
$defaultDarkColor: #2b3d5c;
|
||||
$defaultWarningColor: rgb(215, 121, 118);
|
||||
|
||||
/**
|
||||
* Toolbar
|
||||
@@ -85,10 +86,12 @@ $modalTextColor: #333;
|
||||
/**
|
||||
* Chat
|
||||
*/
|
||||
$chatActionsSeparatorColor: rgb(173, 105, 112);
|
||||
$chatHeaderBackgroundColor: rgba(42, 58, 75, 0.9);
|
||||
$chatInputSeparatorColor: #A4B8D1;
|
||||
$chatLocalMessageBackgroundColor: rgba(26, 108, 180, 1);
|
||||
$chatRemoteMessageBackgroundColor: rgba(240, 243, 247, 0.15);
|
||||
$chatLocalMessageBackgroundColor: rgb(4, 98, 178);
|
||||
$chatPrivateMessageBackgroundColor: rgb(153, 69, 77);
|
||||
$chatRemoteMessageBackgroundColor: rgb(86, 101, 114);
|
||||
$sidebarWidth: 375px;
|
||||
|
||||
/**
|
||||
@@ -163,11 +166,93 @@ $watermarkHeight: 74px;
|
||||
*/
|
||||
$welcomePageDescriptionColor: #fff;
|
||||
$welcomePageFontFamily: inherit;
|
||||
$welcomePageHeaderBackground: linear-gradient(-90deg, #1251AE 0%, #0074FF 50%, #1251AE 100%);
|
||||
$welcomePageBackground: linear-gradient(-90deg, #1251AE 0%, #0074FF 50%, #1251AE 100%);
|
||||
$welcomePageTitleColor: #fff;
|
||||
|
||||
$welcomePageHeaderBackground: none;
|
||||
$welcomePageHeaderBackgroundSmall: none;
|
||||
$welcomePageHeaderBackgroundPosition: none;
|
||||
$welcomePageHeaderBackgroundRepeat: none;
|
||||
$welcomePageHeaderBackgroundSize: none;
|
||||
$welcomePageHeaderPaddingBottom: 0px;
|
||||
|
||||
$welcomePageHeaderTextMarginTop: 35px;
|
||||
$welcomePageHeaderTextMarginBottom: 35px;
|
||||
|
||||
$welcomePageHeaderTextTitleMarginBottom: 16px;
|
||||
$welcomePageHeaderTextTitleFontSize: 2.5rem;
|
||||
$welcomePageHeaderTextTitleFontWeight: 500;
|
||||
$welcomePageHeaderTextTitleLineHeight: 1.18;
|
||||
$welcomePageHeaderTextTitleOpacity: 1;
|
||||
|
||||
$welcomePageHeaderTextDescriptionDisplay: inherit;
|
||||
$welcomePageHeaderTextDescriptionFontSize: 1rem;
|
||||
$welcomePageHeaderTextDescriptionFontWeight: 400;
|
||||
$welcomePageHeaderTextDescriptionLineHeight: 24px;
|
||||
$welcomePageHeaderTextDescriptionMarginBottom: 20px;
|
||||
$welcomePageHeaderTextDescriptionAlignSelf: inherit;
|
||||
|
||||
$welcomePageEnterRoomWidth: 680px;
|
||||
$welcomePageEnterRoomPadding: 25px 30px;
|
||||
$welcomePageEnterRoomBorderRadius: 0px;
|
||||
|
||||
$welcomePageEnterRoomInputContainerPadding: 0 8px 5px 0px;
|
||||
$welcomePageEnterRoomInputContainerBorderWidth: 0px 0px 2px 0px;
|
||||
$welcomePageEnterRoomInputContainerBorderStyle: solid;
|
||||
$welcomePageEnterRoomInputContainerBorderImage: linear-gradient(to right, #dee1e6, #fff) 1;
|
||||
|
||||
$welcomePageEnterRoomTitleDisplay: inherit;
|
||||
|
||||
$welcomePageTabContainerDisplay: flex;
|
||||
$welcomePageTabContentDisplay: inherit;
|
||||
$welcomePageTabButtonsDisplay: flex;
|
||||
$welcomePageTabDisplay: block;
|
||||
|
||||
$welcomePageButtonWidth: 51px;
|
||||
$welcomePageButtonMinWidth: inherit;
|
||||
$welcomePageButtonFontSize: 14px;
|
||||
$welcomePageButtonHeight: 35px;
|
||||
$welcomePageButtonFontWeight: inherit;
|
||||
$welcomePageButtonBorderRadius: 4px;
|
||||
$welcomePageButtonLineHeight: 35px;
|
||||
|
||||
/**
|
||||
* Deep-linking page variables.
|
||||
*/
|
||||
$deepLinkingMobileLogoHeight: 40px;
|
||||
|
||||
$deepLinkingMobileHeaderBackground: #f1f2f5;
|
||||
|
||||
$deepLinkingMobileLinkColor: inherit;
|
||||
$deepLinkingMobileTextFontSize: inherit;
|
||||
$deepLinkingMobileTextLineHeight: inherit;
|
||||
|
||||
$deepLinkingDialInConferenceIdMargin: 10px 0 10px 0;
|
||||
$deepLinkingDialInConferenceIdPadding: inherit;
|
||||
$deepLinkingDialInConferenceIdBackgroundColor: inherit;
|
||||
$deepLinkingDialInConferenceIdBorderRadius: inherit;
|
||||
|
||||
$deepLinkingDialInConferenceNameFontSize: inherit;
|
||||
$deepLinkingDialInConferenceNameLineHeight: inherit;
|
||||
$deepLinkingDialInConferenceNameMarginBottom: none;
|
||||
$deepLinkingDialInConferenceNameFontWeight: inherit;
|
||||
|
||||
$deepLinkingDialInConferenceDescriptionFontSize: 0.8em;
|
||||
$deepLinkingDialInConferenceDescriptionLineHeight: inherit;
|
||||
$deepLinkingDialInConferenceDescriptionMarginBottom: none;
|
||||
|
||||
$deepLinkingDialInConferencePinFontSize: inherit;
|
||||
$deepLinkingDialInConferencePinLineHeight: inherit;
|
||||
|
||||
$depLinkingMobileHrefLineHeight: 2.2857142857142856em;
|
||||
$deepLinkingMobileHrefFontWeight: bolder;
|
||||
$deepLinkingMobileHrefFontSize: inherit;
|
||||
|
||||
$deepLinkingMobileButtonHeight: 2.2857142857142856em;
|
||||
$deepLinkingMobileButtonLineHeight: 2.2857142857142856em;
|
||||
$deepLinkingMobileButtonMargin: 18px auto 10px;
|
||||
$deepLinkingMobileButtonWidth: auto;
|
||||
$deepLinkingMobileButtonFontWeight: bold;
|
||||
$deepLinkingMobileButtonFontSize: inherit;
|
||||
|
||||
$primaryDeepLinkingMobileButtonBorderRadius: inherit;
|
||||
|
||||
@@ -344,8 +344,11 @@
|
||||
/**
|
||||
* Toolbar icon internal i elements (font icons).
|
||||
*/
|
||||
.toolbar-icon>i {
|
||||
line-height: $thumbnailToolbarHeight;
|
||||
.toolbar-icon>div {
|
||||
height: $thumbnailToolbarHeight;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,7 @@ body.welcome-page {
|
||||
}
|
||||
|
||||
.welcome {
|
||||
background-image: $welcomePageHeaderBackground;
|
||||
background-image: $welcomePageBackground;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-family: $welcomePageFontFamily;
|
||||
@@ -13,6 +13,11 @@ body.welcome-page {
|
||||
position: relative;
|
||||
|
||||
.header {
|
||||
background-image: $welcomePageHeaderBackground;
|
||||
background-position: $welcomePageHeaderBackgroundPosition;
|
||||
background-repeat: $welcomePageHeaderBackgroundRepeat;
|
||||
background-size: $welcomePageHeaderBackgroundSize;
|
||||
padding-bottom: $welcomePageHeaderPaddingBottom;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -24,8 +29,8 @@ body.welcome-page {
|
||||
.header-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: $watermarkHeight + 35;
|
||||
margin-bottom: 35px;
|
||||
margin-top: $watermarkHeight + $welcomePageHeaderTextMarginTop;
|
||||
margin-bottom: $welcomePageHeaderTextMarginBottom;
|
||||
max-width: calc(100% - 40px);
|
||||
width: 650px;
|
||||
z-index: $zindex2;
|
||||
@@ -33,41 +38,45 @@ body.welcome-page {
|
||||
|
||||
.header-text-title {
|
||||
color: $welcomePageTitleColor;
|
||||
font-size: 2.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.18;
|
||||
margin-bottom: 16px;
|
||||
font-size: $welcomePageHeaderTextTitleFontSize;
|
||||
font-weight: $welcomePageHeaderTextTitleFontWeight;
|
||||
line-height: $welcomePageHeaderTextTitleLineHeight;
|
||||
margin-bottom: $welcomePageHeaderTextTitleMarginBottom;
|
||||
opacity: $welcomePageHeaderTextTitleOpacity;
|
||||
}
|
||||
|
||||
.header-text-description {
|
||||
display: $welcomePageHeaderTextDescriptionDisplay;
|
||||
color: $welcomePageDescriptionColor;
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
margin-bottom: 20px;
|
||||
font-size: $welcomePageHeaderTextDescriptionFontSize;
|
||||
font-weight: $welcomePageHeaderTextDescriptionFontWeight;
|
||||
line-height: $welcomePageHeaderTextDescriptionLineHeight;
|
||||
margin-bottom: $welcomePageHeaderTextDescriptionMarginBottom;
|
||||
align-self: $welcomePageHeaderTextDescriptionAlignSelf;
|
||||
}
|
||||
|
||||
#enter_room {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
max-width: calc(100% - 40px);
|
||||
width: 680px;
|
||||
width: $welcomePageEnterRoomWidth;
|
||||
z-index: $zindex2;
|
||||
background-color: #fff;
|
||||
padding: 25px 30px;
|
||||
padding: $welcomePageEnterRoomPadding;
|
||||
border-radius: $welcomePageEnterRoomBorderRadius;
|
||||
|
||||
.enter-room-input-container {
|
||||
width: 100%;
|
||||
padding-right: 8px;
|
||||
padding-bottom: 5px;
|
||||
padding: $welcomePageEnterRoomInputContainerPadding;
|
||||
text-align: left;
|
||||
color: #253858;
|
||||
height: fit-content;
|
||||
border-width: 0px 0px 2px 0px;
|
||||
border-style: solid;
|
||||
border-image: linear-gradient(to right, #dee1e6, #fff) 1;
|
||||
border-width: $welcomePageEnterRoomInputContainerBorderWidth;
|
||||
border-style: $welcomePageEnterRoomInputContainerBorderStyle;
|
||||
border-image: $welcomePageEnterRoomInputContainerBorderImage;
|
||||
|
||||
.enter-room-title {
|
||||
display: $welcomePageEnterRoomTitleDisplay;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
padding-bottom: 5px;
|
||||
@@ -94,10 +103,11 @@ body.welcome-page {
|
||||
min-height: 354px;
|
||||
width: 710px;
|
||||
background: #75A7E7;
|
||||
display: flex;
|
||||
display: $welcomePageTabContainerDisplay;
|
||||
flex-direction: column;
|
||||
|
||||
.tab-content{
|
||||
display: $welcomePageTabContentDisplay;
|
||||
margin: 5px 0px;
|
||||
overflow: hidden;
|
||||
flex-grow: 1;
|
||||
@@ -111,13 +121,14 @@ body.welcome-page {
|
||||
.tab-buttons {
|
||||
font-size: 18px;
|
||||
color: #FFFFFF;
|
||||
display: flex;
|
||||
display: $welcomePageTabButtonsDisplay;
|
||||
flex-grow: 0;
|
||||
flex-direction: row;
|
||||
min-height: 54px;
|
||||
width: 100%;
|
||||
|
||||
.tab {
|
||||
display: $welcomePageTabDisplay;
|
||||
text-align: center;
|
||||
background: rgba(9,30,66,0.37);
|
||||
height: 55px;
|
||||
@@ -138,15 +149,17 @@ body.welcome-page {
|
||||
}
|
||||
|
||||
.welcome-page-button {
|
||||
width: 51px;
|
||||
height: 35px;
|
||||
font-size: 14px;
|
||||
width: $welcomePageButtonWidth;
|
||||
min-width: $welcomePageButtonMinWidth;
|
||||
height: $welcomePageButtonHeight;
|
||||
font-size: $welcomePageButtonFontSize;
|
||||
font-weight: $welcomePageButtonFontWeight;
|
||||
background: #0074E0;
|
||||
border-radius: 4px;
|
||||
border-radius: $welcomePageButtonBorderRadius;
|
||||
color: #FFFFFF;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
line-height: 35px;
|
||||
line-height: $welcomePageButtonLineHeight;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
1
css/_welcome_page_settings_toolbar.scss
Normal file
1
css/_welcome_page_settings_toolbar.scss
Normal file
@@ -0,0 +1 @@
|
||||
/** Insert custom CSS for any additional content in the welcome page settings toolbar **/
|
||||
@@ -19,7 +19,8 @@
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none
|
||||
text-decoration: none;
|
||||
color: $deepLinkingMobileLinkColor;
|
||||
}
|
||||
|
||||
&__body {
|
||||
@@ -41,6 +42,8 @@
|
||||
|
||||
&__text {
|
||||
font-weight: bolder;
|
||||
font-size: $deepLinkingMobileTextFontSize;
|
||||
line-height: $deepLinkingMobileTextLineHeight;
|
||||
padding: 10px 10px 0px 10px;
|
||||
}
|
||||
|
||||
@@ -65,11 +68,28 @@
|
||||
}
|
||||
|
||||
.dial-in-conference-id {
|
||||
margin: 10px 0 10px 0;
|
||||
margin: $deepLinkingDialInConferenceIdMargin;
|
||||
padding: $deepLinkingDialInConferenceIdPadding;
|
||||
background-color: $deepLinkingDialInConferenceIdBackgroundColor;
|
||||
border-radius: $deepLinkingDialInConferenceIdBorderRadius;
|
||||
}
|
||||
|
||||
.dial-in-conference-name {
|
||||
font-size: $deepLinkingDialInConferenceNameFontSize;
|
||||
line-height: $deepLinkingDialInConferenceNameLineHeight;
|
||||
margin-bottom: $deepLinkingDialInConferenceNameMarginBottom;
|
||||
font-weight: $deepLinkingDialInConferenceNameFontWeight;
|
||||
}
|
||||
|
||||
.dial-in-conference-description {
|
||||
font-size: 0.8em;
|
||||
font-size: $deepLinkingDialInConferenceDescriptionFontSize;
|
||||
line-height: $deepLinkingDialInConferenceDescriptionLineHeight;
|
||||
margin-bottom: $deepLinkingDialInConferenceDescriptionMarginBottom;
|
||||
}
|
||||
|
||||
.dial-in-conference-pin {
|
||||
font-size: $deepLinkingDialInConferencePinFontSize;
|
||||
line-height: $deepLinkingDialInConferencePinLineHeight;
|
||||
}
|
||||
|
||||
.toll-free-list {
|
||||
@@ -88,25 +108,27 @@
|
||||
|
||||
&__href {
|
||||
height: 2.2857142857142856em;
|
||||
line-height: 2.2857142857142856em;
|
||||
line-height: $depLinkingMobileHrefLineHeight;
|
||||
margin: 18px auto 20px;
|
||||
max-width: 300px;
|
||||
width: auto;
|
||||
font-weight: bolder;
|
||||
font-weight: $deepLinkingMobileHrefFontWeight;
|
||||
font-size: $deepLinkingMobileHrefFontSize;
|
||||
}
|
||||
|
||||
&__button {
|
||||
border: 0;
|
||||
height: 2.2857142857142856em;
|
||||
line-height: 2.2857142857142856em;
|
||||
margin: 18px auto 10px;
|
||||
height: $deepLinkingMobileButtonHeight;
|
||||
line-height: $deepLinkingMobileButtonLineHeight;
|
||||
margin: $deepLinkingMobileButtonMargin;
|
||||
padding: 0px 10px 0px 10px;
|
||||
max-width: 300px;
|
||||
width: auto;
|
||||
width: $deepLinkingMobileButtonWidth;
|
||||
@include border-radius(3px);
|
||||
background-color: $unsupportedBrowserButtonBgColor;
|
||||
color: #505F79;
|
||||
font-weight: bold;
|
||||
font-weight: $deepLinkingMobileButtonFontWeight;
|
||||
font-size: $deepLinkingMobileButtonFontSize;
|
||||
|
||||
&:active {
|
||||
background-color: $unsupportedBrowserButtonBgColor;
|
||||
@@ -115,7 +137,7 @@
|
||||
&_primary {
|
||||
background-color: $primaryUnsupportedBrowserButtonBgColor;
|
||||
color: #FFFFFF;
|
||||
|
||||
border-radius: $primaryDeepLinkingMobileButtonBorderRadius;
|
||||
&:active {
|
||||
background-color: $primaryUnsupportedBrowserButtonBgColor;
|
||||
}
|
||||
|
||||
@@ -23,12 +23,6 @@ $flagsImagePath: "../images/";
|
||||
@import "../node_modules/bc-css-flags/dist/css/bc-css-flags.scss";
|
||||
/* Flags END */
|
||||
|
||||
/* Fonts BEGIN */
|
||||
|
||||
@import 'font';
|
||||
|
||||
/* Fonts END */
|
||||
|
||||
/* Modules BEGIN */
|
||||
|
||||
@import 'aui_reset';
|
||||
@@ -38,6 +32,7 @@ $flagsImagePath: "../images/";
|
||||
@import 'overlay/overlay';
|
||||
@import 'inlay';
|
||||
@import 'reload_overlay/reload_overlay';
|
||||
@import 'mini_toolbox';
|
||||
@import 'modals/desktop-picker/desktop-picker';
|
||||
@import 'modals/device-selection/device-selection';
|
||||
@import 'modals/dialog';
|
||||
@@ -50,6 +45,7 @@ $flagsImagePath: "../images/";
|
||||
@import 'videolayout_default';
|
||||
@import 'notice';
|
||||
@import 'subject';
|
||||
@import 'participants-count';
|
||||
@import 'popup_menu';
|
||||
@import 'recording';
|
||||
@import 'login_menu';
|
||||
@@ -57,6 +53,7 @@ $flagsImagePath: "../images/";
|
||||
@import 'ringing/ringing';
|
||||
@import 'welcome_page';
|
||||
@import 'welcome_page_content';
|
||||
@import 'welcome_page_settings_toolbar';
|
||||
@import 'toolbars';
|
||||
@import 'jquery.contextMenu';
|
||||
@import 'keyboard-shortcuts';
|
||||
@@ -87,5 +84,6 @@ $flagsImagePath: "../images/";
|
||||
@import 'third-party-branding/google';
|
||||
@import 'third-party-branding/microsoft';
|
||||
@import 'avatar';
|
||||
@import 'promotional-footer';
|
||||
|
||||
/* Modules END */
|
||||
|
||||
@@ -63,6 +63,8 @@
|
||||
width: -webkit-max-content;
|
||||
word-break: break-all;
|
||||
max-width: 400px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.info-dialog-dial-in {
|
||||
@@ -86,6 +88,15 @@
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
.info-dialog-url-icon {
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
|
||||
svg {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.info-dialog-title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
@@ -214,4 +225,10 @@
|
||||
-moz-user-select: text;
|
||||
-webkit-user-select: text;
|
||||
}
|
||||
|
||||
.info-dialog-url-text-unselectable {
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
### Adding an icon to the font file (e.g. for the floating menu)
|
||||
1. Go to https://icomoon.io/app/
|
||||
2. Go to "Manage Projects" from the menu on the top left.
|
||||
3. Use "Import project" and select <code>fonts/selection.json</code> from Jitsi Meet.
|
||||
4. Click "load".
|
||||
5. Add the new icons using the "Add icons from library" button...
|
||||
6. Go to "generate font" and make sure the identifiers for the new icons are correct.
|
||||
7. Download the result in a zip file using the "download" button.
|
||||
8. Copy <code>selection.json</code> and <code>fonts/jitsi.*</code> from the zip file to <code>fonts/</code> in Jitsi Meet
|
||||
9. Copy the class for the new icon from <code>style.css</code> in the zip file to <code>css/_font.scss</code> in Jitsi Meet (do *not* copy the whole file)
|
||||
|
||||
Sample commit: https://github.com/jitsi/jitsi-meet/commit/68bc819b89aec12364fcf07b81efa83a1900eed6
|
||||
@@ -19,29 +19,37 @@ server {
|
||||
ssl_certificate_key /etc/jitsi/meet/jitsi-meet.example.com.key;
|
||||
|
||||
root /usr/share/jitsi-meet;
|
||||
ssi on;
|
||||
index index.html index.htm;
|
||||
error_page 404 /static/404.html;
|
||||
|
||||
location /config.js {
|
||||
location = /config.js {
|
||||
alias /etc/jitsi/meet/jitsi-meet.example.com-config.js;
|
||||
}
|
||||
|
||||
location /external_api.js {
|
||||
location = /external_api.js {
|
||||
alias /usr/share/jitsi-meet/libs/external_api.min.js;
|
||||
}
|
||||
|
||||
location ~ ^/([a-zA-Z0-9=\?]+)$ {
|
||||
rewrite ^/(.*)$ / break;
|
||||
}
|
||||
|
||||
location / {
|
||||
ssi on;
|
||||
#ensure all static content can always be found first
|
||||
location ~ ^/(libs|css|static|images|fonts|lang|sounds|connection_optimization|.well-known)/(.*)$
|
||||
{
|
||||
add_header 'Access-Control-Allow-Origin' '*';
|
||||
alias /usr/share/jitsi-meet/$1/$2;
|
||||
}
|
||||
|
||||
# BOSH
|
||||
location /http-bind {
|
||||
location = /http-bind {
|
||||
proxy_pass http://localhost:5280/http-bind;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header Host $http_host;
|
||||
}
|
||||
|
||||
location ~ ^/([^?&:’“]+)$ {
|
||||
try_files $uri @root_path;
|
||||
}
|
||||
|
||||
location @root_path {
|
||||
rewrite ^/(.*)$ / break;
|
||||
}
|
||||
}
|
||||
|
||||
78
doc/development.md
Normal file
78
doc/development.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Developing Jitsi Meet
|
||||
|
||||
## Building the sources
|
||||
|
||||
Node.js >= 10 and npm >= 6 are required.
|
||||
|
||||
On Debian/Ubuntu systems, the required packages can be installed with:
|
||||
```
|
||||
sudo apt-get install npm nodejs
|
||||
cd jitsi-meet
|
||||
npm install
|
||||
```
|
||||
|
||||
To build the Jitsi Meet application, just type
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
### Working with the library sources (lib-jitsi-meet)
|
||||
|
||||
By default the library is build from its git repository sources. The default dependency path in package.json is :
|
||||
```json
|
||||
"lib-jitsi-meet": "jitsi/lib-jitsi-meet",
|
||||
```
|
||||
|
||||
To work with local copy you must change the path to:
|
||||
```json
|
||||
"lib-jitsi-meet": "file:///Users/name/local-lib-jitsi-meet-copy",
|
||||
```
|
||||
|
||||
To make the project you must force it to take the sources as 'npm update':
|
||||
```
|
||||
npm install lib-jitsi-meet --force && make
|
||||
```
|
||||
|
||||
Or if you are making only changes to the library:
|
||||
```
|
||||
npm install lib-jitsi-meet --force && make deploy-lib-jitsi-meet
|
||||
```
|
||||
|
||||
Alternative way is to use [npm link](https://docs.npmjs.com/cli/link).
|
||||
It allows to link `lib-jitsi-meet` dependency to local source in few steps:
|
||||
|
||||
```bash
|
||||
cd lib-jitsi-meet
|
||||
|
||||
#### create global symlink for lib-jitsi-meet package
|
||||
npm link
|
||||
|
||||
cd ../jitsi-meet
|
||||
|
||||
#### create symlink from the local node_modules folder to the global lib-jitsi-meet symlink
|
||||
npm link lib-jitsi-meet
|
||||
```
|
||||
|
||||
After changes in local `lib-jitsi-meet` repository, you can rebuild it with `npm run install` and your `jitsi-meet` repository will use that modified library.
|
||||
Note: when using node version 4.x, the make file of jitsi-meet do npm update which will delete the link. It is no longer the case with version 6.x.
|
||||
|
||||
If you do not want to use local repository anymore you should run
|
||||
```bash
|
||||
cd jitsi-meet
|
||||
npm unlink lib-jitsi-meet
|
||||
npm install
|
||||
```
|
||||
### Running with webpack-dev-server for development
|
||||
|
||||
Use it at the CLI, type
|
||||
```
|
||||
make dev
|
||||
```
|
||||
|
||||
By default the backend deployment used is `beta.meet.jit.si`. You can point the Jitsi-Meet app at a different backend by using a proxy server. To do this, set the WEBPACK_DEV_SERVER_PROXY_TARGET variable:
|
||||
```
|
||||
export WEBPACK_DEV_SERVER_PROXY_TARGET=https://your-example-server.com
|
||||
make dev
|
||||
```
|
||||
|
||||
The app should be running at https://localhost:8080/
|
||||
@@ -0,0 +1,14 @@
|
||||
var subdomain = "<!--# echo var="subdomain" default="" -->";
|
||||
if (subdomain) {
|
||||
subdomain = subdomain.substr(0,subdomain.length-1).split('.').join('_').toLowerCase() + '.';
|
||||
}
|
||||
|
||||
var config = {
|
||||
hosts: {
|
||||
domain: 'jitsi.example.com',
|
||||
muc: 'conference.'+subdomain+'jitsi.example.com', // FIXME: use XEP-0030
|
||||
focus: 'focus.jitsi.example.com',
|
||||
},
|
||||
useNicks: false,
|
||||
bosh: '//jitsi.example.com/http-bind' // FIXME: use xep-0156 for that
|
||||
};
|
||||
@@ -0,0 +1,67 @@
|
||||
server {
|
||||
listen 80;
|
||||
|
||||
server_name jitsi.example.com;
|
||||
# set the root
|
||||
root /srv/jitsi.example.com;
|
||||
# ssi on with javascript for multidomain variables in config.js
|
||||
ssi on;
|
||||
ssi_types application/x-javascript application/javascript;
|
||||
index index.html;
|
||||
set $prefix "";
|
||||
|
||||
|
||||
# BOSH
|
||||
location /http-bind {
|
||||
proxy_pass http://localhost:5280/http-bind;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header Host $http_host;
|
||||
}
|
||||
|
||||
# xmpp websockets
|
||||
location /xmpp-websocket {
|
||||
proxy_pass http://localhost:5280/xmpp-websocket;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
tcp_nodelay on;
|
||||
}
|
||||
|
||||
location ~ ^/([^/?&:'"]+)$ {
|
||||
try_files $uri @root_path;
|
||||
}
|
||||
|
||||
location @root_path {
|
||||
rewrite ^/(.*)$ / break;
|
||||
}
|
||||
|
||||
location / {
|
||||
ssi on;
|
||||
}
|
||||
|
||||
location ~ ^/([^/?&:'"]+)/config.js$
|
||||
{
|
||||
set $subdomain "$1.";
|
||||
set $subdir "$1/";
|
||||
|
||||
alias /etc/jitsi/meet/{{jitsi_meet_domain_name}}-config.js;
|
||||
}
|
||||
|
||||
#Anything that didn't match above, and isn't a real file, assume it's a room name and redirect to /
|
||||
location ~ ^/([^/?&:'"]+)/(.*)$ {
|
||||
set $subdomain "$1.";
|
||||
set $subdir "$1/";
|
||||
rewrite ^/([^/?&:'"]+)/(.*)$ /$2;
|
||||
}
|
||||
|
||||
# BOSH for subdomains
|
||||
location ~ ^/([^/?&:'"]+)/http-bind {
|
||||
set $subdomain "$1.";
|
||||
set $subdir "$1/";
|
||||
set $prefix "$1";
|
||||
|
||||
rewrite ^/(.*)$ /http-bind;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
-- Prosody XMPP Server Configuration
|
||||
--
|
||||
-- Information on configuring Prosody can be found on our
|
||||
-- website at http://prosody.im/doc/configure
|
||||
--
|
||||
-- Tip: You can check that the syntax of this file is correct
|
||||
-- when you have finished by running: prosodyctl check config
|
||||
-- If there are any errors, it will let you know what and where
|
||||
-- they are, otherwise it will keep quiet.
|
||||
--
|
||||
-- Good luck, and happy Jabbering!
|
||||
|
||||
|
||||
---------- Server-wide settings ----------
|
||||
-- Settings in this section apply to the whole server and are the default settings
|
||||
-- for any virtual hosts
|
||||
|
||||
-- This is a (by default, empty) list of accounts that are admins
|
||||
-- for the server. Note that you must create the accounts separately
|
||||
-- (see http://prosody.im/doc/creating_accounts for info)
|
||||
-- Example: admins = { "user1@example.com", "user2@example.net" }
|
||||
admins = { }
|
||||
daemonize = true
|
||||
cross_domain_bosh = true;
|
||||
component_ports = { 5347 }
|
||||
--component_interface = "192.168.0.10"
|
||||
|
||||
-- Enable use of libevent for better performance under high load
|
||||
-- For more information see: http://prosody.im/doc/libevent
|
||||
--use_libevent = true
|
||||
|
||||
-- This is the list of modules Prosody will load on startup.
|
||||
-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too.
|
||||
-- Documentation on modules can be found at: http://prosody.im/doc/modules
|
||||
modules_enabled = {
|
||||
|
||||
-- Generally required
|
||||
"roster"; -- Allow users to have a roster. Recommended ;)
|
||||
"saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
|
||||
"tls"; -- Add support for secure TLS on c2s/s2s connections
|
||||
"dialback"; -- s2s dialback support
|
||||
"disco"; -- Service discovery
|
||||
"posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
|
||||
|
||||
-- Not essential, but recommended
|
||||
"private"; -- Private XML storage (for room bookmarks, etc.)
|
||||
"vcard"; -- Allow users to set vCards
|
||||
|
||||
-- These are commented by default as they have a performance impact
|
||||
--"privacy"; -- Support privacy lists
|
||||
"compression"; -- Stream compression (requires the lua-zlib package installed)
|
||||
|
||||
-- Nice to have
|
||||
"version"; -- Replies to server version requests
|
||||
"uptime"; -- Report how long server has been running
|
||||
"time"; -- Let others know the time here on this server
|
||||
"ping"; -- Replies to XMPP pings with pongs
|
||||
"pep"; -- Enables users to publish their mood, activity, playing music and more
|
||||
"register"; -- Allow users to register on this server using a client and change passwords
|
||||
|
||||
-- Admin interfaces
|
||||
"admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
|
||||
--"admin_telnet"; -- Opens telnet console interface on localhost port 5582
|
||||
|
||||
-- HTTP modules
|
||||
"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
|
||||
--"http_files"; -- Serve static files from a directory over HTTP
|
||||
|
||||
-- Other specific functionality
|
||||
--"groups"; -- Shared roster support
|
||||
--"announce"; -- Send announcement to all online users
|
||||
--"welcome"; -- Welcome users who register accounts
|
||||
--"watchregistrations"; -- Alert admins of registrations
|
||||
--"motd"; -- Send a message to users when they log in
|
||||
--"legacyauth"; -- Legacy authentication. Only used by some old clients and bots.
|
||||
-- jitsi
|
||||
"smacks";
|
||||
"carbons";
|
||||
"mam";
|
||||
"lastactivity";
|
||||
"offline";
|
||||
"pubsub";
|
||||
"adhoc";
|
||||
"websocket";
|
||||
"http_altconnect";
|
||||
-- include domain mapper as global level module
|
||||
"muc_domain_mapper";
|
||||
}
|
||||
|
||||
-- domain mapper options, must at least have domain base set to use the mapper
|
||||
muc_mapper_domain_base = "jitsi.example.com";
|
||||
|
||||
-- These modules are auto-loaded, but should you want
|
||||
-- to disable them then uncomment them here:
|
||||
modules_disabled = {
|
||||
-- "offline"; -- Store offline messages
|
||||
-- "c2s"; -- Handle client connections
|
||||
-- "s2s"; -- Handle server-to-server connections
|
||||
}
|
||||
|
||||
-- Disable account creation by default, for security
|
||||
-- For more information see http://prosody.im/doc/creating_accounts
|
||||
allow_registration = false
|
||||
|
||||
-- These are the SSL/TLS-related settings. If you don't want
|
||||
-- to use SSL/TLS, you may comment or remove this
|
||||
ssl = {
|
||||
key = "/etc/prosody/certs/localhost.key";
|
||||
certificate = "/etc/prosody/certs/localhost.crt";
|
||||
}
|
||||
|
||||
-- Force clients to use encrypted connections? This option will
|
||||
-- prevent clients from authenticating unless they are using encryption.
|
||||
|
||||
-- c2s_require_encryption = true
|
||||
|
||||
-- Force certificate authentication for server-to-server connections?
|
||||
-- This provides ideal security, but requires servers you communicate
|
||||
-- with to support encryption AND present valid, trusted certificates.
|
||||
-- NOTE: Your version of LuaSec must support certificate verification!
|
||||
-- For more information see http://prosody.im/doc/s2s#security
|
||||
|
||||
-- s2s_secure_auth = false
|
||||
|
||||
-- Many servers don't support encryption or have invalid or self-signed
|
||||
-- certificates. You can list domains here that will not be required to
|
||||
-- authenticate using certificates. They will be authenticated using DNS.
|
||||
|
||||
--s2s_insecure_domains = { "gmail.com" }
|
||||
|
||||
-- Even if you leave s2s_secure_auth disabled, you can still require valid
|
||||
-- certificates for some domains by specifying a list here.
|
||||
|
||||
--s2s_secure_domains = { "jabber.org" }
|
||||
|
||||
-- Required for init scripts and prosodyctl
|
||||
pidfile = "/var/run/prosody/prosody.pid"
|
||||
|
||||
-- Select the authentication backend to use. The 'internal' providers
|
||||
-- use Prosody's configured data storage to store the authentication data.
|
||||
-- To allow Prosody to offer secure authentication mechanisms to clients, the
|
||||
-- default provider stores passwords in plaintext. If you do not trust your
|
||||
-- server please see http://prosody.im/doc/modules/mod_auth_internal_hashed
|
||||
-- for information about using the hashed backend.
|
||||
|
||||
-- authentication = "internal_plain"
|
||||
authentication = "internal_hashed"
|
||||
|
||||
-- Select the storage backend to use. By default Prosody uses flat files
|
||||
-- in its configured data directory, but it also supports more backends
|
||||
-- through modules. An "sql" backend is included by default, but requires
|
||||
-- additional dependencies. See http://prosody.im/doc/storage for more info.
|
||||
|
||||
--storage = "sql" -- Default is "internal"
|
||||
|
||||
-- For the "sql" backend, you can uncomment *one* of the below to configure:
|
||||
--sql = { driver = "SQLite3", database = "prosody.sqlite" } -- Default. 'database' is the filename.
|
||||
--sql = { driver = "MySQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" }
|
||||
--sql = { driver = "PostgreSQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" }
|
||||
|
||||
-- Logging configuration
|
||||
-- For advanced logging see http://prosody.im/doc/logging
|
||||
log = {
|
||||
info = "/var/log/prosody/prosody.log"; -- Change 'info' to 'debug' for verbose logging
|
||||
error = "/var/log/prosody/prosody.err";
|
||||
"*syslog";
|
||||
}
|
||||
|
||||
----------- Virtual hosts -----------
|
||||
-- You need to add a VirtualHost entry for each domain you wish Prosody to serve.
|
||||
-- Settings under each VirtualHost entry apply *only* to that host.
|
||||
|
||||
--VirtualHost "localhost"
|
||||
|
||||
VirtualHost "jitsi.example.com"
|
||||
-- enabled = false -- Remove this line to enable this host
|
||||
authentication = "anonymous"
|
||||
-- Assign this host a certificate for TLS, otherwise it would use the one
|
||||
-- set in the global section (if any).
|
||||
-- Note that old-style SSL on port 5223 only supports one certificate, and will always
|
||||
-- use the global one.
|
||||
ssl = {
|
||||
key = "/var/lib/prosody/jitsi.example.com.key";
|
||||
certificate = "/var/lib/prosody/jitsi.example.com.crt";
|
||||
}
|
||||
|
||||
c2s_require_encryption = false
|
||||
|
||||
VirtualHost "auth.jitsi.example.com"
|
||||
ssl = {
|
||||
key = "/var/lib/prosody/auth.jitsi.example.com.key";
|
||||
certificate = "/var/lib/prosody/auth.jitsi.example.com.crt";
|
||||
}
|
||||
authentication = "internal_plain"
|
||||
|
||||
------ Components ------
|
||||
-- You can specify components to add hosts that provide special services,
|
||||
-- like multi-user conferences, and transports.
|
||||
-- For more information on components, see http://prosody.im/doc/components
|
||||
|
||||
---Set up a MUC (multi-user chat) room server on conference.example.com:
|
||||
--Component "conference.example.com" "muc"
|
||||
|
||||
-- Set up a SOCKS5 bytestream proxy for server-proxied file transfers:
|
||||
--Component "proxy.example.com" "proxy65"
|
||||
|
||||
---Set up an external component (default component port is 5347)
|
||||
--
|
||||
-- External components allow adding various services, such as gateways/
|
||||
-- transports to other networks like ICQ, MSN and Yahoo. For more info
|
||||
-- see: http://prosody.im/doc/components#adding_an_external_component
|
||||
--
|
||||
--Component "gateway.example.com"
|
||||
-- component_secret = "password"
|
||||
|
||||
Component "conference.jitsi.example.com" "muc"
|
||||
modules_enabled = { "muc_domain_mapper" }
|
||||
|
||||
Component "jitsi-videobridge.jitsi.example.com"
|
||||
component_secret = "IfGaish6"
|
||||
@@ -210,6 +210,7 @@ Checkout and configure Jitsi Meet:
|
||||
cd /srv
|
||||
git clone https://github.com/jitsi/jitsi-meet.git
|
||||
mv jitsi-meet/ jitsi.example.com
|
||||
cd jitsi.example.com
|
||||
npm install
|
||||
make
|
||||
```
|
||||
|
||||
BIN
fonts/jitsi.eot
BIN
fonts/jitsi.eot
Binary file not shown.
@@ -1,79 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>Generated by IcoMoon</metadata>
|
||||
<defs>
|
||||
<font id="jitsi" horiz-adv-x="1024">
|
||||
<font-face units-per-em="1024" ascent="1024" descent="0" />
|
||||
<missing-glyph horiz-adv-x="1024" />
|
||||
<glyph unicode=" " d="" />
|
||||
<glyph unicode="" glyph-name="chat-unread" d="M768 682v86h-512v-86h512zM598 426v86h-342v-86h342zM256 640v-86h512v86h-512zM854 938c46 0 84-38 84-84v-512c0-46-38-86-84-86h-598l-170-170v768c0 46 38 84 84 84h684z" />
|
||||
<glyph unicode="" glyph-name="phone" d="M282 564c62-120 162-220 282-282l94 94c12 12 30 16 44 10 48-16 100-24 152-24 24 0 42-18 42-42v-150c0-24-18-42-42-42-400 0-726 326-726 726 0 24 18 42 42 42h150c24 0 42-18 42-42 0-54 8-104 24-152 4-14 2-32-10-44z" />
|
||||
<glyph unicode="" glyph-name="invite" d="M810 470h-256v-256h-84v256h-256v84h256v256h84v-256h256v-84z" />
|
||||
<glyph unicode="" glyph-name="add" d="M810 470h-256v-256h-84v256h-256v84h256v256h84v-256h256v-84z" />
|
||||
<glyph unicode="" glyph-name="bluetooth" d="M550 328l-80 82v-162zM470 776v-162l80 82zM670 696l-184-184 184-184-244-242h-42v324l-196-196-60 60 238 238-238 238 60 60 196-196v324h42zM834 738c40-64 62-142 62-222 0-84-24-160-66-226l-50 50c26 52 42 110 42 172s-16 120-42 172zM608 512l98 98c12-30 20-64 20-98s-8-70-20-100z" />
|
||||
<glyph unicode="" glyph-name="headset" d="M512 982c212 0 384-172 384-384v-300c0-70-58-128-128-128h-128v342h170v86c0 166-132 298-298 298s-298-132-298-298v-86h170v-342h-128c-70 0-128 58-128 128v300c0 212 172 384 384 384z" />
|
||||
<glyph unicode="" glyph-name="navigate_next" d="M426 768l256-256-256-256-60 60 196 196-196 196z" />
|
||||
<glyph unicode="" glyph-name="arrow_back" d="M854 554v-84h-520l238-240-60-60-342 342 342 342 60-60-238-240h520z" />
|
||||
<glyph unicode="" glyph-name="close" d="M810 750l-238-238 238-238-60-60-238 238-238-238-60 60 238 238-238 238 60 60 238-238 238 238z" />
|
||||
<glyph unicode="" glyph-name="menu" d="M128 768h768v-86h-768v86zM128 470v84h768v-84h-768zM128 256v86h768v-86h-768z" />
|
||||
<glyph unicode="" glyph-name="thumb-menu" d="M512 342c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM512 598c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM512 682c-46 0-86 40-86 86s40 86 86 86 86-40 86-86-40-86-86-86z" />
|
||||
<glyph unicode="" glyph-name="presentation" horiz-adv-x="1088" d="M952.495 1019.065h-818.689c-72.81 0-132.183-60.63-132.183-135.162v-750.719c0-74.473 59.372-135.101 132.183-135.101h818.686c72.936 0 132.314 60.625 132.314 135.101v750.722c0.003 74.532-59.378 135.159-132.311 135.159zM946.346 139.651h-806.14v737.822h806.015l0.126-737.822zM685.753 738.544h216.911v-566.758h-216.911v566.758zM428.672 610.002h216.911v-438.216h-216.911v438.216zM172.339 481.46h216.161v-309.677h-216.161v309.677z" />
|
||||
<glyph unicode="" glyph-name="event_note" d="M598 426v-84h-300v84h300zM810 214v468h-596v-468h596zM810 896c46 0 86-40 86-86v-596c0-46-40-86-86-86h-596c-48 0-86 40-86 86v596c0 46 38 86 86 86h42v86h86v-86h340v86h86v-86h42zM726 598v-86h-428v86h428z" />
|
||||
<glyph unicode="" glyph-name="phone-talk" d="M640 512c0 70-58 128-128 128v86c118 0 214-96 214-214h-86zM810 512c0 166-132 298-298 298v86c212 0 384-172 384-384h-86zM854 362c24 0 42-18 42-42v-150c0-24-18-42-42-42-400 0-726 326-726 726 0 24 18 42 42 42h150c24 0 42-18 42-42 0-54 8-104 24-152 4-14 2-32-10-44l-94-94c62-122 162-220 282-282l94 94c12 12 30 14 44 10 48-16 98-24 152-24z" />
|
||||
<glyph unicode="" glyph-name="public" d="M764 282c56 60 90 142 90 230 0 142-88 266-214 316v-18c0-46-40-84-86-84h-84v-86c0-24-20-42-44-42h-84v-86h256c24 0 42-18 42-42v-128h42c38 0 70-26 82-60zM470 174v82c-46 0-86 40-86 86v42l-204 204c-6-24-10-50-10-76 0-174 132-318 300-338zM512 938c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426z" />
|
||||
<glyph unicode="" glyph-name="radio_button_unchecked" d="M512 170c188 0 342 154 342 342s-154 342-342 342-342-154-342-342 154-342 342-342zM512 938c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426z" />
|
||||
<glyph unicode="" glyph-name="radio_button_checked" d="M512 170c188 0 342 154 342 342s-154 342-342 342-342-154-342-342 154-342 342-342zM512 938c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426zM512 726c118 0 214-96 214-214s-96-214-214-214-214 96-214 214 96 214 214 214z" />
|
||||
<glyph unicode="" glyph-name="open_in_new" d="M598 896h298v-298h-86v152l-418-418-60 60 418 418h-152v86zM810 214v298h86v-298c0-46-40-86-86-86h-596c-48 0-86 40-86 86v596c0 46 38 86 86 86h298v-86h-298v-596h596z" />
|
||||
<glyph unicode="" glyph-name="restore" d="M512 682h64v-180l150-90-32-52-182 110v212zM554 896c212 0 384-172 384-384s-172-384-384-384c-106 0-200 42-270 112l60 62c54-54 128-88 210-88 166 0 300 132 300 298s-134 298-300 298-298-132-298-298h128l-172-172-4 6-166 166h128c0 212 172 384 384 384z" />
|
||||
<glyph unicode="" glyph-name="search" d="M406 426c106 0 192 86 192 192s-86 192-192 192-192-86-192-192 86-192 192-192zM662 426l212-212-64-64-212 212v34l-12 12c-48-42-112-66-180-66-154 0-278 122-278 276s124 278 278 278 276-124 276-278c0-68-24-132-66-180l12-12h34z" />
|
||||
<glyph unicode="" glyph-name="AUD" d="M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512c282.77 0 512-229.23 512-512s-229.23-512-512-512zM308.25 387.3h57.225l-87.675 252.525h-62.125l-87.675-252.525h53.025l19.425 60.2h88.725l19.075-60.2zM461.9 639.825h-52.85v-165.375c0-56 41.125-93.625 105.7-93.625 64.75 0 105.875 37.625 105.875 93.625v165.375h-52.85v-159.95c0-31.85-19.075-52.15-53.025-52.15-33.775 0-52.85 20.3-52.85 52.15v159.95zM682.225 640v-252.7h99.4c75.6 0 118.475 46.025 118.475 128.1 0 79.1-43.4 124.6-118.475 124.6h-99.4zM735.075 594.85v-162.4h38.15c46.725 0 72.975 28.7 72.975 82.075 0 51.1-27.125 80.325-72.975 80.325h-38.15zM243.5 587.325l-31.675-99.050h66.15l-31.325 99.050h-3.15z" />
|
||||
<glyph unicode="" glyph-name="signal_cellular_0" d="M938 938v-852h-852zM854 732l-562-562h562v562z" />
|
||||
<glyph unicode="" glyph-name="signal_cellular_1" d="M86 86l852 852v-256h-170v-596h-682zM854 86v84h84v-84h-84zM854 256v342h84v-342h-84z" />
|
||||
<glyph unicode="" glyph-name="mic-camera-combined" d="M756.704 628.138l267.296 202.213v-635.075l-267.296 202.213v-191.923c0-12.085-11.296-21.863-25.216-21.863h-706.272c-13.92 0-25.216 9.777-25.216 21.863v612.25c0 12.085 11.296 21.863 25.216 21.863h706.272c13.92 0 25.216-9.777 25.216-21.863v-189.679zM371.338 376.228c47.817 0 86.529 40.232 86.529 89.811v184.835c0 49.651-38.713 89.883-86.529 89.883-47.788 0-86.515-40.232-86.515-89.883v-184.835c0-49.579 38.756-89.811 86.515-89.811v0zM356.754 314.070v-32.78h33.718v33.412c73.858 9.606 131.235 73.73 131.235 151.351v88.232h-30.636v-88.232c0-67.57-53.696-122.534-119.734-122.534-66.024 0-119.691 54.964-119.691 122.534v88.232h-30.636v-88.232c0-79.215 59.674-144.502 135.744-151.969v-0.014z" />
|
||||
<glyph unicode="" glyph-name="kick" d="M512 810l284-426h-568zM214 298h596v-84h-596v84z" />
|
||||
<glyph unicode="" glyph-name="hangup" d="M512 640c-68 0-134-10-196-30v-132c0-16-10-34-24-40-42-20-80-46-114-78-8-8-18-12-30-12s-22 4-30 12l-106 106c-8 8-12 18-12 30s4 22 12 30c130 124 306 200 500 200s370-76 500-200c8-8 12-18 12-30s-4-22-12-30l-106-106c-8-8-18-12-30-12s-22 4-30 12c-34 32-72 58-114 78-14 6-24 20-24 38v132c-62 20-128 32-196 32z" />
|
||||
<glyph unicode="" glyph-name="chat" d="M854 342v512h-684v-598l86 86h598zM854 938c46 0 84-38 84-84v-512c0-46-38-86-84-86h-598l-170-170v768c0 46 38 84 84 84h684z" />
|
||||
<glyph unicode="" glyph-name="signal_cellular_2" d="M86 86l852 852v-852h-852z" />
|
||||
<glyph unicode="" glyph-name="share-doc" d="M554 640h236l-236 234v-234zM682 426v86h-340v-86h340zM682 256v86h-340v-86h340zM598 938l256-256v-512c0-46-40-84-86-84h-512c-46 0-86 38-86 84l2 684c0 46 38 84 84 84h342z" />
|
||||
<glyph unicode="" glyph-name="ninja" d="M330.667 469.333c-0.427 14.933 6.4 29.44 17.92 39.253 32-6.827 61.867-20.053 88.747-39.253 0-29.013-23.893-52.907-53.333-52.907s-52.907 23.467-53.333 52.907zM586.667 469.333c26.88 18.773 56.747 32 88.747 38.827 11.52-9.813 18.347-24.32 17.92-38.827 0-29.867-23.893-53.76-53.333-53.76s-53.333 23.893-53.333 53.76v0zM512 640c-118.187 1.707-234.667-27.733-338.347-85.333l-2.987-42.667c0-52.48 12.373-104.107 35.84-151.040 101.12 15.36 203.093 23.040 305.493 23.040s204.373-7.68 305.493-23.040c23.467 46.933 35.84 98.56 35.84 151.040l-2.987 42.667c-103.68 57.6-220.16 87.040-338.347 85.333zM512 938.667c235.641 0 426.667-191.025 426.667-426.667s-191.025-426.667-426.667-426.667c-235.641 0-426.667 191.025-426.667 426.667s191.025 426.667 426.667 426.667z" />
|
||||
<glyph unicode="" glyph-name="enlarge" d="M896 212v600h-768v-600h768zM896 896q34 0 60-26t26-60v-596q0-34-26-60t-60-26h-768q-34 0-60 26t-26 60v596q0 34 26 60t60 26h768zM598 342l-86-108-86 108h172zM256 598v-172l-106 86zM768 598l106-86-106-86v172zM512 790l86-108h-172z" />
|
||||
<glyph unicode="" glyph-name="full-screen" d="M598 810h212v-212h-84v128h-128v84zM726 298v128h84v-212h-212v84h128zM214 598v212h212v-84h-128v-128h-84zM298 426v-128h128v-84h-212v212h84z" />
|
||||
<glyph unicode="" glyph-name="exit-full-screen" d="M682 682h128v-84h-212v212h84v-128zM598 214v212h212v-84h-128v-128h-84zM342 682v128h84v-212h-212v84h128zM214 342v84h212v-212h-84v128h-128z" />
|
||||
<glyph unicode="" glyph-name="security" d="M768 170v428h-512v-428h512zM768 682c46 0 86-38 86-84v-428c0-46-40-84-86-84h-512c-46 0-86 38-86 84v428c0 46 40 84 86 84h388v86c0 72-60 132-132 132s-132-60-132-132h-82c0 118 96 214 214 214s214-96 214-214v-86h42zM512 298c-46 0-86 40-86 86s40 86 86 86 86-40 86-86-40-86-86-86z" />
|
||||
<glyph unicode="" glyph-name="security-locked" d="M768 170v428h-512v-428h512zM380 768v-86h264v86c0 72-60 132-132 132s-132-60-132-132zM768 682c46 0 86-38 86-84v-428c0-46-40-84-86-84h-512c-46 0-86 38-86 84v428c0 46 40 84 86 84h42v86c0 118 96 214 214 214s214-96 214-214v-86h42zM512 298c-46 0-86 40-86 86s40 86 86 86 86-40 86-86-40-86-86-86z" />
|
||||
<glyph unicode="" glyph-name="blur-background" d="M469.333 640c0-47.128-38.205-85.333-85.333-85.333s-85.333 38.205-85.333 85.333c0 47.128 38.205 85.333 85.333 85.333s85.333-38.205 85.333-85.333zM725.333 640c0-47.128-38.205-85.333-85.333-85.333s-85.333 38.205-85.333 85.333c0 47.128 38.205 85.333 85.333 85.333s85.333-38.205 85.333-85.333zM469.333 384c0-47.128-38.205-85.333-85.333-85.333s-85.333 38.205-85.333 85.333c0 47.128 38.205 85.333 85.333 85.333s85.333-38.205 85.333-85.333zM426.667 170.667c0-23.564-19.103-42.667-42.667-42.667s-42.667 19.103-42.667 42.667c0 23.564 19.103 42.667 42.667 42.667s42.667-19.103 42.667-42.667zM682.667 170.667c0-23.564-19.103-42.667-42.667-42.667s-42.667 19.103-42.667 42.667c0 23.564 19.103 42.667 42.667 42.667s42.667-19.103 42.667-42.667zM213.333 384c0-23.564-19.103-42.667-42.667-42.667s-42.667 19.103-42.667 42.667c0 23.564 19.103 42.667 42.667 42.667s42.667-19.103 42.667-42.667zM213.333 640c0-23.564-19.103-42.667-42.667-42.667s-42.667 19.103-42.667 42.667c0 23.564 19.103 42.667 42.667 42.667s42.667-19.103 42.667-42.667zM896 384c0-23.564-19.103-42.667-42.667-42.667s-42.667 19.103-42.667 42.667c0 23.564 19.103 42.667 42.667 42.667s42.667-19.103 42.667-42.667zM896 640c0-23.564-19.103-42.667-42.667-42.667s-42.667 19.103-42.667 42.667c0 23.564 19.103 42.667 42.667 42.667s42.667-19.103 42.667-42.667zM426.667 853.333c0-23.564-19.103-42.667-42.667-42.667s-42.667 19.103-42.667 42.667c0 23.564 19.103 42.667 42.667 42.667s42.667-19.103 42.667-42.667zM682.667 853.333c0-23.564-19.103-42.667-42.667-42.667s-42.667 19.103-42.667 42.667c0 23.564 19.103 42.667 42.667 42.667s42.667-19.103 42.667-42.667zM725.333 384c0-47.128-38.205-85.333-85.333-85.333s-85.333 38.205-85.333 85.333c0 47.128 38.205 85.333 85.333 85.333s85.333-38.205 85.333-85.333z" />
|
||||
<glyph unicode="" glyph-name="microphone" d="M738 554h72c0-146-116-266-256-286v-140h-84v140c-140 20-256 140-256 286h72c0-128 108-216 226-216s226 88 226 216zM512 426c-70 0-128 58-128 128v256c0 70 58 128 128 128s128-58 128-128v-256c0-70-58-128-128-128z" />
|
||||
<glyph unicode="" glyph-name="send" d="M86 128v298l640 86-640 86v298l896-384z" />
|
||||
<glyph unicode="" glyph-name="mic-disabled" d="M182 896l714-714-54-54-178 178c-32-20-72-32-110-38v-140h-84v140c-140 20-256 140-256 286h72c0-128 108-216 226-216 34 0 68 8 98 22l-70 70c-8-2-18-4-28-4-70 0-128 58-128 128v32l-256 256zM640 548l-256 254v8c0 70 58 128 128 128s128-58 128-128v-262zM810 554c0-50-14-98-38-140l-52 54c12 26 18 54 18 86h72z" />
|
||||
<glyph unicode="" glyph-name="link" d="M640 426c114 0 342-56 342-170v-86h-684v86c0 114 228 170 342 170zM256 598h128v-86h-128v-128h-86v128h-128v86h128v128h86v-128zM640 512c-94 0-170 76-170 170s76 172 170 172 170-78 170-172-76-170-170-170z" />
|
||||
<glyph unicode="" glyph-name="shared-video" d="M512 170c188 0 342 154 342 342s-154 342-342 342-342-154-342-342 154-342 342-342zM512 938c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426zM426 320v384l256-192z" />
|
||||
<glyph unicode="" glyph-name="settings" d="M512 362c82 0 150 68 150 150s-68 150-150 150-150-68-150-150 68-150 150-150zM830 470l90-70c8-6 10-18 4-28l-86-148c-6-10-16-12-26-8l-106 42c-22-16-46-32-72-42l-16-112c-2-10-10-18-20-18h-172c-10 0-18 8-20 18l-16 112c-26 10-50 24-72 42l-106-42c-10-4-20-2-26 8l-86 148c-6 10-4 22 4 28l90 70c-2 14-2 28-2 42s0 28 2 42l-90 70c-8 6-10 18-4 28l86 148c6 10 16 12 26 8l106-42c22 16 46 32 72 42l16 112c2 10 10 18 20 18h172c10 0 18-8 20-18l16-112c26-10 50-24 72-42l106 42c10 4 20 2 26-8l86-148c6-10 4-22-4-28l-90-70c2-14 2-28 2-42s0-28-2-42z" />
|
||||
<glyph unicode="" glyph-name="star" d="M512 366l160-96-42 182 142 124-188 16-72 172-72-172-188-16 142-124-42-182zM938 630l-232-202 70-300-264 160-264-160 70 300-232 202 306 26 120 282 120-282z" />
|
||||
<glyph unicode="" glyph-name="share-desktop" d="M896 298v512h-768v-512h768zM896 896c46 0 86-40 86-86l-2-512c0-46-38-84-84-84h-214v-86h-340v86h-214c-46 0-86 38-86 84v512c0 46 40 86 86 86h768z" />
|
||||
<glyph unicode="" glyph-name="camera" d="M726 576l170 170v-468l-170 170v-150c0-24-20-42-44-42h-512c-24 0-42 18-42 42v428c0 24 18 42 42 42h512c24 0 44-18 44-42v-150z" />
|
||||
<glyph unicode="" glyph-name="camera-disabled" d="M140 938l756-756-54-54-136 136c-6-4-16-8-24-8h-512c-24 0-42 18-42 42v428c0 24 18 42 42 42h32l-116 116zM896 746v-456l-478 478h264c24 0 44-18 44-42v-150z" />
|
||||
<glyph unicode="" glyph-name="volume" d="M598 886c172-38 298-192 298-374s-126-336-298-374v88c124 36 212 150 212 286s-88 250-212 286v88zM704 512c0-76-42-140-106-172v344c64-32 106-96 106-172zM128 640h170l214 214v-684l-214 214h-170v256z" />
|
||||
<glyph unicode="" glyph-name="check" d="M384 334l452 452 60-60-512-512-238 238 60 60z" />
|
||||
<glyph unicode="" glyph-name="cancel" d="M726 358l-154 154 154 154-60 60-154-154-154 154-60-60 154-154-154-154 60-60 154 154 154-154zM512 938q176 0 301-125t125-301-125-301-301-125-301 125-125 301 125 301 301 125z" />
|
||||
<glyph unicode="" glyph-name="feedback" d="M42.667 128h170.667v512h-170.667v-512zM981.333 597.333c0 46.933-38.4 85.333-85.333 85.333h-269.227l40.533 194.987 1.28 13.653c0 17.493-7.253 33.707-18.773 45.227l-45.227 44.8-280.747-281.173c-15.787-15.36-25.173-36.693-25.173-60.16v-426.667c0-46.933 38.4-85.333 85.333-85.333h384c35.413 0 65.707 21.333 78.507 52.053l128.853 300.8c3.84 9.813 5.973 20.053 5.973 31.147v81.493l-0.427 0.427 0.427 3.413z" />
|
||||
<glyph unicode="" glyph-name="raised-hand" d="M982 790v-620c0-94-78-170-172-170h-310c-46 0-90 18-122 50l-336 342s54 52 56 52c10 8 22 12 34 12 10 0 18-2 26-6 2 0 184-104 184-104v508c0 36 28 64 64 64s64-28 64-64v-300h42v406c0 36 28 64 64 64s64-28 64-64v-406h42v364c0 36 28 64 64 64s64-28 64-64v-364h44v236c0 36 28 64 64 64s64-28 64-64z" />
|
||||
<glyph unicode="" glyph-name="menu-up" d="M512 682l256-256-60-60-196 196-196-196-60 60z" />
|
||||
<glyph unicode="" glyph-name="menu-down" d="M708 658l60-60-256-256-256 256 60 60 196-196z" />
|
||||
<glyph unicode="" glyph-name="switch-camera" d="M640 362l150 150-150 150v-108h-256v108l-150-150 150-150v108h256v-108zM854 854c46 0 84-40 84-86v-512c0-46-38-86-84-86h-684c-46 0-84 40-84 86v512c0 46 38 86 84 86h136l78 84h256l78-84h136z" />
|
||||
<glyph unicode="" glyph-name="info" d="M512 938.667c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM554.667 298.667h-85.333v256h85.333v-256zM554.667 640h-85.333v85.333h85.333v-85.333z" />
|
||||
<glyph unicode="" glyph-name="visibility" d="M512 640c70 0 128-58 128-128s-58-128-128-128-128 58-128 128 58 128 128 128zM512 298c118 0 214 96 214 214s-96 214-214 214-214-96-214-214 96-214 214-214zM512 832c214 0 396-132 470-320-74-188-256-320-470-320s-396 132-470 320c74 188 256 320 470 320z" />
|
||||
<glyph unicode="" glyph-name="visibility-off" d="M506 640h6c70 0 128-58 128-128v-8zM322 606c-14-28-24-60-24-94 0-118 96-214 214-214 34 0 66 10 94 24l-66 66c-8-2-18-4-28-4-70 0-128 58-128 128 0 10 2 20 4 28zM86 842l54 54 756-756-54-54c-47.968 47.365-96.266 94.401-144 142-58-24-120-36-186-36-214 0-396 132-470 320 34 84 90 156 160 212-39.017 38.983-77.307 78.693-116 118zM512 726c-28 0-54-6-78-16l-92 92c52 20 110 30 170 30 214 0 394-132 468-320-32-80-82-148-146-202l-124 124c10 24 16 50 16 78 0 118-96 214-214 214z" />
|
||||
<glyph unicode="" glyph-name="gsm-bars" d="M896 1024c70.692 0 128-57.308 128-128v-768c0-70.692-57.308-128-128-128s-128 57.308-128 128v768c0 70.692 57.308 128 128 128zM512 768c70.692 0 128-57.308 128-128v-512c0-70.692-57.308-128-128-128s-128 57.308-128 128v512c0 70.692 57.308 128 128 128zM128 384v0c70.692 0 128-57.308 128-128v-128c0-70.692-57.308-128-128-128s-128 57.308-128 128v128c0 70.692 57.308 128 128 128v0z" />
|
||||
<glyph unicode="" glyph-name="HD" d="M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512c282.77 0 512-229.23 512-512s-229.23-512-512-512zM481.359 384v255.823h-54.273v-103.18h-116.813v103.18h-54.273v-255.823h54.273v106.903h116.813v-106.903h54.273zM544.258 640v-256h102.077c77.636 0 121.665 46.626 121.665 129.773 0 80.133-44.569 126.227-121.665 126.227h-102.077zM598.531 594.26v-164.521h39.177c47.983 0 74.94 29.075 74.94 83.147 0 51.767-27.855 81.374-74.94 81.374h-39.177z" />
|
||||
<glyph unicode="" glyph-name="LD" d="M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512c282.77 0 512-229.23 512-512s-229.23-512-512-512zM472.4 433.325h-112.35v206.5h-52.85v-252.525h165.2v46.025zM520.35 640v-252.7h99.4c75.6 0 118.475 46.025 118.475 128.1 0 79.1-43.4 124.6-118.475 124.6h-99.4zM573.2 594.85v-162.4h38.15c46.725 0 72.975 28.7 72.975 82.075 0 51.1-27.125 80.325-72.975 80.325h-38.15z" />
|
||||
<glyph unicode="" glyph-name="SD" d="M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512c282.77 0 512-229.23 512-512s-229.23-512-512-512zM281.6 451.175c1.925-47.075 40.95-76.65 101.15-76.65 63.35 0 102.375 31.15 102.375 82.075 0 39.2-21.875 61.075-72.625 71.75l-30.45 6.475c-29.575 6.3-41.65 15.225-41.65 30.8 0 19.25 17.5 31.5 43.925 31.5 25.55 0 44.1-13.3 46.55-33.25h49.7c-1.575 44.975-40.95 76.125-96.6 76.125-58.275 0-96.6-31.325-96.6-78.925 0-38.5 22.575-62.475 68.6-72.1l32.9-7c30.975-6.65 43.575-15.925 43.575-32.025 0-19.075-19.425-32.375-46.9-32.375-29.75 0-50.4 13.125-52.85 33.6h-51.1zM535 633.7v-252.7h99.4c75.6 0 118.475 46.025 118.475 128.1 0 79.1-43.4 124.6-118.475 124.6h-99.4zM587.85 588.55v-162.4h38.15c46.725 0 72.975 28.7 72.975 82.075 0 51.1-27.125 80.325-72.975 80.325h-38.15z" />
|
||||
<glyph unicode="" glyph-name="camera-take-picture" d="M725.333 512c0-117.821-95.513-213.333-213.333-213.333s-213.333 95.513-213.333 213.333c0 117.821 95.513 213.333 213.333 213.333s213.333-95.513 213.333-213.333zM512 256c141.385 0 256 114.615 256 256s-114.615 256-256 256v0c-141.385 0-256-114.615-256-256s114.615-256 256-256v0zM512 213.333c-164.949 0-298.667 133.718-298.667 298.667s133.718 298.667 298.667 298.667v0c164.949 0 298.667-133.718 298.667-298.667s-133.718-298.667-298.667-298.667v0z" />
|
||||
<glyph unicode="" glyph-name="rec" d="M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512c282.77 0 512-229.23 512-512s-229.23-512-512-512zM581.333 433.782h-110.595v59.233h104.338v40.332h-104.338v56.87h110.595v43.539h-161.665v-243.512h161.665v43.539zM738.771 384c58.849 0 101.802 36.282 106.029 88.933h-49.717c-4.904-26.832-26.888-44.045-56.143-44.045-38.556 0-62.4 31.895-62.4 83.196s23.844 83.027 62.231 83.027c29.086 0 51.239-18.394 56.143-46.407h49.717c-3.72 52.989-48.026 91.296-105.86 91.296-70.855 0-114.485-48.77-114.485-127.916 0-79.314 43.798-128.084 114.485-128.084zM230.27 478.502h41.769l45.489-88.258h57.834l-51.408 96.19c28.072 11.138 44.306 38.138 44.306 69.189 0 48.432-32.976 78.133-86.582 78.133h-102.478v-243.512h51.070v88.258zM230.27 592.58v-74.927h44.813c25.704 0 40.754 13.838 40.754 37.295 0 23.119-15.896 37.632-41.262 37.632h-44.306z" />
|
||||
<glyph unicode="" glyph-name="speaker" d="M0 512c0-282.795 229.205-512 512-512s512 229.205 512 512c0 282.795-229.205 512-512 512s-512-229.205-512-512zM525.005 759.362c-20.475 24.944-16.326 61.342 9.268 81.297s62.94 15.911 83.416-9.033c16.036-19.536 38.593-52.97 60.894-97.797 81.621-164.065 89.461-340.992-26.857-506.352-8.384-11.919-17.386-23.69-27.012-35.307-20.593-24.851-57.959-28.727-83.458-8.657s-29.476 56.487-8.882 81.338c7.686 9.275 14.833 18.621 21.455 28.035 88.66 126.041 82.71 260.306 17.953 390.475-10.599 21.305-21.94 40.51-33.198 57.196-6.515 9.657-11.322 16.057-13.578 18.805zM353.479 647.46c-19.353 24.679-15.129 60.448 9.434 79.893s60.164 15.2 79.517-9.479c9.635-12.287 22.577-32.644 35.209-60.034 50.35-109.176 50.35-231.689-33.639-349.612-18.198-25.551-53.566-31.441-78.997-13.157s-31.294 53.819-13.096 79.37c57.564 80.822 57.564 160.581 22.983 235.565-8.601 18.65-16.892 31.691-21.412 37.455z" />
|
||||
<glyph unicode="" glyph-name="tiles-many" d="M113.778 1024h227.556c62.838 0 113.778-50.94 113.778-113.778v-227.556c0-62.838-50.94-113.778-113.778-113.778h-227.556c-62.838 0-113.778 50.94-113.778 113.778v227.556c0 62.838 50.94 113.778 113.778 113.778zM170.667 910.222c-31.419 0-56.889-25.47-56.889-56.889v-113.778c0-31.419 25.47-56.889 56.889-56.889h113.778c31.419 0 56.889 25.47 56.889 56.889v113.778c0 31.419-25.47 56.889-56.889 56.889h-113.778zM113.778 455.111h227.556c62.838 0 113.778-50.94 113.778-113.778v-227.556c0-62.838-50.94-113.778-113.778-113.778h-227.556c-62.838 0-113.778 50.94-113.778 113.778v227.556c0 62.838 50.94 113.778 113.778 113.778zM170.667 341.333c-31.419 0-56.889-25.47-56.889-56.889v-113.778c0-31.419 25.47-56.889 56.889-56.889h113.778c31.419 0 56.889 25.47 56.889 56.889v113.778c0 31.419-25.47 56.889-56.889 56.889h-113.778zM682.667 1024h227.556c62.838 0 113.778-50.94 113.778-113.778v-227.556c0-62.838-50.94-113.778-113.778-113.778h-227.556c-62.838 0-113.778 50.94-113.778 113.778v227.556c0 62.838 50.94 113.778 113.778 113.778zM739.556 910.222c-31.419 0-56.889-25.47-56.889-56.889v-113.778c0-31.419 25.47-56.889 56.889-56.889h113.778c31.419 0 56.889 25.47 56.889 56.889v113.778c0 31.419-25.47 56.889-56.889 56.889h-113.778zM682.667 455.111h227.556c62.838 0 113.778-50.94 113.778-113.778v-227.556c0-62.838-50.94-113.778-113.778-113.778h-227.556c-62.838 0-113.778 50.94-113.778 113.778v227.556c0 62.838 50.94 113.778 113.778 113.778zM739.556 341.333c-31.419 0-56.889-25.47-56.889-56.889v-113.778c0-31.419 25.47-56.889 56.889-56.889h113.778c31.419 0 56.889 25.47 56.889 56.889v113.778c0 31.419-25.47 56.889-56.889 56.889h-113.778z" />
|
||||
<glyph unicode="" glyph-name="closed_caption" d="M768 554v44c0 24-18 42-42 42h-128c-24 0-44-18-44-42v-172c0-24 20-42 44-42h128c24 0 42 18 42 42v44h-64v-22h-86v128h86v-22h64zM470 554v44c0 24-20 42-44 42h-128c-24 0-42-18-42-42v-172c0-24 18-42 42-42h128c24 0 44 18 44 42v44h-64v-22h-86v128h86v-22h64zM810 854c46 0 86-40 86-86v-512c0-46-40-86-86-86h-596c-48 0-86 40-86 86v512c0 46 38 86 86 86h596z" />
|
||||
<glyph unicode="" glyph-name="play" horiz-adv-x="809" d="M790.857 494.286l-758.857-421.714c-17.714-9.714-32-1.143-32 18.857v841.143c0 20 14.286 28.571 32 18.857l758.857-421.714c17.714-9.714 17.714-25.714 0-35.429z" />
|
||||
<glyph unicode="" glyph-name="stop" horiz-adv-x="878" d="M877.714 914.286v-804.571c0-20-16.571-36.571-36.571-36.571h-804.571c-20 0-36.571 16.571-36.571 36.571v804.571c0 20 16.571 36.571 36.571 36.571h804.571c20 0 36.571-16.571 36.571-36.571z" />
|
||||
<glyph unicode="" glyph-name="dominant-speaker" d="M950.857 658.286c40.571 0 73.143-32.571 73.143-73.143s-32.571-73.143-73.143-73.143v-219.429c0-40-33.143-73.143-73.143-73.143-101.714 84.571-265.714 200.571-464 217.143-68-22.857-91.429-102.286-46.857-148-40-65.714 11.429-112 72-159.429-35.429-69.714-182.857-70.857-235.429-22.286-33.143 101.714-82.286 203.429-42.286 332h-69.714c-50.286 0-91.429 41.143-91.429 91.429v109.714c0 50.286 41.143 91.429 91.429 91.429h274.286c219.429 0 402.286 128 512 219.429 40 0 73.143-33.143 73.143-73.143v-219.429zM877.714 313.143v545.143c-149.143-114.286-293.714-180-438.857-196v-154.286c145.143-16 289.714-80.571 438.857-194.857z" />
|
||||
</font></defs></svg>
|
||||
|
Before Width: | Height: | Size: 24 KiB |
BIN
fonts/jitsi.ttf
BIN
fonts/jitsi.ttf
Binary file not shown.
BIN
fonts/jitsi.woff
BIN
fonts/jitsi.woff
Binary file not shown.
File diff suppressed because one or more lines are too long
3
images/user-groups.svg
Normal file
3
images/user-groups.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.33331 2C6.28101 2 7.09675 2.56499 7.46207 3.37651C7.00766 3.45023 6.58406 3.61583 6.21095 3.85361C6.04111 3.54356 5.71176 3.33333 5.33331 3.33333C4.78103 3.33333 4.33331 3.78105 4.33331 4.33333C4.33331 4.75895 4.59921 5.12246 4.97395 5.26682C4.77672 5.69245 4.66665 6.16671 4.66665 6.66667L4.66678 6.6967C3.12249 6.85332 2.66665 7.65415 2.66665 9.83333C2.66665 9.89666 2.66835 9.95222 2.67088 10H3.13441C2.977 10.3982 2.86114 10.8423 2.7841 11.3333H2.33331C1.66665 11.3333 1.33331 10.8333 1.33331 9.83333C1.33331 7.60559 1.88097 6.20498 3.39417 5.63152C3.14521 5.26038 2.99998 4.81382 2.99998 4.33333C2.99998 3.04467 4.04465 2 5.33331 2ZM9.78901 3.85361C9.4159 3.61583 8.9923 3.45023 8.53788 3.37651C8.90321 2.56499 9.71895 2 10.6666 2C11.9553 2 13 3.04467 13 4.33333C13 4.81382 12.8547 5.26038 12.6058 5.63152C14.119 6.20498 14.6666 7.60559 14.6666 9.83333C14.6666 10.8333 14.3333 11.3333 13.6666 11.3333H13.2159C13.1388 10.8423 13.023 10.3982 12.8656 10H13.3291C13.3316 9.95222 13.3333 9.89666 13.3333 9.83333C13.3333 7.65415 12.8775 6.85332 11.3332 6.6967L11.3333 6.66667C11.3333 6.1667 11.2232 5.69245 11.026 5.26682C11.4008 5.12246 11.6666 4.75895 11.6666 4.33333C11.6666 3.78105 11.2189 3.33333 10.6666 3.33333C10.2882 3.33333 9.95885 3.54356 9.78901 3.85361ZM4.49998 14.6667C3.7222 14.6667 3.33331 14.1111 3.33331 13C3.33331 10.4598 4.0062 8.8875 5.87888 8.28308C5.5366 7.83462 5.33331 7.27438 5.33331 6.66667C5.33331 5.19391 6.52722 4 7.99998 4C9.47274 4 10.6666 5.19391 10.6666 6.66667C10.6666 7.27438 10.4634 7.83462 10.1211 8.28308C11.9938 8.8875 12.6666 10.4598 12.6666 13C12.6666 14.1111 12.2778 14.6667 11.5 14.6667H4.49998ZM9.33331 6.66667C9.33331 7.40305 8.73636 8 7.99998 8C7.2636 8 6.66665 7.40305 6.66665 6.66667C6.66665 5.93029 7.2636 5.33333 7.99998 5.33333C8.73636 5.33333 9.33331 5.93029 9.33331 6.66667ZM11.3333 13C11.3333 13.1426 11.3252 13.2536 11.3152 13.3333H4.68477C4.67476 13.2536 4.66665 13.1426 4.66665 13C4.66665 10.1957 5.42021 9.33333 7.99998 9.33333C10.5797 9.33333 11.3333 10.1957 11.3333 13Z" fill="#5E6D7A"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -148,6 +148,7 @@
|
||||
<!--#include virtual="title.html" -->
|
||||
<!--#include virtual="plugin.head.html" -->
|
||||
<!--#include virtual="static/welcomePageAdditionalContent.html" -->
|
||||
<!--#include virtual="static/settingsToolbarAdditionalContent.html" -->
|
||||
</head>
|
||||
<body>
|
||||
<div id="react"></div>
|
||||
|
||||
@@ -27,6 +27,7 @@ var interfaceConfig = {
|
||||
SHOW_DEEP_LINKING_IMAGE: false,
|
||||
GENERATE_ROOMNAMES_ON_WELCOME_PAGE: true,
|
||||
DISPLAY_WELCOME_PAGE_CONTENT: true,
|
||||
DISPLAY_WELCOME_PAGE_TOOLBAR_ADDITIONAL_CONTENT: false,
|
||||
APP_NAME: 'Jitsi Meet',
|
||||
NATIVE_APP_NAME: 'Jitsi Meet',
|
||||
PROVIDER_NAME: 'Jitsi',
|
||||
@@ -50,7 +51,7 @@ var interfaceConfig = {
|
||||
'fodeviceselection', 'hangup', 'profile', 'info', 'chat', 'recording',
|
||||
'livestreaming', 'etherpad', 'sharedvideo', 'settings', 'raisehand',
|
||||
'videoquality', 'filmstrip', 'invite', 'feedback', 'stats', 'shortcuts',
|
||||
'tileview', 'videobackgroundblur'
|
||||
'tileview', 'videobackgroundblur', 'download', 'help'
|
||||
],
|
||||
|
||||
SETTINGS_SECTIONS: [ 'devices', 'language', 'moderator', 'profile', 'calendar' ],
|
||||
@@ -221,6 +222,13 @@ var interfaceConfig = {
|
||||
* milliseconds, those notifications should remain displayed.
|
||||
*/
|
||||
// ENFORCE_NOTIFICATION_AUTO_DISMISS_TIMEOUT: 15000,
|
||||
|
||||
// List of undocumented settings
|
||||
/**
|
||||
INDICATOR_FONT_SIZES
|
||||
MOBILE_DYNAMIC_LINK
|
||||
PHONE_NUMBER_REGEX
|
||||
*/
|
||||
};
|
||||
|
||||
/* eslint-enable no-unused-vars, no-var, max-len */
|
||||
|
||||
24
ios/Podfile
24
ios/Podfile
@@ -17,9 +17,20 @@ target 'JitsiMeet' do
|
||||
# React Native and its dependencies
|
||||
#
|
||||
|
||||
pod 'FBLazyVector', :path => '../node_modules/react-native/Libraries/FBLazyVector/'
|
||||
pod 'FBReactNativeSpec', :path => '../node_modules/react-native/Libraries/FBReactNativeSpec/'
|
||||
pod 'RCTRequired', :path => '../node_modules/react-native/Libraries/RCTRequired/'
|
||||
pod 'RCTTypeSafety', :path => '../node_modules/react-native/Libraries/TypeSafety/'
|
||||
pod 'React', :path => '../node_modules/react-native/'
|
||||
pod 'React-Core', :path => '../node_modules/react-native/React'
|
||||
pod 'React-DevSupport', :path => '../node_modules/react-native/React'
|
||||
pod 'ReactCommon', :path => '../node_modules/react-native/ReactCommon', :subspecs => [
|
||||
'turbomodule'
|
||||
]
|
||||
pod 'React-Core', :path => '../node_modules/react-native/', :subspecs => [
|
||||
'CoreModulesHeaders',
|
||||
'DevSupport',
|
||||
'RCTWebSocket'
|
||||
]
|
||||
pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
|
||||
pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
|
||||
pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
|
||||
pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
|
||||
@@ -29,13 +40,12 @@ target 'JitsiMeet' do
|
||||
pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
|
||||
pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
|
||||
pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
|
||||
pod 'React-RCTWebSocket', :path => '../node_modules/react-native/Libraries/WebSocket'
|
||||
|
||||
pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
|
||||
pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
|
||||
pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
|
||||
pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
|
||||
pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
|
||||
pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
|
||||
|
||||
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
|
||||
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
|
||||
@@ -52,9 +62,9 @@ target 'JitsiMeet' do
|
||||
pod 'react-native-webrtc', :path => '../node_modules/react-native-webrtc'
|
||||
pod 'BVLinearGradient', :path => '../node_modules/react-native-linear-gradient'
|
||||
pod 'RNCAsyncStorage', :path => '../node_modules/@react-native-community/async-storage'
|
||||
pod 'RNGoogleSignin', :path => '../node_modules/react-native-google-signin'
|
||||
pod 'RNGoogleSignin', :path => '../node_modules/@react-native-community/google-signin'
|
||||
pod 'RNSound', :path => '../node_modules/react-native-sound'
|
||||
pod 'RNVectorIcons', :path => '../node_modules/react-native-vector-icons'
|
||||
pod 'RNSVG', :path => '../node_modules/react-native-svg'
|
||||
pod 'RNWatch', :path => '../node_modules/react-native-watch-connectivity'
|
||||
|
||||
# Native pod dependencies
|
||||
@@ -71,6 +81,8 @@ post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
target.build_configurations.each do |config|
|
||||
config.build_settings['ENABLE_BITCODE'] = 'YES'
|
||||
config.build_settings['SUPPORTS_MACCATALYST'] = 'NO'
|
||||
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '10.0'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
410
ios/Podfile.lock
410
ios/Podfile.lock
@@ -1,5 +1,10 @@
|
||||
PODS:
|
||||
- Amplitude-iOS (4.0.4)
|
||||
- AppAuth (1.2.0):
|
||||
- AppAuth/Core (= 1.2.0)
|
||||
- AppAuth/ExternalUserAgent (= 1.2.0)
|
||||
- AppAuth/Core (1.2.0)
|
||||
- AppAuth/ExternalUserAgent (1.2.0)
|
||||
- boost-for-react-native (1.63.0)
|
||||
- BVLinearGradient (2.5.6):
|
||||
- React
|
||||
@@ -10,6 +15,14 @@ PODS:
|
||||
- Fabric (~> 1.9.0)
|
||||
- DoubleConversion (1.1.6)
|
||||
- Fabric (1.9.0)
|
||||
- FBLazyVector (0.61.3)
|
||||
- FBReactNativeSpec (0.61.3):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- RCTRequired (= 0.61.3)
|
||||
- RCTTypeSafety (= 0.61.3)
|
||||
- React-Core (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- ReactCommon/turbomodule/core (= 0.61.3)
|
||||
- Firebase/Core (5.18.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseAnalytics (= 5.7.0)
|
||||
@@ -54,18 +67,10 @@ PODS:
|
||||
- GoogleUtilities/Network (~> 5.2)
|
||||
- "GoogleUtilities/NSData+zlib (~> 5.2)"
|
||||
- nanopb (~> 0.3)
|
||||
- GoogleSignIn (4.4.0):
|
||||
- "GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)"
|
||||
- "GoogleToolboxForMac/NSString+URLArguments (~> 2.1)"
|
||||
- GoogleSignIn (5.0.1):
|
||||
- AppAuth (~> 1.2)
|
||||
- GTMAppAuth (~> 1.0)
|
||||
- GTMSessionFetcher/Core (~> 1.1)
|
||||
- GoogleToolboxForMac/DebugUtils (2.2.0):
|
||||
- GoogleToolboxForMac/Defines (= 2.2.0)
|
||||
- GoogleToolboxForMac/Defines (2.2.0)
|
||||
- "GoogleToolboxForMac/NSDictionary+URLArguments (2.2.0)":
|
||||
- GoogleToolboxForMac/DebugUtils (= 2.2.0)
|
||||
- GoogleToolboxForMac/Defines (= 2.2.0)
|
||||
- "GoogleToolboxForMac/NSString+URLArguments (= 2.2.0)"
|
||||
- "GoogleToolboxForMac/NSString+URLArguments (2.2.0)"
|
||||
- GoogleUtilities/AppDelegateSwizzler (5.4.1):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Logger
|
||||
@@ -84,58 +89,183 @@ PODS:
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/UserDefaults (5.4.1):
|
||||
- GoogleUtilities/Logger
|
||||
- GTMSessionFetcher/Core (1.2.1)
|
||||
- GTMAppAuth (1.0.0):
|
||||
- AppAuth/Core (~> 1.0)
|
||||
- GTMSessionFetcher (~> 1.1)
|
||||
- GTMSessionFetcher (1.2.2):
|
||||
- GTMSessionFetcher/Full (= 1.2.2)
|
||||
- GTMSessionFetcher/Core (1.2.2)
|
||||
- GTMSessionFetcher/Full (1.2.2):
|
||||
- GTMSessionFetcher/Core (= 1.2.2)
|
||||
- nanopb (0.3.901):
|
||||
- nanopb/decode (= 0.3.901)
|
||||
- nanopb/encode (= 0.3.901)
|
||||
- nanopb/decode (0.3.901)
|
||||
- nanopb/encode (0.3.901)
|
||||
- ObjectiveDropboxOfficial (3.9.4)
|
||||
- React (0.60.5):
|
||||
- React-Core (= 0.60.5)
|
||||
- React-DevSupport (= 0.60.5)
|
||||
- React-RCTActionSheet (= 0.60.5)
|
||||
- React-RCTAnimation (= 0.60.5)
|
||||
- React-RCTBlob (= 0.60.5)
|
||||
- React-RCTImage (= 0.60.5)
|
||||
- React-RCTLinking (= 0.60.5)
|
||||
- React-RCTNetwork (= 0.60.5)
|
||||
- React-RCTSettings (= 0.60.5)
|
||||
- React-RCTText (= 0.60.5)
|
||||
- React-RCTVibration (= 0.60.5)
|
||||
- React-RCTWebSocket (= 0.60.5)
|
||||
- React-Core (0.60.5):
|
||||
- RCTRequired (0.61.3)
|
||||
- RCTTypeSafety (0.61.3):
|
||||
- FBLazyVector (= 0.61.3)
|
||||
- Folly (= 2018.10.22.00)
|
||||
- React-cxxreact (= 0.60.5)
|
||||
- React-jsiexecutor (= 0.60.5)
|
||||
- yoga (= 0.60.5.React)
|
||||
- React-cxxreact (0.60.5):
|
||||
- RCTRequired (= 0.61.3)
|
||||
- React-Core (= 0.61.3)
|
||||
- React (0.61.3):
|
||||
- React-Core (= 0.61.3)
|
||||
- React-Core/DevSupport (= 0.61.3)
|
||||
- React-Core/RCTWebSocket (= 0.61.3)
|
||||
- React-RCTActionSheet (= 0.61.3)
|
||||
- React-RCTAnimation (= 0.61.3)
|
||||
- React-RCTBlob (= 0.61.3)
|
||||
- React-RCTImage (= 0.61.3)
|
||||
- React-RCTLinking (= 0.61.3)
|
||||
- React-RCTNetwork (= 0.61.3)
|
||||
- React-RCTSettings (= 0.61.3)
|
||||
- React-RCTText (= 0.61.3)
|
||||
- React-RCTVibration (= 0.61.3)
|
||||
- React-Core (0.61.3):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default (= 0.61.3)
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- React-jsiexecutor (= 0.61.3)
|
||||
- Yoga
|
||||
- React-Core/CoreModulesHeaders (0.61.3):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- React-jsiexecutor (= 0.61.3)
|
||||
- Yoga
|
||||
- React-Core/Default (0.61.3):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- React-jsiexecutor (= 0.61.3)
|
||||
- Yoga
|
||||
- React-Core/DevSupport (0.61.3):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default (= 0.61.3)
|
||||
- React-Core/RCTWebSocket (= 0.61.3)
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- React-jsiexecutor (= 0.61.3)
|
||||
- React-jsinspector (= 0.61.3)
|
||||
- Yoga
|
||||
- React-Core/RCTActionSheetHeaders (0.61.3):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- React-jsiexecutor (= 0.61.3)
|
||||
- Yoga
|
||||
- React-Core/RCTAnimationHeaders (0.61.3):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- React-jsiexecutor (= 0.61.3)
|
||||
- Yoga
|
||||
- React-Core/RCTBlobHeaders (0.61.3):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- React-jsiexecutor (= 0.61.3)
|
||||
- Yoga
|
||||
- React-Core/RCTImageHeaders (0.61.3):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- React-jsiexecutor (= 0.61.3)
|
||||
- Yoga
|
||||
- React-Core/RCTLinkingHeaders (0.61.3):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- React-jsiexecutor (= 0.61.3)
|
||||
- Yoga
|
||||
- React-Core/RCTNetworkHeaders (0.61.3):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- React-jsiexecutor (= 0.61.3)
|
||||
- Yoga
|
||||
- React-Core/RCTSettingsHeaders (0.61.3):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- React-jsiexecutor (= 0.61.3)
|
||||
- Yoga
|
||||
- React-Core/RCTTextHeaders (0.61.3):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- React-jsiexecutor (= 0.61.3)
|
||||
- Yoga
|
||||
- React-Core/RCTVibrationHeaders (0.61.3):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- React-jsiexecutor (= 0.61.3)
|
||||
- Yoga
|
||||
- React-Core/RCTWebSocket (0.61.3):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default (= 0.61.3)
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- React-jsiexecutor (= 0.61.3)
|
||||
- Yoga
|
||||
- React-CoreModules (0.61.3):
|
||||
- FBReactNativeSpec (= 0.61.3)
|
||||
- Folly (= 2018.10.22.00)
|
||||
- RCTTypeSafety (= 0.61.3)
|
||||
- React-Core/CoreModulesHeaders (= 0.61.3)
|
||||
- React-RCTImage (= 0.61.3)
|
||||
- ReactCommon/turbomodule/core (= 0.61.3)
|
||||
- React-cxxreact (0.61.3):
|
||||
- boost-for-react-native (= 1.63.0)
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-jsinspector (= 0.60.5)
|
||||
- React-DevSupport (0.60.5):
|
||||
- React-Core (= 0.60.5)
|
||||
- React-RCTWebSocket (= 0.60.5)
|
||||
- React-jsi (0.60.5):
|
||||
- React-jsinspector (= 0.61.3)
|
||||
- React-jsi (0.61.3):
|
||||
- boost-for-react-native (= 1.63.0)
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-jsi/Default (= 0.60.5)
|
||||
- React-jsi/Default (0.60.5):
|
||||
- React-jsi/Default (= 0.61.3)
|
||||
- React-jsi/Default (0.61.3):
|
||||
- boost-for-react-native (= 1.63.0)
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-jsiexecutor (0.60.5):
|
||||
- React-jsiexecutor (0.61.3):
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-cxxreact (= 0.60.5)
|
||||
- React-jsi (= 0.60.5)
|
||||
- React-jsinspector (0.60.5)
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- React-jsinspector (0.61.3)
|
||||
- react-native-background-timer (2.1.1):
|
||||
- React
|
||||
- react-native-calendar-events (1.7.3):
|
||||
@@ -146,46 +276,77 @@ PODS:
|
||||
- React
|
||||
- react-native-webrtc (1.75.0):
|
||||
- React
|
||||
- react-native-webview (5.8.1):
|
||||
- react-native-webview (7.4.1):
|
||||
- React
|
||||
- React-RCTActionSheet (0.60.5):
|
||||
- React-Core (= 0.60.5)
|
||||
- React-RCTAnimation (0.60.5):
|
||||
- React-Core (= 0.60.5)
|
||||
- React-RCTBlob (0.60.5):
|
||||
- React-Core (= 0.60.5)
|
||||
- React-RCTNetwork (= 0.60.5)
|
||||
- React-RCTWebSocket (= 0.60.5)
|
||||
- React-RCTImage (0.60.5):
|
||||
- React-Core (= 0.60.5)
|
||||
- React-RCTNetwork (= 0.60.5)
|
||||
- React-RCTLinking (0.60.5):
|
||||
- React-Core (= 0.60.5)
|
||||
- React-RCTNetwork (0.60.5):
|
||||
- React-Core (= 0.60.5)
|
||||
- React-RCTSettings (0.60.5):
|
||||
- React-Core (= 0.60.5)
|
||||
- React-RCTText (0.60.5):
|
||||
- React-Core (= 0.60.5)
|
||||
- React-RCTVibration (0.60.5):
|
||||
- React-Core (= 0.60.5)
|
||||
- React-RCTWebSocket (0.60.5):
|
||||
- React-Core (= 0.60.5)
|
||||
- React-RCTActionSheet (0.61.3):
|
||||
- React-Core/RCTActionSheetHeaders (= 0.61.3)
|
||||
- React-RCTAnimation (0.61.3):
|
||||
- React-Core/RCTAnimationHeaders (= 0.61.3)
|
||||
- React-RCTBlob (0.61.3):
|
||||
- React-Core/RCTBlobHeaders (= 0.61.3)
|
||||
- React-Core/RCTWebSocket (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- React-RCTNetwork (= 0.61.3)
|
||||
- React-RCTImage (0.61.3):
|
||||
- React-Core/RCTImageHeaders (= 0.61.3)
|
||||
- React-RCTNetwork (= 0.61.3)
|
||||
- React-RCTLinking (0.61.3):
|
||||
- React-Core/RCTLinkingHeaders (= 0.61.3)
|
||||
- React-RCTNetwork (0.61.3):
|
||||
- React-Core/RCTNetworkHeaders (= 0.61.3)
|
||||
- React-RCTSettings (0.61.3):
|
||||
- React-Core/RCTSettingsHeaders (= 0.61.3)
|
||||
- React-RCTText (0.61.3):
|
||||
- React-Core/RCTTextHeaders (= 0.61.3)
|
||||
- React-RCTVibration (0.61.3):
|
||||
- React-Core/RCTVibrationHeaders (= 0.61.3)
|
||||
- ReactCommon/jscallinvoker (0.61.3):
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- ReactCommon/turbomodule (0.61.3):
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core (= 0.61.3)
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- ReactCommon/jscallinvoker (= 0.61.3)
|
||||
- ReactCommon/turbomodule/core (= 0.61.3)
|
||||
- ReactCommon/turbomodule/samples (= 0.61.3)
|
||||
- ReactCommon/turbomodule/core (0.61.3):
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core (= 0.61.3)
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- ReactCommon/jscallinvoker (= 0.61.3)
|
||||
- ReactCommon/turbomodule/samples (0.61.3):
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core (= 0.61.3)
|
||||
- React-cxxreact (= 0.61.3)
|
||||
- React-jsi (= 0.61.3)
|
||||
- ReactCommon/jscallinvoker (= 0.61.3)
|
||||
- ReactCommon/turbomodule/core (= 0.61.3)
|
||||
- RNCAsyncStorage (1.3.4):
|
||||
- React
|
||||
- RNGoogleSignin (2.0.0):
|
||||
- GoogleSignIn (~> 4.4.0)
|
||||
- RNGoogleSignin (3.0.1):
|
||||
- GoogleSignIn (~> 5.0.0)
|
||||
- React
|
||||
- RNSound (0.11.0):
|
||||
- React
|
||||
- RNSound/Core (= 0.11.0)
|
||||
- RNSound/Core (0.11.0):
|
||||
- React
|
||||
- RNVectorIcons (6.0.2):
|
||||
- RNSVG (9.7.1):
|
||||
- React
|
||||
- RNWatch (0.2.0):
|
||||
- React
|
||||
- yoga (0.60.5.React)
|
||||
- Yoga (1.14.0)
|
||||
|
||||
DEPENDENCIES:
|
||||
- Amplitude-iOS (~> 4.0.4)
|
||||
@@ -194,15 +355,21 @@ DEPENDENCIES:
|
||||
- Crashlytics (~> 3.12.0)
|
||||
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
|
||||
- Fabric (~> 1.9.0)
|
||||
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector/`)
|
||||
- FBReactNativeSpec (from `../node_modules/react-native/Libraries/FBReactNativeSpec/`)
|
||||
- Firebase/Core (~> 5.18.0)
|
||||
- Firebase/DynamicLinks (~> 5.18.0)
|
||||
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
|
||||
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
|
||||
- ObjectiveDropboxOfficial (~> 3.9.4)
|
||||
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired/`)
|
||||
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety/`)
|
||||
- React (from `../node_modules/react-native/`)
|
||||
- React-Core (from `../node_modules/react-native/React`)
|
||||
- React-Core/CoreModulesHeaders (from `../node_modules/react-native/`)
|
||||
- React-Core/DevSupport (from `../node_modules/react-native/`)
|
||||
- React-Core/RCTWebSocket (from `../node_modules/react-native/`)
|
||||
- React-CoreModules (from `../node_modules/react-native/React/CoreModules`)
|
||||
- React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`)
|
||||
- React-DevSupport (from `../node_modules/react-native/React`)
|
||||
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
|
||||
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
|
||||
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
|
||||
@@ -221,16 +388,16 @@ DEPENDENCIES:
|
||||
- React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`)
|
||||
- React-RCTText (from `../node_modules/react-native/Libraries/Text`)
|
||||
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
|
||||
- React-RCTWebSocket (from `../node_modules/react-native/Libraries/WebSocket`)
|
||||
- ReactCommon/turbomodule (from `../node_modules/react-native/ReactCommon`)
|
||||
- "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)"
|
||||
- RNGoogleSignin (from `../node_modules/react-native-google-signin`)
|
||||
- "RNGoogleSignin (from `../node_modules/@react-native-community/google-signin`)"
|
||||
- RNSound (from `../node_modules/react-native-sound`)
|
||||
- RNVectorIcons (from `../node_modules/react-native-vector-icons`)
|
||||
- RNSVG (from `../node_modules/react-native-svg`)
|
||||
- RNWatch (from `../node_modules/react-native-watch-connectivity`)
|
||||
- yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/cocoapods/specs.git:
|
||||
https://github.com/CocoaPods/Specs.git:
|
||||
- Amplitude-iOS
|
||||
- boost-for-react-native
|
||||
- CocoaLumberjack
|
||||
@@ -243,30 +410,40 @@ SPEC REPOS:
|
||||
- FirebaseDynamicLinks
|
||||
- FirebaseInstanceID
|
||||
- GoogleAppMeasurement
|
||||
- GoogleSignIn
|
||||
- GoogleToolboxForMac
|
||||
- GoogleUtilities
|
||||
- GTMSessionFetcher
|
||||
- nanopb
|
||||
- ObjectiveDropboxOfficial
|
||||
trunk:
|
||||
- AppAuth
|
||||
- GoogleSignIn
|
||||
- GTMAppAuth
|
||||
- GTMSessionFetcher
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
BVLinearGradient:
|
||||
:path: "../node_modules/react-native-linear-gradient"
|
||||
DoubleConversion:
|
||||
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
|
||||
FBLazyVector:
|
||||
:path: "../node_modules/react-native/Libraries/FBLazyVector/"
|
||||
FBReactNativeSpec:
|
||||
:path: "../node_modules/react-native/Libraries/FBReactNativeSpec/"
|
||||
Folly:
|
||||
:podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec"
|
||||
glog:
|
||||
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
|
||||
RCTRequired:
|
||||
:path: "../node_modules/react-native/Libraries/RCTRequired/"
|
||||
RCTTypeSafety:
|
||||
:path: "../node_modules/react-native/Libraries/TypeSafety/"
|
||||
React:
|
||||
:path: "../node_modules/react-native/"
|
||||
React-Core:
|
||||
:path: "../node_modules/react-native/React"
|
||||
:path: "../node_modules/react-native/"
|
||||
React-CoreModules:
|
||||
:path: "../node_modules/react-native/React/CoreModules"
|
||||
React-cxxreact:
|
||||
:path: "../node_modules/react-native/ReactCommon/cxxreact"
|
||||
React-DevSupport:
|
||||
:path: "../node_modules/react-native/React"
|
||||
React-jsi:
|
||||
:path: "../node_modules/react-native/ReactCommon/jsi"
|
||||
React-jsiexecutor:
|
||||
@@ -303,29 +480,32 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/Libraries/Text"
|
||||
React-RCTVibration:
|
||||
:path: "../node_modules/react-native/Libraries/Vibration"
|
||||
React-RCTWebSocket:
|
||||
:path: "../node_modules/react-native/Libraries/WebSocket"
|
||||
ReactCommon:
|
||||
:path: "../node_modules/react-native/ReactCommon"
|
||||
RNCAsyncStorage:
|
||||
:path: "../node_modules/@react-native-community/async-storage"
|
||||
RNGoogleSignin:
|
||||
:path: "../node_modules/react-native-google-signin"
|
||||
:path: "../node_modules/@react-native-community/google-signin"
|
||||
RNSound:
|
||||
:path: "../node_modules/react-native-sound"
|
||||
RNVectorIcons:
|
||||
:path: "../node_modules/react-native-vector-icons"
|
||||
RNSVG:
|
||||
:path: "../node_modules/react-native-svg"
|
||||
RNWatch:
|
||||
:path: "../node_modules/react-native-watch-connectivity"
|
||||
yoga:
|
||||
Yoga:
|
||||
:path: "../node_modules/react-native/ReactCommon/yoga"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Amplitude-iOS: 2ad4d7270c99186236c1272a3a9425463b1ae1a7
|
||||
AppAuth: bce82c76043657c99d91e7882e8a9e1a93650cd4
|
||||
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
|
||||
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
|
||||
CocoaLumberjack: 2f44e60eb91c176d471fdba43b9e3eae6a721947
|
||||
Crashlytics: 07fb167b1694128c1c9a5a5cc319b0e9c3ca0933
|
||||
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
|
||||
Fabric: f988e33c97f08930a413e08123064d2e5f68d655
|
||||
FBLazyVector: 5bc5b1606fc9a7ac6956de049f6e30901ed31c49
|
||||
FBReactNativeSpec: f7be9bcc5ce259f7c39509f3f4caf59020d11d4c
|
||||
Firebase: 02f3281965c075426141a0ce1277e9de6649cab9
|
||||
FirebaseAnalytics: 23851fe602c872130a2c5c55040b302120346cc2
|
||||
FirebaseAnalyticsInterop: efbe45c8385ec626e29f9525e5ebd38520dfb6c1
|
||||
@@ -335,42 +515,44 @@ SPEC CHECKSUMS:
|
||||
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
|
||||
glog: 1f3da668190260b06b429bb211bfbee5cd790c28
|
||||
GoogleAppMeasurement: 6cf307834da065863f9faf4c0de0a936d81dd832
|
||||
GoogleSignIn: 7ff245e1a7b26d379099d3243a562f5747e23d39
|
||||
GoogleToolboxForMac: ff31605b7d66400dcec09bed5861689aebadda4d
|
||||
GoogleSignIn: 3a51b9bb8e48b635fd7f4272cee06ca260345b86
|
||||
GoogleUtilities: 1e25823cbf46540b4284f6ef8e17b3a68ee12bbc
|
||||
GTMSessionFetcher: 32aeca0aa144acea523e1c8e053089dec2cb98ca
|
||||
GTMAppAuth: 4deac854479704f348309e7b66189e604cf5e01e
|
||||
GTMSessionFetcher: 61bb0f61a4cb560030f1222021178008a5727a23
|
||||
nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48
|
||||
ObjectiveDropboxOfficial: a5afefc83f6467c42c45f2253f583f2ad1ffc701
|
||||
React: 53c53c4d99097af47cf60594b8706b4e3321e722
|
||||
React-Core: ba421f6b4f4cbe2fb17c0b6fc675f87622e78a64
|
||||
React-cxxreact: 8384287780c4999351ad9b6e7a149d9ed10a2395
|
||||
React-DevSupport: 197fb409737cff2c4f9986e77c220d7452cb9f9f
|
||||
React-jsi: 4d8c9efb6312a9725b18d6fc818ffc103f60fec2
|
||||
React-jsiexecutor: 90ad2f9db09513fc763bc757fdc3c4ff8bde2a30
|
||||
React-jsinspector: e08662d1bf5b129a3d556eb9ea343a3f40353ae4
|
||||
RCTRequired: a72523286ea3381f97b28d87529c265baad3ad7d
|
||||
RCTTypeSafety: e3cc0537400222250f0be37bd69f4b339d3c0a0f
|
||||
React: 3dc877fc32548b0c7108ca7f301466f4956cbff8
|
||||
React-Core: ca94e2e7d22cdcc266a405c4d2ad5e5675145776
|
||||
React-CoreModules: aa415458b5d7dacd10ac1b324d679f6e17cd8685
|
||||
React-cxxreact: bac5da3d62ee98abd3c1bf7338a7cc6205da7f69
|
||||
React-jsi: 8bcf5836caa8a759c135ab9ef97f3e023a7b94af
|
||||
React-jsiexecutor: ae078e9df9c65bcdcf68f9a17656657932d95528
|
||||
React-jsinspector: a8939cc6909607eb5e8a5ecfff7c6226984e174d
|
||||
react-native-background-timer: 0d34748e53a972507c66963490c775321a88f6f2
|
||||
react-native-calendar-events: 2fe35a9294af05de0ed819d3a1b5dac048d2c010
|
||||
react-native-keep-awake: eba3137546b10003361b37c761f6c429b59814ae
|
||||
react-native-netinfo: 8d8db463bcc5db66a8ac5c48a7d86beb3b92f61a
|
||||
react-native-webrtc: c5e3d631179a933548a8e49bddbd8fad02586095
|
||||
react-native-webview: a95842e3f351a6d2c8bc8bcc9eab689c7e7e5ad4
|
||||
React-RCTActionSheet: b0f1ea83f4bf75fb966eae9bfc47b78c8d3efd90
|
||||
React-RCTAnimation: 359ba1b5690b1e87cc173558a78e82d35919333e
|
||||
React-RCTBlob: 5e2b55f76e9a1c7ae52b826923502ddc3238df24
|
||||
React-RCTImage: f5f1c50922164e89bdda67bcd0153952a5cfe719
|
||||
React-RCTLinking: d0ecbd791e9ddddc41fa1f66b0255de90e8ee1e9
|
||||
React-RCTNetwork: e26946300b0ab7bb6c4a6348090e93fa21f33a9d
|
||||
React-RCTSettings: d0d37cb521b7470c998595a44f05847777cc3f42
|
||||
React-RCTText: b074d89033583d4f2eb5faf7ea2db3a13c7553a2
|
||||
React-RCTVibration: 2105b2e0e2b66a6408fc69a46c8a7fb5b2fdade0
|
||||
React-RCTWebSocket: cd932a16b7214898b6b7f788c8bddb3637246ac4
|
||||
react-native-webview: 4dbc1d2a4a6b9c5e9e723c62651917aa2b5e579e
|
||||
React-RCTActionSheet: 94671eef55b01a93be735605822ef712d5ea208e
|
||||
React-RCTAnimation: 524ae33e73de9c0fe6501a7a4bda8e01d26499d9
|
||||
React-RCTBlob: 5481c2db702f57207af7e7a9b32d90524b821b72
|
||||
React-RCTImage: b472cc0606f8a7c1ac270d6ccc57123a09439a32
|
||||
React-RCTLinking: 9cfc7bfdfda078489736695ac476de1f265b9f82
|
||||
React-RCTNetwork: 967547e4eeac92e55d41573a82da7fff4003052a
|
||||
React-RCTSettings: 6ab7911172056b5077dacd9240f057eeeb1b121b
|
||||
React-RCTText: b8f895b94aa0e7778fef28d13f3d71eed4a10c3d
|
||||
React-RCTVibration: 262588c97551b0b1c675468cda857466ba5af18f
|
||||
ReactCommon: c2c63d9290b422ca6ad5b3663073a015dd892ae9
|
||||
RNCAsyncStorage: 8e31405a9f12fbf42c2bb330e4560bfd79c18323
|
||||
RNGoogleSignin: d030c6c6591db24c3cee649f64c7babf0a1699a0
|
||||
RNGoogleSignin: 39336070b35fc4cea6a98cf111e00480317be0ae
|
||||
RNSound: c980916b596cc15c8dcd2f6ecd3b13c4881dbe20
|
||||
RNVectorIcons: d819334932bcda3332deb3d2c8ea4d069e0b98f9
|
||||
RNSVG: aac12785382e8fd4f28d072fe640612e34914631
|
||||
RNWatch: 09738b339eceb66e4d80a2371633ca5fb380fa42
|
||||
yoga: 312528f5bbbba37b4dcea5ef00e8b4033fdd9411
|
||||
Yoga: 02036f6383c0008edb7ef0773a0e6beb6ce82bd1
|
||||
|
||||
PODFILE CHECKSUM: 0e3406a4217cc348dcadad5b016e8d939d4aa61f
|
||||
PODFILE CHECKSUM: 63c90b1d33cd96709fb72bad6be440ae9c3deecb
|
||||
|
||||
COCOAPODS: 1.7.2
|
||||
COCOAPODS: 1.8.1
|
||||
|
||||
@@ -41,8 +41,6 @@
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
@@ -52,8 +50,8 @@
|
||||
ReferencedContainer = "container:app.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
@@ -75,8 +73,6 @@
|
||||
ReferencedContainer = "container:app.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>19.3.0</string>
|
||||
<string>19.4.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>19.3.0</string>
|
||||
<string>19.4.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>19.3.0</string>
|
||||
<string>19.4.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>CLKComplicationPrincipalClass</key>
|
||||
|
||||
103
ios/ci/build-ipa.sh
Executable file
103
ios/ci/build-ipa.sh
Executable file
@@ -0,0 +1,103 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Mandatory arguments with no default values provided:
|
||||
# PR_REPO_SLUG - the Github name of the repo to be merged into the origin/master
|
||||
# PR_BRANCH - the branch to be merged, if set to "master" no merge will happen
|
||||
# IPA_DEPLOY_LOCATION - the location understandable by the "scp" command
|
||||
# executed at the end of the script to deploy the output .ipa file
|
||||
# LIB_JITSI_MEET_PKG (optional) - the npm package for lib-jitsi-meet which will
|
||||
# be put in place of the current version in the package.json file.
|
||||
#
|
||||
# Other than that the script requires the following env variables to be set:
|
||||
#
|
||||
# DEPLOY_SSH_CERT_URL - the SSH private key used by the 'scp' command to deploy
|
||||
# the .ipa. It is expected to be encrypted with the $ENCRYPTION_PASSWORD.
|
||||
# ENCRYPTION_PASSWORD - the password used to decrypt certificate/key files used
|
||||
# in the script.
|
||||
# IOS_TEAM_ID - the team ID inserted into build-ipa-.plist.template file in
|
||||
# place of "YOUR_TEAM_ID".
|
||||
|
||||
function echoAndExit1() {
|
||||
echo $1
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ -z $PR_REPO_SLUG ]; then
|
||||
echoAndExit1 "No PR_REPO_SLUG defined"
|
||||
fi
|
||||
if [ -z $PR_BRANCH ]; then
|
||||
echoAndExit1 "No PR_BRANCH defined"
|
||||
fi
|
||||
if [ -z $IPA_DEPLOY_LOCATION ]; then
|
||||
echoAndExit1 "No IPA_DEPLOY_LOCATION defined"
|
||||
fi
|
||||
|
||||
echo "PR_REPO_SLUG=${PR_REPO_SLUG} PR_BRANCH=${PR_BRANCH}"
|
||||
|
||||
# do the marge and git log
|
||||
|
||||
if [ $PR_BRANCH != "master" ]; then
|
||||
echo "Will merge ${PR_REPO_SLUG}/${PR_BRANCH} into master"
|
||||
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
|
||||
git fetch origin master
|
||||
git checkout master
|
||||
git pull https://github.com/${PR_REPO_SLUG}.git $PR_BRANCH --no-edit
|
||||
fi
|
||||
|
||||
# Link this lib-jitsi-meet checkout in jitsi-meet through the package.json
|
||||
if [ ! -z ${LIB_JITSI_MEET_PKG} ];
|
||||
then
|
||||
echo "Adjusting lib-jitsi-meet package in package.json to ${LIB_JITSI_MEET_PKG}"
|
||||
# escape for the sed
|
||||
LIB_JITSI_MEET_PKG=$(echo $LIB_JITSI_MEET_PKG | sed -e 's/\\/\\\\/g; s/\//\\\//g; s/&/\\\&/g')
|
||||
sed -i.bak -e "s/\"lib-jitsi-meet.*/\"lib-jitsi-meet\"\: \"${LIB_JITSI_MEET_PKG}\",/g" package.json
|
||||
echo "Package.json lib-jitsi-meet line:"
|
||||
grep lib-jitsi-meet package.json
|
||||
else
|
||||
echo "LIB_JITSI_MEET_PKG var not set - will not modify the package.json"
|
||||
fi
|
||||
|
||||
git log -20 --graph --pretty=format':%C(yellow)%h%Cblue%d%Creset %s %C(white) %an, %ar%Creset'
|
||||
|
||||
# certificates
|
||||
|
||||
CERT_DIR="ios/ci/certs"
|
||||
|
||||
mkdir -p $CERT_DIR
|
||||
|
||||
curl -L -o ${CERT_DIR}/id_rsa.enc ${DEPLOY_SSH_CERT_URL}
|
||||
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/id_rsa.enc -d -a -out ${CERT_DIR}/id_rsa
|
||||
chmod 0600 ${CERT_DIR}/id_rsa
|
||||
ssh-add ${CERT_DIR}/id_rsa
|
||||
|
||||
npm install
|
||||
|
||||
# Ever since the Apple Watch app has been added the bitcode for WebRTC needs to be downloaded in order to build successfully
|
||||
./node_modules/react-native-webrtc/tools/downloadBitcode.sh
|
||||
|
||||
cd ios
|
||||
pod install --repo-update --no-ansi
|
||||
cd ..
|
||||
|
||||
mkdir -p /tmp/jitsi-meet/
|
||||
|
||||
xcodebuild archive -quiet -workspace ios/jitsi-meet.xcworkspace -scheme jitsi-meet -configuration Release -archivePath /tmp/jitsi-meet/jitsi-meet.xcarchive
|
||||
|
||||
sed -e "s/YOUR_TEAM_ID/${IOS_TEAM_ID}/g" ios/ci/build-ipa.plist.template > ios/ci/build-ipa.plist
|
||||
|
||||
IPA_EXPORT_DIR=/tmp/jitsi-meet/jitsi-meet-ipa
|
||||
|
||||
xcodebuild -quiet -exportArchive -archivePath /tmp/jitsi-meet/jitsi-meet.xcarchive -exportPath $IPA_EXPORT_DIR -exportOptionsPlist ios/ci/build-ipa.plist
|
||||
|
||||
echo "Will try deploy the .ipa to: ${IPA_DEPLOY_LOCATION}"
|
||||
|
||||
if [ ! -z ${SCP_PROXY_HOST} ];
|
||||
then
|
||||
scp -o ProxyCommand="ssh -t -A -l %r ${SCP_PROXY_HOST} -o \"StrictHostKeyChecking no\" -o \"BatchMode yes\" -W %h:%p" -o StrictHostKeyChecking=no -o LogLevel=DEBUG "${IPA_EXPORT_DIR}/jitsi-meet.ipa" "${IPA_DEPLOY_LOCATION}"
|
||||
else
|
||||
scp -o StrictHostKeyChecking=no -o LogLevel=DEBUG "${IPA_EXPORT_DIR}/jitsi-meet.ipa" "${IPA_DEPLOY_LOCATION}"
|
||||
fi
|
||||
|
||||
rm -r /tmp/jitsi-meet/
|
||||
rm -r $CERT_DIR
|
||||
100
ios/ci/setup-certificates.sh
Executable file
100
ios/ci/setup-certificates.sh
Executable file
@@ -0,0 +1,100 @@
|
||||
# The script is based on tutorial written by Antonis Tsakiridis published at:
|
||||
# https://medium.com/@atsakiridis/continuous-deployment-for-ios-using-travis-ci-55dcea342d9
|
||||
#
|
||||
# APPLE_CERT_URL - the URL pointing to Apple certificate (set to
|
||||
# http://developer.apple.com/certificationauthority/AppleWWDRCA.cer by default)
|
||||
# DEPLOY_SSH_CERT_URL - the SSH private key used by the 'scp' command to deploy
|
||||
# the .ipa. It is expected to be encrypted with the $ENCRYPTION_PASSWORD.
|
||||
# ENCRYPTION_PASSWORD - the password used to decrypt certificate/key files used
|
||||
# in the script.
|
||||
# IOS_DEV_CERT_KEY_URL - URL pointing to provisioning profile certificate key
|
||||
# file (development-key.p12.enc from the tutorial) encrypted with the
|
||||
# $ENCRYPTION_PASSWORD.
|
||||
# IOS_DEV_CERT_URL - URL pointing to provisioning profile certificate file
|
||||
# (development-cert.cer.enc from the tutorial) encrypted with the
|
||||
# $ENCRYPTION_PASSWORD.
|
||||
# IOS_DEV_PROV_PROFILE_URL - URL pointing to provisioning profile file
|
||||
# (profile-development-olympus.mobileprovision.enc from the tutorial) encrypted
|
||||
# IOS_DEV_WATCH_PROV_PROFILE_URL - URL pointing to watch app provisioning profile file(encrypted).
|
||||
# with the $ENCRYPTION_PASSWORD.
|
||||
# IOS_SIGNING_CERT_PASSWORD - the password to the provisioning profile
|
||||
# certificate key (used to open development-key.p12 from the tutorial).
|
||||
|
||||
function echoAndExit1() {
|
||||
echo $1
|
||||
exit 1
|
||||
}
|
||||
|
||||
CERT_DIR=$1
|
||||
|
||||
if [ -z $CERT_DIR ]; then
|
||||
echoAndExit1 "First argument must be certificates directory"
|
||||
fi
|
||||
|
||||
if [ -z $APPLE_CERT_URL ]; then
|
||||
APPLE_CERT_URL="http://developer.apple.com/certificationauthority/AppleWWDRCA.cer"
|
||||
fi
|
||||
|
||||
if [ -z $DEPLOY_SSH_CERT_URL ]; then
|
||||
echoAndExit1 "DEPLOY_SSH_CERT_URL env var is not defined"
|
||||
fi
|
||||
|
||||
if [ -z $ENCRYPTION_PASSWORD ]; then
|
||||
echoAndExit1 "ENCRYPTION_PASSWORD env var is not defined"
|
||||
fi
|
||||
|
||||
if [ -z $IOS_DEV_CERT_KEY_URL ]; then
|
||||
echoAndExit1 "IOS_DEV_CERT_KEY_URL env var is not defined"
|
||||
fi
|
||||
|
||||
if [ -z $IOS_DEV_CERT_URL ]; then
|
||||
echoAndExit1 "IOS_DEV_CERT_URL env var is not defined"
|
||||
fi
|
||||
|
||||
if [ -z $IOS_DEV_PROV_PROFILE_URL ]; then
|
||||
echoAndExit1 "IOS_DEV_PROV_PROFILE_URL env var is not defined"
|
||||
fi
|
||||
|
||||
if [ -z $IOS_DEV_WATCH_PROV_PROFILE_URL ]; then
|
||||
echoAndExit1 "IOS_DEV_WATCH_PROV_PROFILE_URL env var is not defined"
|
||||
fi
|
||||
|
||||
if [ -z $IOS_SIGNING_CERT_PASSWORD ]; then
|
||||
echoAndExit1 "IOS_SIGNING_CERT_PASSWORD env var is not defined"
|
||||
fi
|
||||
|
||||
# certificates
|
||||
|
||||
curl -L -o ${CERT_DIR}/AppleWWDRCA.cer 'http://developer.apple.com/certificationauthority/AppleWWDRCA.cer'
|
||||
curl -L -o ${CERT_DIR}/dev-cert.cer.enc ${IOS_DEV_CERT_URL}
|
||||
curl -L -o ${CERT_DIR}/dev-key.p12.enc ${IOS_DEV_CERT_KEY_URL}
|
||||
curl -L -o ${CERT_DIR}/dev-profile.mobileprovision.enc ${IOS_DEV_PROV_PROFILE_URL}
|
||||
curl -L -o ${CERT_DIR}/dev-watch-profile.mobileprovision.enc ${IOS_DEV_WATCH_PROV_PROFILE_URL}
|
||||
|
||||
|
||||
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/dev-cert.cer.enc -d -a -out ${CERT_DIR}/dev-cert.cer
|
||||
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/dev-key.p12.enc -d -a -out ${CERT_DIR}/dev-key.p12
|
||||
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/dev-profile.mobileprovision.enc -d -a -out ${CERT_DIR}/dev-profile.mobileprovision
|
||||
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/dev-watch-profile.mobileprovision.enc -d -a -out ${CERT_DIR}/dev-watch-profile.mobileprovision
|
||||
|
||||
security create-keychain -p $ENCRYPTION_PASSWORD ios-build.keychain
|
||||
security default-keychain -s ios-build.keychain
|
||||
security unlock-keychain -p $ENCRYPTION_PASSWORD ios-build.keychain
|
||||
security set-keychain-settings -t 3600 -l ~/Library/Keychains/ios-build.keychain
|
||||
|
||||
echo "importing Apple cert"
|
||||
security import ${CERT_DIR}/AppleWWDRCA.cer -k ios-build.keychain -A
|
||||
echo "importing dev-cert.cer"
|
||||
security import ${CERT_DIR}/dev-cert.cer -k ios-build.keychain -A
|
||||
echo "importing dev-key.p12"
|
||||
security import ${CERT_DIR}/dev-key.p12 -k ios-build.keychain -P $IOS_SIGNING_CERT_PASSWORD -A
|
||||
|
||||
echo "will set-key-partition-list"
|
||||
# Fix for OS X Sierra that hungs in the codesign step
|
||||
security set-key-partition-list -S apple-tool:,apple: -s -k $ENCRYPTION_PASSWORD ios-build.keychain > /dev/null
|
||||
echo "done set-key-partition-list"
|
||||
|
||||
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
|
||||
|
||||
cp "${CERT_DIR}/dev-profile.mobileprovision" ~/Library/MobileDevice/Provisioning\ Profiles/
|
||||
cp "${CERT_DIR}/dev-watch-profile.mobileprovision" ~/Library/MobileDevice/Provisioning\ Profiles/
|
||||
@@ -2,7 +2,7 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildSystemType</key>
|
||||
<string>Original</string>
|
||||
<key>PreviewsEnabled</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
0BCA495F1EC4B6C600B793EE /* AudioMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495C1EC4B6C600B793EE /* AudioMode.m */; };
|
||||
0BCA49601EC4B6C600B793EE /* POSIX.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495D1EC4B6C600B793EE /* POSIX.m */; };
|
||||
0BCA49611EC4B6C600B793EE /* Proximity.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495E1EC4B6C600B793EE /* Proximity.m */; };
|
||||
0BCA496C1EC4BBF900B793EE /* jitsi.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 0BCA496B1EC4BBF900B793EE /* jitsi.ttf */; };
|
||||
0BD906EA1EC0C00300C8C18E /* JitsiMeet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BD906E81EC0C00300C8C18E /* JitsiMeet.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
0F65EECE1D95DA94561BB47E /* libPods-JitsiMeet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 03F2ADC957FF109849B7FCA1 /* libPods-JitsiMeet.a */; };
|
||||
6C31EDC820C06D490089C899 /* recordingOn.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 6C31EDC720C06D490089C899 /* recordingOn.mp3 */; };
|
||||
@@ -43,6 +42,7 @@
|
||||
C69EFA0E209A0F660027712B /* JMCallKitListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = C69EFA0B209A0F660027712B /* JMCallKitListener.swift */; };
|
||||
C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3425E204EF76800E062DD /* DragGestureController.swift */; };
|
||||
C6CC49AF207412CF000DFA42 /* PiPViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6CC49AE207412CF000DFA42 /* PiPViewCoordinator.swift */; };
|
||||
DE438CDA2350934700DD541D /* JavaScriptSandbox.m in Sources */ = {isa = PBXBuildFile; fileRef = DE438CD82350934700DD541D /* JavaScriptSandbox.m */; };
|
||||
DE65AACA2317FFCD00290BEC /* LogUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AAC92317FFCD00290BEC /* LogUtils.h */; };
|
||||
DE65AACC2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */; };
|
||||
DE762DB422AFDE76000DEBD6 /* JitsiMeetUserInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DE762DB322AFDE76000DEBD6 /* JitsiMeetUserInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -105,6 +105,7 @@
|
||||
C6A3425E204EF76800E062DD /* DragGestureController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DragGestureController.swift; sourceTree = "<group>"; };
|
||||
C6CC49AE207412CF000DFA42 /* PiPViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PiPViewCoordinator.swift; sourceTree = "<group>"; };
|
||||
C6F99C13204DB63D0001F710 /* JitsiMeetView+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetView+Private.h"; sourceTree = "<group>"; };
|
||||
DE438CD82350934700DD541D /* JavaScriptSandbox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JavaScriptSandbox.m; sourceTree = "<group>"; };
|
||||
DE65AAC92317FFCD00290BEC /* LogUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LogUtils.h; sourceTree = "<group>"; };
|
||||
DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetBaseLogHandler+Private.h"; sourceTree = "<group>"; };
|
||||
DE762DB322AFDE76000DEBD6 /* JitsiMeetUserInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeetUserInfo.h; sourceTree = "<group>"; };
|
||||
@@ -191,6 +192,7 @@
|
||||
A4A934E7212F3AB8001E9388 /* dropbox */,
|
||||
0BA13D301EE83FF8007BEF7F /* ExternalAPI.m */,
|
||||
0BD906E91EC0C00300C8C18E /* Info.plist */,
|
||||
DE438CD82350934700DD541D /* JavaScriptSandbox.m */,
|
||||
0BD906E81EC0C00300C8C18E /* JitsiMeet.h */,
|
||||
DEFE535821FB311F00011A3A /* JitsiMeet+Private.h */,
|
||||
DEFE535321FB1BF800011A3A /* JitsiMeet.m */,
|
||||
@@ -319,7 +321,6 @@
|
||||
0BD906E31EC0C00300C8C18E /* Resources */,
|
||||
0BCA49651EC4B77500B793EE /* Package React bundle */,
|
||||
C7BC10B338C94EEB98048E64 /* [CP] Copy Pods Resources */,
|
||||
0B64F7BE2175DFEA005009CD /* Remove unneeded fonts */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -376,7 +377,6 @@
|
||||
6C31EDCA20C06D530089C899 /* recordingOff.mp3 in Resources */,
|
||||
A4414AE020B37F1A003546E6 /* rejected.wav in Resources */,
|
||||
0B49424620AD8DBD00BD2DE0 /* outgoingRinging.wav in Resources */,
|
||||
0BCA496C1EC4BBF900B793EE /* jitsi.ttf in Resources */,
|
||||
C6245F5D2053091D0040BE68 /* image-resize@2x.png in Resources */,
|
||||
6C31EDC820C06D490089C899 /* recordingOn.mp3 in Resources */,
|
||||
0BC4B8691F8C03A700CE8B21 /* CallKitIcon.png in Resources */,
|
||||
@@ -389,24 +389,6 @@
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
0B64F7BE2175DFEA005009CD /* Remove unneeded fonts */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Remove unneeded fonts";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# We need to manually do this because react-native-vecotr-icons lists fonts as resources in the Pod spec file\n# so they are automatically added.\n\nshopt -s extglob\n\nrm -f ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/!(jitsi).ttf\n";
|
||||
};
|
||||
0BCA49651EC4B77500B793EE /* Package React bundle */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -451,21 +433,6 @@
|
||||
"${PODS_ROOT}/Amplitude-iOS/Amplitude/ComodoRsaCA.der",
|
||||
"${PODS_ROOT}/Amplitude-iOS/Amplitude/ComodoRsaDomainValidationCA.der",
|
||||
"${PODS_ROOT}/GoogleSignIn/Resources/GoogleSignIn.bundle",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Feather.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Regular.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Foundation.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Octicons.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf",
|
||||
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Zocial.ttf",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
@@ -474,21 +441,6 @@
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ComodoRsaCA.der",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ComodoRsaDomainValidationCA.der",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleSignIn.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AntDesign.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Entypo.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EvilIcons.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Feather.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Brands.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Regular.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Solid.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Foundation.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Ionicons.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialCommunityIcons.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialIcons.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Octicons.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SimpleLineIcons.ttf",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Zocial.ttf",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
@@ -544,6 +496,7 @@
|
||||
C69EFA0E209A0F660027712B /* JMCallKitListener.swift in Sources */,
|
||||
0B412F191EDEC65D00B1A0A6 /* JitsiMeetView.m in Sources */,
|
||||
DEFE535421FB1BF800011A3A /* JitsiMeet.m in Sources */,
|
||||
DE438CDA2350934700DD541D /* JavaScriptSandbox.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -674,6 +627,7 @@
|
||||
baseConfigurationReference = 98E09B5C73D9036B4ED252FC /* Pods-JitsiMeet.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = NO;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
|
||||
@@ -685,15 +639,18 @@
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = src/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.JitsiMeetSDK.ios;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -702,6 +659,7 @@
|
||||
baseConfigurationReference = 9C77CA3CC919B081F1A52982 /* Pods-JitsiMeet.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
|
||||
@@ -713,14 +671,17 @@
|
||||
ENABLE_BITCODE = YES;
|
||||
INFOPLIST_FILE = src/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.JitsiMeetSDK.ios;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
||||
@@ -29,8 +29,6 @@
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
@@ -51,8 +49,6 @@
|
||||
ReferencedContainer = "container:sdk.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
@@ -81,7 +77,7 @@
|
||||
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
|
||||
<ActionContent
|
||||
title = "Run Script"
|
||||
scriptText = "exec > /tmp/${PROJECT_NAME}_archive.log 2>&1 UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal if [ "true" == ${ALREADYINVOKED:-false} ] then echo "RECURSION: Detected, stopping" else export ALREADYINVOKED="true" # make sure the output directory exists mkdir -p "${UNIVERSAL_OUTPUTFOLDER}" echo "Building for iPhoneSimulator" xcodebuild -workspace "${WORKSPACE_PATH}" -scheme "${TARGET_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6' ONLY_ACTIVE_ARCH=NO ARCHS='i386 x86_64' BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode" BITCODE_GENERATION_MODE=bitcode clean build # Step 1. Copy the framework structure (from iphoneos build) to the universal folder echo "Copying to output folder" cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${FULL_PRODUCT_NAME}" "${UNIVERSAL_OUTPUTFOLDER}/" # Step 2. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory SIMULATOR_SWIFT_MODULES_DIR="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/Modules/${TARGET_NAME}.swiftmodule/." if [ -d "${SIMULATOR_SWIFT_MODULES_DIR}" ]; then cp -R "${SIMULATOR_SWIFT_MODULES_DIR}" "${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Modules/${TARGET_NAME}.swiftmodule" fi # Step 3. Create universal binary file using lipo and place the combined executable in the copied framework directory echo "Combining executables" lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${EXECUTABLE_PATH}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${EXECUTABLE_PATH}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${EXECUTABLE_PATH}" # Step 4. Create universal binaries for embedded frameworks #for SUB_FRAMEWORK in $( ls "${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Frameworks" ); do #BINARY_NAME="${SUB_FRAMEWORK%.*}" #lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${SUB_FRAMEWORK}/${BINARY_NAME}" "${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/${TARGET_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}" #done # Step 5. Convenience step to copy the framework to the project's directory echo "Copying to project dir" yes | cp -Rf "${UNIVERSAL_OUTPUTFOLDER}/${FULL_PRODUCT_NAME}" "${PROJECT_DIR}" fi">
|
||||
scriptText = "exec > /tmp/${PROJECT_NAME}_archive.log 2>&1 UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal if [ "true" == ${ALREADYINVOKED:-false} ] then echo "RECURSION: Detected, stopping" else export ALREADYINVOKED="true" # make sure the output directory exists mkdir -p "${UNIVERSAL_OUTPUTFOLDER}" echo "Building for iPhoneSimulator" xcodebuild -workspace "${WORKSPACE_PATH}" -scheme "${TARGET_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 8' ONLY_ACTIVE_ARCH=NO ARCHS='i386 x86_64' BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode" BITCODE_GENERATION_MODE=bitcode build # Step 1. Copy the framework structure (from iphoneos build) to the universal folder echo "Copying to output folder" cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${FULL_PRODUCT_NAME}" "${UNIVERSAL_OUTPUTFOLDER}/" # Step 2. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory SIMULATOR_SWIFT_MODULES_DIR="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/Modules/${TARGET_NAME}.swiftmodule/." if [ -d "${SIMULATOR_SWIFT_MODULES_DIR}" ]; then cp -R "${SIMULATOR_SWIFT_MODULES_DIR}" "${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Modules/${TARGET_NAME}.swiftmodule" fi # Step 3. Create universal binary file using lipo and place the combined executable in the copied framework directory echo "Combining executables" lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${EXECUTABLE_PATH}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${EXECUTABLE_PATH}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${EXECUTABLE_PATH}" # Step 4. Create universal binaries for embedded frameworks #for SUB_FRAMEWORK in $( ls "${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Frameworks" ); do #BINARY_NAME="${SUB_FRAMEWORK%.*}" #lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${SUB_FRAMEWORK}/${BINARY_NAME}" "${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/${TARGET_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}" #done # Step 5. Convenience step to copy the framework to the project's directory echo "Copying to project dir" yes | cp -Rf "${UNIVERSAL_OUTPUTFOLDER}/${FULL_PRODUCT_NAME}" "${PROJECT_DIR}" fi ">
|
||||
<EnvironmentBuildable>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.2.0</string>
|
||||
<string>2.4.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
55
ios/sdk/src/JavaScriptSandbox.m
Normal file
55
ios/sdk/src/JavaScriptSandbox.m
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright @ 2019-present 8x8, Inc.
|
||||
*
|
||||
* 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 JavaScriptCore;
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
|
||||
@interface JavaScriptSandbox : NSObject<RCTBridgeModule>
|
||||
@end
|
||||
|
||||
@implementation JavaScriptSandbox
|
||||
|
||||
RCT_EXPORT_MODULE();
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup {
|
||||
return NO;
|
||||
}
|
||||
|
||||
#pragma mark - Exported methods
|
||||
|
||||
RCT_EXPORT_METHOD(evaluate:(NSString *)code
|
||||
resolve:(RCTPromiseResolveBlock)resolve
|
||||
reject:(RCTPromiseRejectBlock)reject) {
|
||||
__block BOOL hasError = NO;
|
||||
JSContext *ctx = [[JSContext alloc] init];
|
||||
ctx.exceptionHandler = ^(JSContext *context, JSValue *exception) {
|
||||
hasError = YES;
|
||||
reject(@"evaluate", [exception toString], nil);
|
||||
};
|
||||
JSValue *ret = [ctx evaluateScript:code];
|
||||
if (!hasError) {
|
||||
NSString *result = [ret toString];
|
||||
if (result == nil) {
|
||||
reject(@"evaluate", @"Error in string coercion", nil);
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -37,7 +37,6 @@
|
||||
* List of domains used for universal linking.
|
||||
*/
|
||||
@property (copy, nonatomic, nullable) NSArray<NSString *> *universalLinkDomains;
|
||||
|
||||
/**
|
||||
* Default conference options used for all conferences. These options will be merged
|
||||
* with those passed to JitsiMeetView.join when joining a conference.
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#import "ReactUtils.h"
|
||||
|
||||
#import <RNGoogleSignin/RNGoogleSignin.h>
|
||||
#import <WebRTC/RTCLogging.h>
|
||||
|
||||
|
||||
@implementation JitsiMeet {
|
||||
@@ -54,6 +55,11 @@
|
||||
|
||||
// Register a log handler for React.
|
||||
registerReactLogHandler();
|
||||
|
||||
#if 0
|
||||
// Enable WebRTC logs
|
||||
RTCSetMinDebugLogLevel(RTCLoggingSeverityInfo);
|
||||
#endif
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -90,8 +96,7 @@
|
||||
|
||||
if ([RNGoogleSignin application:app
|
||||
openURL:url
|
||||
sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]
|
||||
annotation:options[UIApplicationOpenURLOptionsAnnotationKey]]) {
|
||||
options:options]) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -179,6 +184,15 @@
|
||||
return _universalLinkDomains ? _universalLinkDomains : @[];
|
||||
}
|
||||
|
||||
- (void)setDefaultConferenceOptions:(JitsiMeetConferenceOptions *)defaultConferenceOptions {
|
||||
if (defaultConferenceOptions != nil && _defaultConferenceOptions.room != nil) {
|
||||
@throw [NSException exceptionWithName:@"RuntimeError"
|
||||
reason:@"'room' must be null in the default conference options"
|
||||
userInfo:nil];
|
||||
}
|
||||
_defaultConferenceOptions = defaultConferenceOptions;
|
||||
}
|
||||
|
||||
#pragma mark - Private API methods
|
||||
|
||||
- (NSDictionary *)getDefaultProps {
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
*/
|
||||
__attribute__((constructor))
|
||||
static void initializeLogger() {
|
||||
[DDLog addLogger:[DDOSLogger sharedInstance]];
|
||||
NSString *mainBundleId = [NSBundle mainBundle].bundleIdentifier;
|
||||
DDOSLogger *osLogger = [[DDOSLogger alloc] initWithSubsystem:mainBundleId category:@"JitsiMeetSDK"];
|
||||
[DDLog addLogger:osLogger];
|
||||
}
|
||||
|
||||
+ (void)addHandler:(JitsiMeetBaseLogHandler *)handler {
|
||||
|
||||
@@ -37,6 +37,7 @@ set -e
|
||||
# IOS_TEAM_ID - the team ID inserted into build-ipa-.plist.template file in
|
||||
# place of "YOUR_TEAM_ID".
|
||||
|
||||
|
||||
# Travis will not print the last echo if there's no sleep 1
|
||||
function echoSleepAndExit1() {
|
||||
echo $1
|
||||
@@ -57,10 +58,6 @@ if [ -z $IPA_DEPLOY_LOCATION ]; then
|
||||
echoSleepAndExit1 "No IPA_DEPLOY_LOCATION defined"
|
||||
fi
|
||||
|
||||
if [ -z $APPLE_CERT_URL ]; then
|
||||
APPLE_CERT_URL="http://developer.apple.com/certificationauthority/AppleWWDRCA.cer"
|
||||
fi
|
||||
|
||||
echo "PR_REPO_SLUG=${PR_REPO_SLUG} PR_BRANCH=${PR_BRANCH}"
|
||||
|
||||
# do the marge and git log
|
||||
@@ -88,47 +85,17 @@ fi
|
||||
|
||||
git log -20 --graph --pretty=format':%C(yellow)%h%Cblue%d%Creset %s %C(white) %an, %ar%Creset'
|
||||
|
||||
# certificates
|
||||
|
||||
#certificates
|
||||
CERT_DIR="ios/travis-ci/certs"
|
||||
|
||||
mkdir $CERT_DIR
|
||||
mkdir -p $CERT_DIR
|
||||
|
||||
./ios/ci/setup-certificates.sh $CERT_DIR
|
||||
|
||||
curl -L -o ${CERT_DIR}/AppleWWDRCA.cer 'http://developer.apple.com/certificationauthority/AppleWWDRCA.cer'
|
||||
curl -L -o ${CERT_DIR}/dev-cert.cer.enc ${IOS_DEV_CERT_URL}
|
||||
curl -L -o ${CERT_DIR}/dev-key.p12.enc ${IOS_DEV_CERT_KEY_URL}
|
||||
curl -L -o ${CERT_DIR}/dev-profile.mobileprovision.enc ${IOS_DEV_PROV_PROFILE_URL}
|
||||
curl -L -o ${CERT_DIR}/dev-watch-profile.mobileprovision.enc ${IOS_DEV_WATCH_PROV_PROFILE_URL}
|
||||
curl -L -o ${CERT_DIR}/id_rsa.enc ${DEPLOY_SSH_CERT_URL}
|
||||
|
||||
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/dev-cert.cer.enc -d -a -out ${CERT_DIR}/dev-cert.cer
|
||||
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/dev-key.p12.enc -d -a -out ${CERT_DIR}/dev-key.p12
|
||||
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/dev-profile.mobileprovision.enc -d -a -out ${CERT_DIR}/dev-profile.mobileprovision
|
||||
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/dev-watch-profile.mobileprovision.enc -d -a -out ${CERT_DIR}/dev-watch-profile.mobileprovision
|
||||
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/id_rsa.enc -d -a -out ${CERT_DIR}/id_rsa
|
||||
chmod 0600 ${CERT_DIR}/id_rsa
|
||||
|
||||
security create-keychain -p $ENCRYPTION_PASSWORD ios-build.keychain
|
||||
security default-keychain -s ios-build.keychain
|
||||
security unlock-keychain -p $ENCRYPTION_PASSWORD ios-build.keychain
|
||||
security set-keychain-settings -t 3600 -l ~/Library/Keychains/ios-build.keychain
|
||||
|
||||
echo "importing Apple cert"
|
||||
security import ${CERT_DIR}/AppleWWDRCA.cer -k ios-build.keychain -A
|
||||
echo "importing dev-cert.cer"
|
||||
security import ${CERT_DIR}/dev-cert.cer -k ios-build.keychain -A
|
||||
echo "importing dev-key.p12"
|
||||
security import ${CERT_DIR}/dev-key.p12 -k ios-build.keychain -P $IOS_SIGNING_CERT_PASSWORD -A
|
||||
|
||||
echo "will set-key-partition-list"
|
||||
# Fix for OS X Sierra that hungs in the codesign step
|
||||
security set-key-partition-list -S apple-tool:,apple: -s -k $ENCRYPTION_PASSWORD ios-build.keychain > /dev/null
|
||||
echo "done set-key-partition-list"
|
||||
|
||||
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
|
||||
|
||||
cp "${CERT_DIR}/dev-profile.mobileprovision" ~/Library/MobileDevice/Provisioning\ Profiles/
|
||||
cp "${CERT_DIR}/dev-watch-profile.mobileprovision" ~/Library/MobileDevice/Provisioning\ Profiles/
|
||||
ssh-add ${CERT_DIR}/id_rsa
|
||||
|
||||
npm install
|
||||
|
||||
@@ -136,24 +103,21 @@ npm install
|
||||
./node_modules/react-native-webrtc/tools/downloadBitcode.sh
|
||||
|
||||
cd ios
|
||||
pod update
|
||||
pod install
|
||||
pod install --repo-update --no-ansi
|
||||
cd ..
|
||||
|
||||
mkdir -p /tmp/jitsi-meet/
|
||||
|
||||
xcodebuild archive -quiet -workspace ios/jitsi-meet.xcworkspace -scheme jitsi-meet -configuration Release -archivePath /tmp/jitsi-meet/jitsi-meet.xcarchive
|
||||
|
||||
sed -e "s/YOUR_TEAM_ID/${IOS_TEAM_ID}/g" ios/travis-ci/build-ipa.plist.template > ios/travis-ci/build-ipa.plist
|
||||
sed -e "s/YOUR_TEAM_ID/${IOS_TEAM_ID}/g" ios/ci/build-ipa.plist.template > ios/ci/build-ipa.plist
|
||||
|
||||
IPA_EXPORT_DIR=/tmp/jitsi-meet/jitsi-meet-ipa
|
||||
|
||||
xcodebuild -quiet -exportArchive -archivePath /tmp/jitsi-meet/jitsi-meet.xcarchive -exportPath $IPA_EXPORT_DIR -exportOptionsPlist ios/travis-ci/build-ipa.plist
|
||||
xcodebuild -quiet -exportArchive -archivePath /tmp/jitsi-meet/jitsi-meet.xcarchive -exportPath $IPA_EXPORT_DIR -exportOptionsPlist ios/ci/build-ipa.plist
|
||||
|
||||
echo "Will try deploy the .ipa to: ${IPA_DEPLOY_LOCATION}"
|
||||
|
||||
ssh-add ${CERT_DIR}/id_rsa
|
||||
|
||||
if [ ! -z ${SCP_PROXY_HOST} ];
|
||||
then
|
||||
scp -o ProxyCommand="ssh -t -A -l %r ${SCP_PROXY_HOST} -o \"StrictHostKeyChecking no\" -o \"BatchMode yes\" -W %h:%p" -o StrictHostKeyChecking=no -o LogLevel=DEBUG "${IPA_EXPORT_DIR}/jitsi-meet.ipa" "${IPA_DEPLOY_LOCATION}"
|
||||
|
||||
@@ -1,27 +1,31 @@
|
||||
{
|
||||
"en": "Английски",
|
||||
"af": "Африканс",
|
||||
"az": "Азербайджански",
|
||||
"bg": "Български",
|
||||
"ca": "Каталонски",
|
||||
"cs": "Чешки",
|
||||
"de": "Немски",
|
||||
"el": "Гръцки",
|
||||
"enGB": "Английски (Великобритания)",
|
||||
"eo": "Есперанто",
|
||||
"es": "Испански",
|
||||
"esUS": "Испански (Латинска Америка)",
|
||||
"fi": "Фински",
|
||||
"fr": "Френски",
|
||||
"frCA": "Френски (Канада)",
|
||||
"hr": "Хърватски",
|
||||
"hy": "Арменски",
|
||||
"it": "Италиански",
|
||||
"ja": "Японски",
|
||||
"ko": "Корейски",
|
||||
"nb": "Норвежки букмол",
|
||||
"nl": "Нидерландски",
|
||||
"oc": "Окситански",
|
||||
"pl": "Полски",
|
||||
"ptBR": "Португалски (Бразилия)",
|
||||
"ru": "Руски",
|
||||
"sk": "Словашки",
|
||||
"sl": "Словенски",
|
||||
"sv": "Шведски",
|
||||
"tr": "Турски",
|
||||
"vi": "Виетнамски",
|
||||
"zhCN": "Китайски (Китай)"
|
||||
"zhCN": "Китайски (Китай)",
|
||||
"zhTW": "Тайвански"
|
||||
}
|
||||
@@ -1,27 +1,31 @@
|
||||
{
|
||||
"en": "Angol",
|
||||
"af": "",
|
||||
"az": "",
|
||||
"bg": "Bolgár",
|
||||
"cs": "",
|
||||
"de": "Német",
|
||||
"el": "",
|
||||
"eo": "Eszperantó",
|
||||
"es": "Spanyol",
|
||||
"fr": "Francia",
|
||||
"hy": "Örmény",
|
||||
"it": "Olasz",
|
||||
"ja": "",
|
||||
"ko": "",
|
||||
"nb": "Norvég bokmal",
|
||||
"oc": "Okszitán",
|
||||
"pl": "Lengyel",
|
||||
"ptBR": "Portugál (Brazil)",
|
||||
"ru": "Orosz",
|
||||
"sk": "Szlovák",
|
||||
"sl": "Szlovén",
|
||||
"sv": "Svéd",
|
||||
"tr": "Török",
|
||||
"vi": "",
|
||||
"zhCN": "Kínai (Kína)"
|
||||
"en": "angol",
|
||||
"af": "afrikaans",
|
||||
"bg": "bolgár",
|
||||
"ca": "katalán",
|
||||
"cs": "cseh",
|
||||
"de": "német",
|
||||
"el": "görög",
|
||||
"enGB": "angol (Egyesült Királyság)",
|
||||
"eo": "eszperantó",
|
||||
"es": "spanyol",
|
||||
"esUS": "spanyol (Latin-Amerika)",
|
||||
"fi": "finn",
|
||||
"fr": "francia",
|
||||
"frCA": "francia (kanadai)",
|
||||
"hr": "horvát",
|
||||
"hy": "örmény",
|
||||
"it": "olasz",
|
||||
"ja": "japán",
|
||||
"ko": "koreai",
|
||||
"nl": "holland",
|
||||
"oc": "okszitán",
|
||||
"pl": "lengyel",
|
||||
"ptBR": "portugál (Brazil)",
|
||||
"ru": "orosz",
|
||||
"sv": "svéd",
|
||||
"tr": "török",
|
||||
"vi": "vietnámi",
|
||||
"zhCN": "kínai (Kína)",
|
||||
"zhTW": "kínai (Tajvan)"
|
||||
}
|
||||
@@ -2,23 +2,23 @@
|
||||
"en": "Anglés",
|
||||
"af": "Afrikaans",
|
||||
"bg": "Bulgar",
|
||||
"ca": "",
|
||||
"ca": "Catalan",
|
||||
"cs": "Chèc",
|
||||
"de": "Aleman",
|
||||
"el": "Grèc",
|
||||
"enGB": "",
|
||||
"enGB": "Anglés (Reialme Unit)",
|
||||
"eo": "Esperanto",
|
||||
"es": "Castelhan",
|
||||
"esUS": "",
|
||||
"fi": "",
|
||||
"esUS": "Espanhòl (America latina)",
|
||||
"fi": "Finés",
|
||||
"fr": "Francés",
|
||||
"frCA": "",
|
||||
"hr": "",
|
||||
"frCA": "Francés (Canadian)",
|
||||
"hr": "Croat",
|
||||
"hy": "Armenian",
|
||||
"it": "Italian",
|
||||
"ja": "Japonés",
|
||||
"ko": "Corean",
|
||||
"nl": "",
|
||||
"nl": "Neerlandés",
|
||||
"oc": "Occitan",
|
||||
"pl": "Polonés",
|
||||
"ptBR": "Portugués (Brasil)",
|
||||
@@ -27,5 +27,5 @@
|
||||
"tr": "Turc",
|
||||
"vi": "Vietnamian",
|
||||
"zhCN": "Chinés (China)",
|
||||
"zhTW": ""
|
||||
"zhTW": "Chinés (Taiwan)"
|
||||
}
|
||||
@@ -1,27 +1,31 @@
|
||||
{
|
||||
"en": "Anglik",
|
||||
"af": "",
|
||||
"az": "Azerski",
|
||||
"en": "Angielski",
|
||||
"af": "Afrykanerski",
|
||||
"bg": "Bułgarski",
|
||||
"ca": "",
|
||||
"cs": "Czeski",
|
||||
"de": "Niemiecki",
|
||||
"el": "Grecki",
|
||||
"enGB": "",
|
||||
"eo": "Esperanto",
|
||||
"es": "Hiszpański",
|
||||
"esUS": "",
|
||||
"fi": "",
|
||||
"fr": "Francuski",
|
||||
"frCA": "",
|
||||
"hr": "",
|
||||
"hy": "Ormiański",
|
||||
"it": "Włoski",
|
||||
"ja": "Japoński",
|
||||
"ko": "Koreański",
|
||||
"nb": "Norweski Bokmal",
|
||||
"nl": "",
|
||||
"oc": "Oksytański",
|
||||
"pl": "Polski",
|
||||
"ptBR": "portugalski (brazylijski)",
|
||||
"ptBR": "Portugalski (brazylijski)",
|
||||
"ru": "Rosyjski",
|
||||
"sk": "Słowacki",
|
||||
"sl": "Słoweński",
|
||||
"sv": "Szwedzki",
|
||||
"tr": "Turecki",
|
||||
"vi": "Wietnamski",
|
||||
"zhCN": "Chiński (Chiny)"
|
||||
"zhCN": "Chiński (Chiny)",
|
||||
"zhTW": ""
|
||||
}
|
||||
@@ -1,27 +1,31 @@
|
||||
{
|
||||
"en": "Inglês",
|
||||
"af": "Africâner",
|
||||
"az": "Azerbaijanês",
|
||||
"bg": "Búlgaro",
|
||||
"ca": "",
|
||||
"cs": "Checo",
|
||||
"de": "Alemão",
|
||||
"el": "Grego",
|
||||
"enGB": "",
|
||||
"eo": "Esperanto",
|
||||
"es": "Espanhol",
|
||||
"esUS": "",
|
||||
"fi": "",
|
||||
"fr": "Francês",
|
||||
"frCA": "",
|
||||
"hr": "",
|
||||
"hy": "Armênio",
|
||||
"it": "Italiano",
|
||||
"ja": "Japonês",
|
||||
"ko": "Coreano",
|
||||
"nb": "Bokmal norueguês",
|
||||
"nl": "",
|
||||
"oc": "Occitano",
|
||||
"pl": "Polonês",
|
||||
"ptBR": "Português (Brasil)",
|
||||
"ru": "Russo",
|
||||
"sk": "Eslovaco",
|
||||
"sl": "Esloveno",
|
||||
"sv": "Sueco",
|
||||
"tr": "Turco",
|
||||
"vi": "Vietnamita",
|
||||
"zhCN": "Chinês (China)"
|
||||
"zhCN": "Chinês (China)",
|
||||
"zhTW": ""
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
"fr": "French",
|
||||
"frCA": "French (Canadian)",
|
||||
"hr": "Croatian",
|
||||
"hu": "Hungarian",
|
||||
"hy": "Armenian",
|
||||
"it": "Italian",
|
||||
"ja": "Japanese",
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
"countryNotSupported": "Желаната дестинация не се поддържа.",
|
||||
"countryReminder": "Международно обаждане? Започнете номера с международният код!",
|
||||
"disabled": "Не можете да каните хора.",
|
||||
"failedToAdd": "",
|
||||
"footerText": "Изходящиите разговори не са разрешени.",
|
||||
"failedToAdd": "Неуспешно добавяне на участници",
|
||||
"footerText": "Изходящите разговори не са разрешени.",
|
||||
"loading": "Търсене на хора и телефонни номера.",
|
||||
"loadingNumber": "Валидиране на номера",
|
||||
"loadingPeople": "Търсене на хора",
|
||||
@@ -13,48 +13,49 @@
|
||||
"noValidNumbers": "Моля въведете телефонен номер",
|
||||
"searchNumbers": "Добавяне на номера",
|
||||
"searchPeople": "Търсене на хора",
|
||||
"searchPeopleAndNumbers": "",
|
||||
"telephone": "",
|
||||
"title": ""
|
||||
"searchPeopleAndNumbers": "Търсене на участници или добавяне с телефони номера",
|
||||
"telephone": "Телефон: {{number}}",
|
||||
"title": "Добавяне на участници в срещата"
|
||||
},
|
||||
"audioDevices": {
|
||||
"bluetooth": "",
|
||||
"bluetooth": "Bluetooth",
|
||||
"headphones": "Слушалки",
|
||||
"phone": "Телефон",
|
||||
"speaker": "Говорещ"
|
||||
"speaker": "Говорещ",
|
||||
"none": "Няма налични устройства за звук"
|
||||
},
|
||||
"audioOnly": {
|
||||
"audioOnly": "Само звук"
|
||||
"audioOnly": "Нисък дебит"
|
||||
},
|
||||
"calendarSync": {
|
||||
"addMeetingURL": "",
|
||||
"confirmAddLink": "",
|
||||
"addMeetingURL": "Добавяне на връзка за среща",
|
||||
"confirmAddLink": "Искате ли да добавите връзка към това събитие?",
|
||||
"error": {
|
||||
"appConfiguration": "",
|
||||
"generic": "",
|
||||
"notSignedIn": ""
|
||||
"appConfiguration": "Интеграцията с календара не е настроена.",
|
||||
"generic": "Грешка, моля проверете настройката за календара или го обновете.",
|
||||
"notSignedIn": "Грешка при идентификация за изтегляне на събития. Моля проверете настройките на календара и опитайте отново."
|
||||
},
|
||||
"join": "",
|
||||
"joinTooltip": "",
|
||||
"nextMeeting": "",
|
||||
"noEvents": "",
|
||||
"ongoingMeeting": "",
|
||||
"permissionButton": "",
|
||||
"permissionMessage": "",
|
||||
"refresh": "",
|
||||
"today": ""
|
||||
"join": "Влизане",
|
||||
"joinTooltip": "Влизане в срещата",
|
||||
"nextMeeting": "следваща среща",
|
||||
"noEvents": "Няма насрочени бъдещи събития.",
|
||||
"ongoingMeeting": "настояща среща",
|
||||
"permissionButton": "Отваряне на настройки",
|
||||
"permissionMessage": "За показване на срещите ви е нужно позволение за ползване на календара.",
|
||||
"refresh": "Обновяване на календара",
|
||||
"today": "Днес"
|
||||
},
|
||||
"chat": {
|
||||
"error": "",
|
||||
"messagebox": "",
|
||||
"error": "Грешка: вашето съобщение \"{{originalText}}\" не е бе изпратено. Поради: {{error}}",
|
||||
"messagebox": "Въведете съобщение",
|
||||
"nickname": {
|
||||
"popover": "Избор на име",
|
||||
"title": ""
|
||||
"title": "Въведете име за да обменяте съобщения"
|
||||
},
|
||||
"title": ""
|
||||
"title": "Текстови съобщения"
|
||||
},
|
||||
"connectingOverlay": {
|
||||
"joiningRoom": ""
|
||||
"joiningRoom": "Свързване с вашата среща..."
|
||||
},
|
||||
"connection": {
|
||||
"ATTACHED": "Прикрепен",
|
||||
@@ -72,8 +73,8 @@
|
||||
"address": "Адрес:",
|
||||
"bandwidth": "Предполагаема скорост:",
|
||||
"bitrate": "Скорост:",
|
||||
"bridgeCount": "",
|
||||
"connectedTo": "",
|
||||
"bridgeCount": "Брой сървъри:",
|
||||
"connectedTo": "Свързан към:",
|
||||
"framerate": "Кадри в секунда:",
|
||||
"less": "Скриване",
|
||||
"localaddress": "Локален адрес:",
|
||||
@@ -96,26 +97,25 @@
|
||||
"resolution": "Резолюция:",
|
||||
"status": "Връзка:",
|
||||
"transport": "Транспорт:",
|
||||
"transport_plural": "Транспорти:",
|
||||
"turn": " (обръщане)"
|
||||
"transport_plural": "Транспорти:"
|
||||
},
|
||||
"dateUtils": {
|
||||
"earlier": "",
|
||||
"today": "",
|
||||
"yesterday": ""
|
||||
"earlier": "По-рано",
|
||||
"today": "Днес",
|
||||
"yesterday": "Вчера"
|
||||
},
|
||||
"deepLinking": {
|
||||
"appNotInstalled": "",
|
||||
"description": "",
|
||||
"descriptionWithoutWeb": "",
|
||||
"downloadApp": "Сваляне не приложението",
|
||||
"launchWebButton": "",
|
||||
"openApp": "",
|
||||
"title": "",
|
||||
"tryAgainButton": ""
|
||||
"appNotInstalled": "Имате нужда от мобилното приложение {{app}} за влизане в тази среща от телефона.",
|
||||
"description": "Нищо не се случва? Опитахме се да заредим срещата в приложението {{app}}. Пробвайте отново или влезте чрез уеб приложението {{app}}.",
|
||||
"descriptionWithoutWeb": "Нищо не се случва? Опитахме се да заредим срещата в приложението {{app}}.",
|
||||
"downloadApp": "Свалете приложението",
|
||||
"launchWebButton": "Заредете уеб страницата",
|
||||
"openApp": "Продължете към приложението",
|
||||
"title": "Зареждане на срещата в {{app}}...",
|
||||
"tryAgainButton": "Пробвайте отново"
|
||||
},
|
||||
"\u0005deepLinking": {},
|
||||
"defaultLink": "напр. {{url}}",
|
||||
"defaultNickname": "напр. Иван Иванов",
|
||||
"deviceError": {
|
||||
"cameraError": "Камерата е недостъпна",
|
||||
"cameraPermission": "Грешка при получаване на разрешение за достъп до камерата",
|
||||
@@ -126,14 +126,14 @@
|
||||
"noPermission": "Не е получено разрешение",
|
||||
"previewUnavailable": "Няма възможност за преглед",
|
||||
"selectADevice": "Изберете устройство",
|
||||
"testAudio": ""
|
||||
"testAudio": "Пусни пробен звук"
|
||||
},
|
||||
"dialog": {
|
||||
"accessibilityLabel": {
|
||||
"liveStreaming": "Излъчване на живо"
|
||||
},
|
||||
"allow": "Разрешаване",
|
||||
"alreadySharedVideoMsg": "",
|
||||
"alreadySharedVideoMsg": "Друг участник вече е споделил видео. Тази среща позволява само едно споделено видео.",
|
||||
"alreadySharedVideoTitle": "Разрешено е споделянето само на едно видео в даден момент",
|
||||
"applicationWindow": "Прозореца на програмата",
|
||||
"Back": "Назад",
|
||||
@@ -150,8 +150,8 @@
|
||||
"conferenceDisconnectTitle": "Връзката се разпадна.",
|
||||
"conferenceReloadMsg": "Опитваме се да оправим нещата. Повторно свързване след {{seconds}} сек…",
|
||||
"conferenceReloadTitle": "За съжаление, нещо се обърка.",
|
||||
"confirm": "",
|
||||
"confirmNo": "",
|
||||
"confirm": "Потвърждение",
|
||||
"confirmNo": "Не",
|
||||
"confirmYes": "Да",
|
||||
"connectError": "Опа! Нещо се обърка и не успяхме да се свържем с конференцията.",
|
||||
"connectErrorWithMsg": "Опа! Нещо се обърка и не успяхме да се свържем с конференцията: {{msg}}",
|
||||
@@ -159,66 +159,66 @@
|
||||
"contactSupport": "Връзка с отдела по поддръжка",
|
||||
"copy": "Копиране",
|
||||
"dismiss": "Отхвърляне",
|
||||
"displayNameRequired": "",
|
||||
"displayNameRequired": "Здравей! Как се казваш?",
|
||||
"done": "Готово",
|
||||
"enterDisplayName": "",
|
||||
"enterDisplayName": "Моля въведете вашето име",
|
||||
"error": "Грешка",
|
||||
"externalInstallationMsg": "Трябва да инсталирате разширението за споделяне на екрана.",
|
||||
"externalInstallationTitle": "Нужно е разширение",
|
||||
"goToStore": "Към магазина в Интернет",
|
||||
"gracefulShutdown": "Услугата временно не е достъпна поради профилактика. Моля опитайте по-късно.",
|
||||
"IamHost": "Аз съм домакина",
|
||||
"incorrectRoomLockPassword": "",
|
||||
"incorrectRoomLockPassword": "Грешна парола",
|
||||
"incorrectPassword": "Неправилно потребителско име или парола",
|
||||
"inlineInstallationMsg": "Трябва да инсталирате разширението за споделяне на екрана.",
|
||||
"inlineInstallExtension": "Инсталиране сега",
|
||||
"internalError": "Опа! Нещо се обърка. Възникна следната грешка: {{error}}",
|
||||
"internalErrorTitle": "Вътрешна грешка",
|
||||
"kickMessage": "",
|
||||
"kickParticipantButton": "",
|
||||
"kickParticipantDialog": "",
|
||||
"kickParticipantTitle": "",
|
||||
"kickTitle": "",
|
||||
"kickMessage": "Може да се свържете с {{participantDisplayName}} за повече подробности.",
|
||||
"kickParticipantButton": "Изгони",
|
||||
"kickParticipantDialog": "Сигурни ли сте че искате да изгоните участника?",
|
||||
"kickParticipantTitle": "Изгонване на този участник?",
|
||||
"kickTitle": "Ауч! {{participantDisplayName}} ви изгони от тази среща",
|
||||
"liveStreaming": "Излъчване на живо",
|
||||
"liveStreamingDisabledForGuestTooltip": "",
|
||||
"liveStreamingDisabledTooltip": "",
|
||||
"liveStreamingDisabledForGuestTooltip": "Гостите не могат да стартират излъчване на живо.",
|
||||
"liveStreamingDisabledTooltip": "Излъчването на живо е деактивирано.",
|
||||
"lockMessage": "Неуспешно заключване на конференцията.",
|
||||
"lockRoom": "",
|
||||
"lockRoom": "Добавяне $t(lockRoomPasswordUppercase) за срещата",
|
||||
"lockTitle": "Неуспешно заключване",
|
||||
"logoutQuestion": "Сигурни ли сте, че искате да излезете и да прекъснете конференцията?",
|
||||
"logoutTitle": "Изход",
|
||||
"maxUsersLimitReached": "",
|
||||
"maxUsersLimitReachedTitle": "",
|
||||
"maxUsersLimitReached": "Лимитът за максимален брой участници бе достигнат. Капацитета на срещата е запълнен. Моля свържете се с организатора или опитайте по-късно!",
|
||||
"maxUsersLimitReachedTitle": "Достигнат е лимита за максимален брой участници",
|
||||
"micConstraintFailedError": "Микрофонът Ви не покрива някои от изискванията.",
|
||||
"micNotFoundError": "Не е открит микрофон.",
|
||||
"micNotSendingData": "",
|
||||
"micNotSendingDataTitle": "",
|
||||
"micNotSendingData": "Пуснете микрофона си от системните настройки на компютъра ви.",
|
||||
"micNotSendingDataTitle": "Микрофона ви е спрян от системните настройки",
|
||||
"micPermissionDeniedError": "Не сте дали разрешение за използване на микрофона. Ще можете да се присъедините в беседата, но другите няма да Ви чуват. Използвайте бутона с камерата в адресната лента, за да оправите това.",
|
||||
"micUnknownError": "Не възможен достъп до микрофона по неясна причина.",
|
||||
"micUnknownError": "Невъзможен достъп до микрофона по неясна причина.",
|
||||
"muteParticipantBody": "Вие няма да можете да спрете заглушаването на участника, но той ще може да го направи по всяко време.",
|
||||
"muteParticipantButton": "Изключи микрофона",
|
||||
"muteParticipantDialog": "",
|
||||
"muteParticipantTitle": "",
|
||||
"muteParticipantDialog": "Сигурни ли сте че искате да заглушите този участник? Няма да можете да пуснете обратно звука му, но участника ще може да направи това сам.",
|
||||
"muteParticipantTitle": "Спиране звука на участник?",
|
||||
"Ok": "Готово",
|
||||
"passwordLabel": "",
|
||||
"passwordNotSupported": "Задаването на парола за срещата не се поддържа.",
|
||||
"passwordNotSupportedTitle": "",
|
||||
"passwordRequired": "",
|
||||
"passwordLabel": "Парола",
|
||||
"passwordNotSupported": "Задаването на $t(lockRoomPassword) за срещата не се поддържа.",
|
||||
"passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) не се поддържа",
|
||||
"passwordRequired": "Изисква се $t(lockRoomPassword) ",
|
||||
"popupError": "Браузърът Ви блокира изскачащите прозорци от този уеб сайт. Моля, разрешете изскачащите прозорци от настройките за сигурност на браузъра си и след това опитайте отново.",
|
||||
"popupErrorTitle": "Блокиран изскачащ прозорец",
|
||||
"recording": "Запис",
|
||||
"recordingDisabledForGuestTooltip": "",
|
||||
"recordingDisabledTooltip": "",
|
||||
"recordingDisabledForGuestTooltip": "Гостите не могат да стартират запис",
|
||||
"recordingDisabledTooltip": "Стартирането на запис е спряно",
|
||||
"rejoinNow": "Повторно присъединяване сега",
|
||||
"remoteControlAllowedMessage": "{{user}} прие заявката Ви за отдалечено управление!",
|
||||
"remoteControlDeniedMessage": "{{user}} отказа заявката Ви за отдалечено управление!",
|
||||
"remoteControlErrorMessage": "Възникна грешка при опита за искана на разрешение за отдалечено управление от {{user}}!",
|
||||
"remoteControlErrorMessage": "Възникна грешка при опита за искане на разрешение за отдалечено управление от {{user}}!",
|
||||
"remoteControlRequestMessage": "Ще позволите ли на {{user}} да управлява отдалечено компютъра Ви?",
|
||||
"remoteControlShareScreenWarning": "Ако натиснете „Разрешаване“, ще споделите екрана си!",
|
||||
"remoteControlStopMessage": "Сесията за отдалечено управление приключи!",
|
||||
"remoteControlTitle": "Отдалечено управление на компютъра",
|
||||
"Remove": "Премахване",
|
||||
"removePassword": "",
|
||||
"removePassword": "Премахване на $t(lockRoomPassword)",
|
||||
"removeSharedVideoMsg": "Наистина ли искате да премахнете споделеното си видео?",
|
||||
"removeSharedVideoTitle": "Край на споделянето на видео",
|
||||
"reservationError": "Грешка в системата за резервации",
|
||||
@@ -226,8 +226,8 @@
|
||||
"retry": "Повторен опит",
|
||||
"screenSharingFailedToInstall": "Опа! Разширението за споделяне на екрана не успя да се инсталира.",
|
||||
"screenSharingFailedToInstallTitle": "Разширението за споделяне на екрана не успя да се инсталира",
|
||||
"screenSharingFirefoxPermissionDeniedError": "",
|
||||
"screenSharingFirefoxPermissionDeniedTitle": "",
|
||||
"screenSharingFirefoxPermissionDeniedError": "Нещо се обърка докато се опитвахме да споделим екрана. Моля уверете се че сте дали права за това.",
|
||||
"screenSharingFirefoxPermissionDeniedTitle": "Упс! Не успяхме да стартираме споделянето на екрана!",
|
||||
"screenSharingPermissionDeniedError": "Опа! Нещо се обърка с разрешенията на разширението за споделяне на екрана. Моля, презаредете и опитайте отново.",
|
||||
"serviceUnavailable": "Услугата не е налична",
|
||||
"sessTerminated": "Разговорът приключи",
|
||||
@@ -235,91 +235,86 @@
|
||||
"shareVideoLinkError": "Моля въведете правилна връзка към YouTube.",
|
||||
"shareVideoTitle": "Сподели видео",
|
||||
"shareYourScreen": "Споделяне на екрана",
|
||||
"shareYourScreenDisabled": "",
|
||||
"shareYourScreenDisabledForGuest": "",
|
||||
"shareYourScreenDisabled": "Споделянето на екрана не се поддържа.",
|
||||
"shareYourScreenDisabledForGuest": "Гостите не могат да споделят екрана.",
|
||||
"startLiveStreaming": "Започване на излъчване на живо",
|
||||
"startRecording": "Край на записа",
|
||||
"startRecording": "Стартиране на запис",
|
||||
"startRemoteControlErrorMessage": "Възникна грешка при опита за започване на сесията за отдалечено управление!",
|
||||
"stopLiveStreaming": "Спиране на излъчването на живо",
|
||||
"stopRecording": "Край на записа",
|
||||
"stopRecordingWarning": "Наистина ли искате да спрем записа?",
|
||||
"stopStreamingWarning": "Наистина ли искате да спрете излъчването на живо?",
|
||||
"streamKey": "",
|
||||
"streamKey": "Ключ за излъчване на живо",
|
||||
"Submit": "Изпращане",
|
||||
"thankYou": "Благодарим, че използвахте {{appName}}!",
|
||||
"token": "код за достъп",
|
||||
"tokenAuthFailed": "Съжаляваме, но не можете да се присъедините към този разговор.",
|
||||
"tokenAuthFailedTitle": "Неуспешна идентификация",
|
||||
"transcribing": "",
|
||||
"unlockRoom": "",
|
||||
"transcribing": "Транскрипция",
|
||||
"unlockRoom": "Премахване $t(lockRoomPassword) от срещата",
|
||||
"userPassword": "потребителска парола",
|
||||
"WaitForHostMsg": "",
|
||||
"WaitForHostMsgWOk": "",
|
||||
"WaitForHostMsg": "Конференцията <b>{{room}}</b> все още не е започнала. Ако сте домакинът тогава се идентифицирайте. В противен случай изчакайте докато домакинът пристигне.",
|
||||
"WaitForHostMsgWOk": "Конференцията <b>{{room}}</b> все още не е започнала. Ако сте домакинът тогава натиснете бутона за да се идентифицирате. В противен случай изчакайте докато домакинът пристигне.",
|
||||
"WaitingForHost": "Чакаме домакина ...",
|
||||
"Yes": "Да",
|
||||
"yourEntireScreen": "Целия екран"
|
||||
},
|
||||
"\u0005dialog": {
|
||||
"accessibilityLabel": {}
|
||||
},
|
||||
"dialOut": {
|
||||
"statusMessage": "в момента е {{status}}"
|
||||
},
|
||||
"feedback": {
|
||||
"average": "Средно",
|
||||
"bad": "Лошо",
|
||||
"detailsLabel": "",
|
||||
"detailsLabel": "Разкажете ни повече.",
|
||||
"good": "Добра",
|
||||
"rateExperience": "Моля, оценете качеството на срещата.",
|
||||
"veryBad": "Много лошо",
|
||||
"veryGood": "Много добра"
|
||||
},
|
||||
"\u0005feedback": {},
|
||||
"incomingCall": {
|
||||
"answer": "",
|
||||
"audioCallTitle": "",
|
||||
"answer": "Вдигни",
|
||||
"audioCallTitle": "Входящ разговор",
|
||||
"decline": "Отхвърляне",
|
||||
"productLabel": "",
|
||||
"videoCallTitle": ""
|
||||
"productLabel": "от Jitsi Meet",
|
||||
"videoCallTitle": "Входящ видео разговор"
|
||||
},
|
||||
"info": {
|
||||
"accessibilityLabel": "",
|
||||
"addPassword": "",
|
||||
"cancelPassword": "",
|
||||
"conferenceURL": "",
|
||||
"country": "",
|
||||
"dialANumber": "",
|
||||
"dialInConferenceID": "",
|
||||
"dialInNotSupported": "",
|
||||
"dialInNumber": "",
|
||||
"dialInSummaryError": "",
|
||||
"dialInTollFree": "",
|
||||
"genericError": "",
|
||||
"inviteLiveStream": "",
|
||||
"invitePhone": "",
|
||||
"invitePhoneAlternatives": "",
|
||||
"inviteURLFirstPartGeneral": "",
|
||||
"inviteURLFirstPartPersonal": "",
|
||||
"inviteURLSecondPart": "",
|
||||
"liveStreamURL": "Излъчване на живо",
|
||||
"moreNumbers": "",
|
||||
"noNumbers": "",
|
||||
"accessibilityLabel": "Покажи информация",
|
||||
"addPassword": "Добави $t(lockRoomPassword)",
|
||||
"cancelPassword": "Премахни $t(lockRoomPassword)",
|
||||
"conferenceURL": "Връзка:",
|
||||
"country": "Страна",
|
||||
"dialANumber": "За влизане в срещата, наберете един от изброените номера и въведете кода.",
|
||||
"dialInConferenceID": "Код:",
|
||||
"dialInNotSupported": "Съжаляваме, обаждането в момента не се поддържа. ",
|
||||
"dialInNumber": "Тел:",
|
||||
"dialInSummaryError": "Проблем при достъпа на информация за опциите за влизане през телефон. Моля опитайте отново по-късно.",
|
||||
"dialInTollFree": "Безплатен",
|
||||
"genericError": "Упс, нещо се случи.",
|
||||
"inviteLiveStream": "За да видите предаването на живо на срещата, използвйте тази връзка: {{url}}",
|
||||
"invitePhone": "За влизане през телефон, използвайте: {{number}},,{{conferenceID}}#\n",
|
||||
"invitePhoneAlternatives": "Търсене на друг номер за набиране?\nВижте още номера: : {{url}}\n\n\nАко вече сте набрали от телефон в стаята, влезте без да е пуснат звука: {{silentUrl}}",
|
||||
"inviteURLFirstPartGeneral": "Поканени сте да се присъедините към среща.",
|
||||
"inviteURLFirstPartPersonal": "{{name}} ви кани за среща.\n",
|
||||
"inviteURLSecondPart": "\nВлезте в срещата:\n{{url}}\n",
|
||||
"liveStreamURL": "Излъчване на живо:",
|
||||
"moreNumbers": "Повече номера",
|
||||
"noNumbers": "Няма номера за набиране.",
|
||||
"noPassword": "Няма",
|
||||
"noRoom": "",
|
||||
"numbers": "",
|
||||
"password": "",
|
||||
"noRoom": "Няма посочена стая за информация за номера за набиране.",
|
||||
"numbers": "Номера",
|
||||
"password": "$t(lockRoomPasswordUppercase):",
|
||||
"title": "Споделяне",
|
||||
"tooltip": "",
|
||||
"label": ""
|
||||
"tooltip": "Споделете връзката и информацията за номера свързани със срещата",
|
||||
"label": "Информация за срещата"
|
||||
},
|
||||
"\u0005info": {},
|
||||
"inviteDialog": {
|
||||
"alertText": "",
|
||||
"alertText": "Не успях да поканя участниците.",
|
||||
"header": "Покани",
|
||||
"searchCallOnlyPlaceholder": "Въведете телефонен номер",
|
||||
"searchPeopleOnlyPlaceholder": "",
|
||||
"searchPlaceholder": "",
|
||||
"send": ""
|
||||
"searchPeopleOnlyPlaceholder": "Търсене на участници",
|
||||
"searchPlaceholder": "Участник или телефонен номер",
|
||||
"send": "Изпрати"
|
||||
},
|
||||
"inlineDialogFailure": {
|
||||
"msg": "Имаше грешка.",
|
||||
@@ -329,181 +324,182 @@
|
||||
},
|
||||
"keyboardShortcuts": {
|
||||
"focusLocal": "Фокусиране върху Вашето видео",
|
||||
"focusRemote": "Фокусиране върху видеото на друг участник",
|
||||
"focusRemote": "Фокусирай видеото на друг участник",
|
||||
"fullScreen": "Влизане/излизане от режим на цял екран",
|
||||
"keyboardShortcuts": "Клавишни комбинации",
|
||||
"localRecording": "",
|
||||
"localRecording": "Показване или скриване на контролите за локален запис",
|
||||
"mute": "Спиране/пускане на микрофона",
|
||||
"pushToTalk": "Натиснете, за да говорите",
|
||||
"raiseHand": "Вдигнете или свалете ръка",
|
||||
"showSpeakerStats": "Показване на статистика за говорителя",
|
||||
"toggleChat": "Отваряне/скриване на текстовите съобщения",
|
||||
"toggleFilmstrip": "",
|
||||
"toggleFilmstrip": "Показване или скриване на видео миниатюрите",
|
||||
"toggleScreensharing": "Смяна между камера и споделен екран",
|
||||
"toggleShortcuts": "",
|
||||
"videoMute": "Пускане/спиране на камерата"
|
||||
"toggleShortcuts": "Показване или скриване на клавишните комбинации",
|
||||
"videoMute": "Пускане/спиране на камерата",
|
||||
"videoQuality": "Управление на качество на обаждането"
|
||||
},
|
||||
"\u0005keyboardShortcuts": {},
|
||||
"liveStreaming": {
|
||||
"busy": "Работим върху това да освободим ресурси за излъчване. Моля, опитайте отново след няколко минути.",
|
||||
"busyTitle": "Всички излъчватели в момента са заети.",
|
||||
"changeSignIn": "",
|
||||
"choose": "",
|
||||
"chooseCTA": "",
|
||||
"enterStreamKey": "",
|
||||
"changeSignIn": "Смяна на акаунти.",
|
||||
"choose": "Изберете предаване на живо",
|
||||
"chooseCTA": "Изберете опция за предаване. Влезли сте като {{email}}.",
|
||||
"enterStreamKey": "Въведете ключа от YouTube за предаване на живо.",
|
||||
"error": "Излъчването на живо беше неуспешно. Моля, опитайте отново.",
|
||||
"errorAPI": "",
|
||||
"errorLiveStreamNotEnabled": "",
|
||||
"expandedOff": "",
|
||||
"expandedOn": "",
|
||||
"expandedPending": "",
|
||||
"errorAPI": "Изникна проблем с връзката към YouTube. Моля опитайте отново.",
|
||||
"errorLiveStreamNotEnabled": "Предаването на живо не е пуснато за {{email}}. Моля активирайте го или сменете акаунта.",
|
||||
"expandedOff": "Предаването на живо бе спряно",
|
||||
"expandedOn": "Срещата се излъчва на живо в YouTube.",
|
||||
"expandedPending": "Излъчването на живо се стартира...",
|
||||
"failedToStart": "Излъчването на живо не успя да започне",
|
||||
"getStreamKeyManually": "",
|
||||
"invalidStreamKey": "",
|
||||
"getStreamKeyManually": "Не успяхме да открием никакво предаване на живо. Опитайте да вземете ключа за такова от YouTube.",
|
||||
"invalidStreamKey": "Ключът за предаване на живо е грешен.",
|
||||
"off": "Край на излъчването на живо",
|
||||
"offBy": "{{name}} спря излъчването на живо",
|
||||
"on": "Излъчване на живо",
|
||||
"onBy": "{{name}} пусна излъчване на живо",
|
||||
"pending": "Започване на излъчването на живо…",
|
||||
"serviceName": "",
|
||||
"signedInAs": "",
|
||||
"signIn": "",
|
||||
"signInCTA": "",
|
||||
"serviceName": "Предаване на живо",
|
||||
"signedInAs": "В момента сте влезли като:",
|
||||
"signIn": "Влезте с Гугъл",
|
||||
"signInCTA": "Влезте или въведете ключът за излъчване на живо от YouTube.",
|
||||
"signOut": "",
|
||||
"start": "Започване на излъчване на живо",
|
||||
"streamIdHelp": "",
|
||||
"start": "Започни излъчване на живо",
|
||||
"streamIdHelp": "Какво е това?",
|
||||
"unavailableTitle": "Излъчването на живо е недостъпно"
|
||||
},
|
||||
"\u0005liveStreaming": {},
|
||||
"localRecording": {
|
||||
"clientState": {
|
||||
"off": "",
|
||||
"on": "",
|
||||
"unknown": ""
|
||||
"off": "Изключено",
|
||||
"on": "Включено",
|
||||
"unknown": "Непознат"
|
||||
},
|
||||
"dialogTitle": "",
|
||||
"duration": "",
|
||||
"durationNA": "",
|
||||
"encoding": "",
|
||||
"label": "",
|
||||
"labelToolTip": "",
|
||||
"localRecording": "",
|
||||
"dialogTitle": "Управление на локален запис",
|
||||
"duration": "Продължителност",
|
||||
"durationNA": "Няма",
|
||||
"encoding": "Кодек",
|
||||
"label": "Етикет",
|
||||
"labelToolTip": "Локалния запис е включен",
|
||||
"localRecording": "Локален запис",
|
||||
"me": "Аз",
|
||||
"messages": {
|
||||
"engaged": "",
|
||||
"finished": "",
|
||||
"finishedModerator": "",
|
||||
"notModerator": ""
|
||||
"engaged": "Локалния запис е включен.",
|
||||
"finished": "Записа на сесията {{token}} приключи. Моля изпратете записа на вашият домакин.",
|
||||
"finishedModerator": "Сесията {{token}} за запис приключи. Локалният запис беше запазен. Моля поканете останалите участници да ви изпратят техните записи.",
|
||||
"notModerator": "Нямате права да пускате спирате локален запис."
|
||||
},
|
||||
"moderator": "Модератор",
|
||||
"no": "",
|
||||
"no": "Не",
|
||||
"participant": "Участник",
|
||||
"participantStats": "",
|
||||
"sessionToken": "",
|
||||
"start": "Край на записа",
|
||||
"stop": "Край на записа",
|
||||
"participantStats": "Статистика на участник",
|
||||
"sessionToken": "Тоукън за сесията",
|
||||
"start": "Започни запис",
|
||||
"stop": "Спри записа",
|
||||
"yes": "Да"
|
||||
},
|
||||
"\u0005localRecording": {},
|
||||
"lockRoomPassword": "парола",
|
||||
"lockRoomPasswordUppercase": "Парола",
|
||||
"me": "аз",
|
||||
"notify": {
|
||||
"connectedOneMember": "",
|
||||
"connectedThreePlusMembers": "",
|
||||
"connectedTwoMembers": "",
|
||||
"disconnected": "Връзка:",
|
||||
"connectedOneMember": "{{name}} влезна в срещата",
|
||||
"connectedThreePlusMembers": "{{name}} и още {{count}} влезнаха в срещата",
|
||||
"connectedTwoMembers": "{{first}} и {{second}} влезнаха в срещата",
|
||||
"disconnected": "Напусна срещата",
|
||||
"focus": "Конферентен фокус",
|
||||
"focusFail": "{{component}} не е на раположения - следващ опит след {{ms}} секунди",
|
||||
"focusFail": "{{component}} не е на раположение - следващ опит след {{ms}} секунди",
|
||||
"grantedTo": "Даване на роля модератор на {{to}}!",
|
||||
"invitedOneMember": "",
|
||||
"invitedThreePlusMembers": "",
|
||||
"invitedTwoMembers": "",
|
||||
"kickParticipant": "",
|
||||
"invitedOneMember": "{{name}} бе поканен",
|
||||
"invitedThreePlusMembers": "{{name}} и още {{count}} бяха поканени",
|
||||
"invitedTwoMembers": "{{first}} и {{second}} бяха поканени",
|
||||
"kickParticipant": "{{kicked}} беше изгонен от {{kicker}}",
|
||||
"me": "Аз",
|
||||
"moderator": "Придобихте права на модератор!",
|
||||
"muted": "Започвате разговора без звук.",
|
||||
"mutedTitle": "Звукът ви е спрян!",
|
||||
"mutedRemotelyTitle": "",
|
||||
"mutedRemotelyDescription": "",
|
||||
"passwordRemovedRemotely": "",
|
||||
"passwordSetRemotely": "",
|
||||
"raisedHand": "",
|
||||
"mutedRemotelyTitle": "Микрофонът ви бе спрян от {{participantDisplayName}}!",
|
||||
"mutedRemotelyDescription": "Винаги можете да пуснете микрофона си когато сте готови да говорите. Заглушете го отново за да не изпращате шум в срещата.",
|
||||
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) е премахната от друг потребител",
|
||||
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) създадена от друг потребител",
|
||||
"raisedHand": "{{name}} иска думата.",
|
||||
"somebody": "Някой",
|
||||
"startSilentTitle": "",
|
||||
"startSilentDescription": "",
|
||||
"suboptimalExperienceDescription": "",
|
||||
"suboptimalExperienceTitle": "",
|
||||
"unmute": "",
|
||||
"newDeviceCameraTitle": "",
|
||||
"newDeviceAudioTitle": "",
|
||||
"newDeviceAction": ""
|
||||
"startSilentTitle": "Влязохте с опция да не чувате аудио!",
|
||||
"startSilentDescription": "Влезте повторно за да пуснете звука",
|
||||
"suboptimalBrowserWarning": "Опасяваме се, че няма да можете да се насладите на срещата. Работим по въпроса, междувременно използвайте някой от <a href='static/recommendedBrowsers.html' target='_blank'>напълно поддържаните браузъри</a>.",
|
||||
"suboptimalExperienceTitle": "Внимание",
|
||||
"unmute": "Пускане на микрофона",
|
||||
"newDeviceCameraTitle": "Засечена е нова камера",
|
||||
"newDeviceAudioTitle": "Ново аудио устройство е засечено",
|
||||
"newDeviceAction": "Използвай"
|
||||
},
|
||||
"passwordSetRemotely": "",
|
||||
"passwordDigitsOnly": "",
|
||||
"passwordSetRemotely": "зададена от друг участник",
|
||||
"passwordDigitsOnly": "До {{number}} цифри",
|
||||
"poweredby": "с подкрепата на",
|
||||
"presenceStatus": {
|
||||
"busy": "",
|
||||
"calling": "",
|
||||
"busy": "Зает",
|
||||
"calling": "Обаждане...",
|
||||
"connected": "Свързан",
|
||||
"connecting": "Свързване",
|
||||
"connecting2": "Свързване",
|
||||
"connecting": "Свързване...",
|
||||
"connecting2": "Свързване*...",
|
||||
"disconnected": "Изключен",
|
||||
"expired": "",
|
||||
"ignored": "",
|
||||
"initializingCall": "",
|
||||
"invited": "Покани",
|
||||
"rejected": "",
|
||||
"ringing": ""
|
||||
"expired": "Изтекъл",
|
||||
"ignored": "Пренебрегнат",
|
||||
"initializingCall": "Свързване на обаждането...",
|
||||
"invited": "Поканен",
|
||||
"rejected": "Отхвърлен",
|
||||
"ringing": "Звъни..."
|
||||
},
|
||||
"\u0005presenceStatus": {},
|
||||
"profile": {
|
||||
"setDisplayNameLabel": "Задайте екранното си име",
|
||||
"setEmailInput": "Въведете е-поща",
|
||||
"setEmailLabel": "Задайте е-пощата си в „gravatar“",
|
||||
"title": "Профил"
|
||||
},
|
||||
"raisedHand": "Иска думата",
|
||||
"recording": {
|
||||
"authDropboxText": "",
|
||||
"availableSpace": "",
|
||||
"beta": "",
|
||||
"authDropboxText": "Качете в Dropbox",
|
||||
"availableSpace": "Налично място: {{spaceLeft}} MB (приблизително {{duration}} минути запис)",
|
||||
"beta": "БЕТА",
|
||||
"busy": "Работим върху това да освободим ресурси за запис. Моля, опитайте отново след няколко минути.",
|
||||
"busyTitle": "Всички възможности за запис в момента са заети",
|
||||
"error": "Грешка при опит за запис. Моля опитайте отново.",
|
||||
"expandedOff": "Записът спрян",
|
||||
"expandedOn": "",
|
||||
"expandedPending": "Записът започна",
|
||||
"expandedOff": "Записът спря",
|
||||
"expandedOn": "Срещата се записва в момента",
|
||||
"expandedPending": "Записът започва...",
|
||||
"failedToStart": "Неуспешен опит за записване",
|
||||
"fileSharingdescription": "",
|
||||
"live": "",
|
||||
"loggedIn": "",
|
||||
"fileSharingdescription": "Споделете записа с участниците в срещата",
|
||||
"live": "На Живо",
|
||||
"loggedIn": "Влезли сте като {{userName}}",
|
||||
"off": "Записът спрян",
|
||||
"offBy": "{{name}} спря записът",
|
||||
"on": "Запис",
|
||||
"pending": "",
|
||||
"rec": "",
|
||||
"serviceDescription": "",
|
||||
"serviceName": "",
|
||||
"signIn": "",
|
||||
"signOut": "",
|
||||
"unavailable": "",
|
||||
"onBy": "{{name}} пусна запис",
|
||||
"pending": "Стартира запис на срещата...",
|
||||
"rec": "ЗАПИС",
|
||||
"serviceDescription": "Записът ви ще се запише от специална записваща услуга",
|
||||
"serviceName": "Записваща услуга",
|
||||
"signIn": "Влизане",
|
||||
"signOut": "Излизане",
|
||||
"unavailable": "Упс! В момент {{serviceName}} е недостъпна. В момента се опитваме да решим проблема. Моля опитайте отново малко по-късно.",
|
||||
"unavailableTitle": "Записът е невъзможен"
|
||||
},
|
||||
"\u0005recording": {},
|
||||
"sectionList": {
|
||||
"pullToRefresh": ""
|
||||
"pullToRefresh": "Издърпай за да се обнови"
|
||||
},
|
||||
"settings": {
|
||||
"calendar": {
|
||||
"about": "",
|
||||
"disconnect": "Изключен",
|
||||
"microsoftSignIn": "",
|
||||
"signedIn": "",
|
||||
"about": "Календарната интеграция на {{appName}} сигурно достъпва вашия календар за да покаже настъпващите събития.",
|
||||
"disconnect": "Разкачи",
|
||||
"microsoftSignIn": "Влез с Microsoft акаунт",
|
||||
"signedIn": "В момента достъпва календара с {{email}}. Натиснете бутона Разкачи за да спрете достъпа.",
|
||||
"title": ""
|
||||
},
|
||||
"devices": "",
|
||||
"devices": "Устройства",
|
||||
"followMe": "Всички ме следват",
|
||||
"language": "",
|
||||
"loggedIn": "",
|
||||
"language": "Език",
|
||||
"loggedIn": "Влезли сте като {{name}}",
|
||||
"moderator": "Модератор",
|
||||
"more": "",
|
||||
"more": "Повече",
|
||||
"name": "Име",
|
||||
"noDevice": "Няма",
|
||||
"selectAudioOutput": "Звуков изход",
|
||||
@@ -513,27 +509,24 @@
|
||||
"startVideoMuted": "Всички започват скрити",
|
||||
"title": "Настройки"
|
||||
},
|
||||
"\u0005settings": {
|
||||
"calendar": {}
|
||||
},
|
||||
"settingsView": {
|
||||
"alertOk": "",
|
||||
"alertOk": "Потвърди",
|
||||
"alertTitle": "Внимание",
|
||||
"alertURLText": "",
|
||||
"buildInfoSection": "",
|
||||
"conferenceSection": "",
|
||||
"displayName": "",
|
||||
"email": "",
|
||||
"alertURLText": "Въведената връзка за сървър е невалидна",
|
||||
"buildInfoSection": "Информация за програмата",
|
||||
"conferenceSection": "Конференция",
|
||||
"displayName": "Име",
|
||||
"email": "Поща",
|
||||
"header": "Настройки",
|
||||
"profileSection": "Профил",
|
||||
"serverURL": "",
|
||||
"startWithAudioMuted": "",
|
||||
"startWithVideoMuted": "",
|
||||
"version": ""
|
||||
"serverURL": "Линк на сървъра",
|
||||
"startWithAudioMuted": "Започни със спрян звук",
|
||||
"startWithVideoMuted": "Започни със спряно видео",
|
||||
"version": "Версия"
|
||||
},
|
||||
"share": {
|
||||
"dialInfoText": "",
|
||||
"mainText": ""
|
||||
"dialInfoText": "\n\n=====\n\nИскате да наберете от телефона?\n\n{{defaultDialInNumber}}Използвайте този линк за повече номера\n{{dialInfoPageUrl}}",
|
||||
"mainText": "Използвайте линка за да влезете в срещата:\n{{roomUrl}}"
|
||||
},
|
||||
"speaker": "Говорещ",
|
||||
"speakerStats": {
|
||||
@@ -555,99 +548,95 @@
|
||||
},
|
||||
"toolbar": {
|
||||
"accessibilityLabel": {
|
||||
"audioOnly": "",
|
||||
"audioOnly": "Пускане на режим само с звук",
|
||||
"audioRoute": "",
|
||||
"callQuality": "",
|
||||
"cc": "",
|
||||
"chat": "",
|
||||
"document": "Отваряне/затваряне на споделен документ",
|
||||
"callQuality": "Управление на качестото на обаждането",
|
||||
"cc": "Пускане на субтитри",
|
||||
"chat": "Активиране на прозорец за съобщения",
|
||||
"document": "Показване на споделен документ",
|
||||
"feedback": "",
|
||||
"fullScreen": "",
|
||||
"hangup": "",
|
||||
"fullScreen": "Пускане/Спиране на изглед в цял екран",
|
||||
"hangup": "Напускане на срещата",
|
||||
"invite": "Поканете участници",
|
||||
"kick": "",
|
||||
"localRecording": "",
|
||||
"lockRoom": "",
|
||||
"moreActions": "",
|
||||
"moreActionsMenu": "",
|
||||
"mute": "",
|
||||
"pip": "",
|
||||
"kick": "Изгони участник",
|
||||
"localRecording": "Показване на контроли за локален запис",
|
||||
"lockRoom": "Смяна парола на среща",
|
||||
"moreActions": "Показване на меню с повече опции",
|
||||
"moreActionsMenu": "Меню с повече опции",
|
||||
"mute": "Пускане/спиране на видеото",
|
||||
"pip": "Пускане на Картина-в-Картина",
|
||||
"profile": "Редактиране на профила",
|
||||
"raiseHand": "",
|
||||
"recording": "",
|
||||
"remoteMute": "",
|
||||
"Settings": "",
|
||||
"sharedvideo": "",
|
||||
"raiseHand": "Смяна искане на думата",
|
||||
"recording": "Пускане/спиране на запис",
|
||||
"remoteMute": "Заглуши участник",
|
||||
"Settings": "Промяна на настройки",
|
||||
"sharedvideo": "Споделяне на YouTube видео",
|
||||
"shareRoom": "",
|
||||
"shareYourScreen": "",
|
||||
"shortcuts": "",
|
||||
"shareYourScreen": "Споделяне на екрана",
|
||||
"shortcuts": "Бързи клавиши",
|
||||
"show": "",
|
||||
"speakerStats": "",
|
||||
"speakerStats": "Показване на статистики за участниците",
|
||||
"tileView": "",
|
||||
"toggleCamera": "",
|
||||
"videomute": "",
|
||||
"videoblur": ""
|
||||
"videomute": "Пускане/спиране на видеото",
|
||||
"videoblur": "Пускане/спиране на замъгляване на видеото"
|
||||
},
|
||||
"addPeople": "Добавяне на участници в разговора",
|
||||
"audioOnlyOff": "",
|
||||
"audioOnlyOn": "",
|
||||
"audioRoute": "",
|
||||
"audioOnlyOff": "Спиране режима с нисък трафик",
|
||||
"audioOnlyOn": "Пускане режима с нисък трафик",
|
||||
"audioRoute": "Изберете устройство за звук",
|
||||
"authenticate": "Идентификация",
|
||||
"callQuality": "",
|
||||
"callQuality": "Промяна качеството на видеото",
|
||||
"chat": "Отваряне/затваряне на текстовите съобщения",
|
||||
"closeChat": "",
|
||||
"documentClose": "Отваряне/затваряне на споделен документ",
|
||||
"documentOpen": "Отваряне/затваряне на споделен документ",
|
||||
"enterFullScreen": "",
|
||||
"enterTileView": "",
|
||||
"exitFullScreen": "",
|
||||
"exitTileView": "",
|
||||
"feedback": "",
|
||||
"closeChat": "Затваряне на съобщенията",
|
||||
"documentClose": "Затваряне на споделеният документ",
|
||||
"documentOpen": "Отваряне на споделен документ",
|
||||
"enterFullScreen": "Вижте на цял екран",
|
||||
"enterTileView": "Влизане в изглед галерия",
|
||||
"exitFullScreen": "Изход от цял екран",
|
||||
"exitTileView": "Спиране на изглед галерия",
|
||||
"feedback": "Отзиви",
|
||||
"hangup": "Напускане",
|
||||
"invite": "Поканете участници",
|
||||
"login": "Влез",
|
||||
"logout": "Изход",
|
||||
"lowerYourHand": "",
|
||||
"moreActions": "",
|
||||
"lowerYourHand": "Махни искането на думата",
|
||||
"moreActions": "Още опции",
|
||||
"mute": "Спиране/пускане на микрофона",
|
||||
"openChat": "",
|
||||
"pip": "",
|
||||
"openChat": "Отвори съобщенията",
|
||||
"pip": "Пусни Картина-в-Картина",
|
||||
"profile": "Редактиране на профила",
|
||||
"raiseHand": "Вдигане/сваляне на ръка",
|
||||
"raiseYourHand": "Вдигни ръка.",
|
||||
"raiseYourHand": "Поискай думата",
|
||||
"Settings": "Настройки",
|
||||
"sharedvideo": "Пускане/спиране на споделянето на екрана",
|
||||
"shareRoom": "",
|
||||
"shortcuts": "",
|
||||
"speakerStats": "Статистика на говорителя",
|
||||
"startScreenSharing": "",
|
||||
"startSubtitles": "",
|
||||
"stopScreenSharing": "",
|
||||
"stopSubtitles": "",
|
||||
"stopSharedVideo": "",
|
||||
"shareRoom": "Добавете някого",
|
||||
"shortcuts": "Виж бързите клавиши",
|
||||
"speakerStats": "Статистика за говорителите",
|
||||
"startScreenSharing": "Започни споделяне на екрана",
|
||||
"startSubtitles": "Пускане на субтитри",
|
||||
"stopScreenSharing": "Спиране споделяне на екрана",
|
||||
"stopSubtitles": "Спиране на субтитри",
|
||||
"stopSharedVideo": "Спиране на YouTube видео",
|
||||
"talkWhileMutedPopup": "Опитвате се да говорите? В момента микрофонът Ви е заглушен.",
|
||||
"tileViewToggle": "",
|
||||
"toggleCamera": "",
|
||||
"tileViewToggle": "Превключване на изглед галерия",
|
||||
"toggleCamera": "Пускане/спиране на камера",
|
||||
"videomute": "Пускане/спиране на камерата",
|
||||
"startvideoblur": "",
|
||||
"stopvideoblur": ""
|
||||
},
|
||||
"\u0005toolbar": {
|
||||
"accessibilityLabel": {}
|
||||
"startvideoblur": "Замъгли фона ми",
|
||||
"stopvideoblur": "Спиране замъгляването на фона"
|
||||
},
|
||||
"transcribing": {
|
||||
"ccButtonTooltip": "",
|
||||
"error": "Грешка при опит за запис. Моля опитайте отново.",
|
||||
"expandedLabel": "",
|
||||
"failedToStart": "",
|
||||
"labelToolTip": "",
|
||||
"off": "",
|
||||
"pending": "",
|
||||
"start": "",
|
||||
"stop": "",
|
||||
"tr": ""
|
||||
"ccButtonTooltip": "Пускане / Спиране на субтитри",
|
||||
"error": "Грешка при опит за транскрибиране. Моля опитайте отново.",
|
||||
"expandedLabel": "Транскрибирането е пуснато",
|
||||
"failedToStart": "Транскрибирането не успя при пускане",
|
||||
"labelToolTip": "Тази среща се транскрибира",
|
||||
"off": "Транскрибирането спря",
|
||||
"pending": "Стартира се транскрибиране на срещата...",
|
||||
"start": "Започва показване на субтитри",
|
||||
"stop": "Спира показване на субтитри",
|
||||
"tr": "СУБ"
|
||||
},
|
||||
"\u0005transcribing": {},
|
||||
"userMedia": {
|
||||
"androidGrantPermissions": "Изберете <b><i>Разрешаване</i></b>, когато браузърът Ви помоли за разрешение.",
|
||||
"chromeGrantPermissions": "Изберете <b><i>Разрешаване</i></b>, когато браузърът Ви помоли за разрешение.",
|
||||
@@ -661,31 +650,34 @@
|
||||
"safariGrantPermissions": "Изберете <b><i>Добре</i></b>, когато браузърът Ви помоли за разрешение."
|
||||
},
|
||||
"videoSIPGW": {
|
||||
"busy": "",
|
||||
"busyTitle": "",
|
||||
"errorAlreadyInvited": "",
|
||||
"errorInvite": "",
|
||||
"errorInviteFailed": "",
|
||||
"errorInviteFailedTitle": "",
|
||||
"errorInviteTitle": "",
|
||||
"pending": ""
|
||||
"busy": "Работим по освобождаване на ресурси. Моля, опитайте след няколко минути.",
|
||||
"busyTitle": "Услугата за стаи в момента е заета",
|
||||
"errorAlreadyInvited": "{{displayName}} вече е поканен",
|
||||
"errorInvite": "Конференцията не е стартирана. Моля, опитайте по-късно.",
|
||||
"errorInviteFailed": "Работим по разрешаването на проблем. Моля, опитайте по-късно.",
|
||||
"errorInviteFailedTitle": "Добавянето на {{displayName}} не успя",
|
||||
"errorInviteTitle": "Грешка при добавяне на стая",
|
||||
"pending": "{{displayName}} бе поканен"
|
||||
},
|
||||
"videoStatus": {
|
||||
"audioOnly": "",
|
||||
"audioOnlyExpanded": "",
|
||||
"callQuality": "",
|
||||
"audioOnly": "АУДИО",
|
||||
"audioOnlyExpanded": "Вие сте в режим на нисък трафик. В този режим ще получавате само аудио или споделени екрани.",
|
||||
"callQuality": "Качество на видеото",
|
||||
"hd": "ВК",
|
||||
"hdTooltip": "Гледате високо качество на видеото",
|
||||
"highDefinition": "Високо качество",
|
||||
"labelTooiltipNoVideo": "",
|
||||
"labelTooltipAudioOnly": "Включен е режим само със звук",
|
||||
"labelTooiltipNoVideo": "Няма видео",
|
||||
"labelTooltipAudioOnly": "Пуснат режим на нисък трафик",
|
||||
"ld": "НК",
|
||||
"ldTooltip": "Виждате ниско качество на видеото",
|
||||
"lowDefinition": "Ниско качество",
|
||||
"onlyAudioAvailable": "",
|
||||
"onlyAudioSupported": "",
|
||||
"onlyAudioAvailable": "Само аудио е налично",
|
||||
"onlyAudioSupported": "Този браузър поддържа само аудио.",
|
||||
"p2pEnabled": "Вкл. директно свързване",
|
||||
"p2pVideoQualityDescription": "",
|
||||
"p2pVideoQualityDescription": "В директна връзка, получаваното качество може да се сменя между високо и само аудио. Останалите настройки ще са достъпни когато връзката не е директна.",
|
||||
"recHighDefinitionOnly": "Ще се предпочита високо качество.",
|
||||
"sd": "СК",
|
||||
"sdTooltip": "Гледате стандартно качество на видеото",
|
||||
"standardDefinition": "Стандартно качество"
|
||||
},
|
||||
"videothumbnail": {
|
||||
@@ -693,38 +685,39 @@
|
||||
"flip": "Огледално",
|
||||
"kick": "Изгони",
|
||||
"moderator": "Модератор",
|
||||
"mute": "Учасника е с изключен микрофон",
|
||||
"mute": "Участника е с изключен микрофон",
|
||||
"muted": "Изключен микрофон",
|
||||
"remoteControl": "Отдалечено управление",
|
||||
"show": "",
|
||||
"videomute": ""
|
||||
"show": "Покажи на главния екран",
|
||||
"videomute": "Участник е спрял камерата си"
|
||||
},
|
||||
"welcomepage": {
|
||||
"accessibilityLabel": {
|
||||
"join": "",
|
||||
"join": "Натиснете за да влезете",
|
||||
"roomname": "Въведете име на стаята"
|
||||
},
|
||||
"appDescription": "",
|
||||
"appDescription": "Хайде на видео разговорите с целият ви екип. Всъщност, поканете всички познати. {{app}} е напълно защитено, 100% решение за видеоконференции с отворен код което може да ползвате по цял ден, всеки ден, безплатно - без да ви е нужна регистрация.",
|
||||
"audioVideoSwitch": {
|
||||
"audio": "",
|
||||
"video": ""
|
||||
"audio": "Глас",
|
||||
"video": "Видео"
|
||||
},
|
||||
"calendar": "",
|
||||
"connectCalendarButton": "",
|
||||
"connectCalendarText": "",
|
||||
"enterRoomTitle": "",
|
||||
"calendar": "Календар",
|
||||
"connectCalendarButton": "Свържете вашия календар",
|
||||
"connectCalendarText": "Свържете вашия календар за да видите срещите си в {{app}}. Добавяйки {{provider}} срещите в календара си ще можете да ги старирате с едно докосване.",
|
||||
"enterRoomTitle": "Започни нова среща",
|
||||
"onlyAsciiAllowed": "Името на срещата може да съдържа само латински букви и цифри.",
|
||||
"go": "НАПРЕД",
|
||||
"join": "ПРИСЪЕДИНЯВАНЕ",
|
||||
"info": "",
|
||||
"info": "Информация",
|
||||
"privacy": "Поверителност",
|
||||
"recentList": "",
|
||||
"recentListDelete": "",
|
||||
"recentListEmpty": "",
|
||||
"reducedUIText": "",
|
||||
"recentList": "Скорошни срещи",
|
||||
"recentListDelete": "Изтрий",
|
||||
"recentListEmpty": "Списъка с скорошни срещи е празен. След като участвате в някоя среща, ще я намерите тук.",
|
||||
"reducedUIText": "Добре дошли в {{app}}!",
|
||||
"roomname": "Въведете име на стаята",
|
||||
"roomnameHint": "",
|
||||
"roomnameHint": "Въведете името или връзката на стаята в която искате да влезете. Също може да си измислите име. Само го споделете с някой, за да може и той да въведе същото име за да се срещнете.",
|
||||
"sendFeedback": "Изпращане на отзиви",
|
||||
"terms": "Условия",
|
||||
"title": ""
|
||||
"title": "Сигурна, с много възможности, и напълно безплатна платформа за видео конференции"
|
||||
}
|
||||
}
|
||||
1187
lang/main-hu.json
1187
lang/main-hu.json
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,7 @@
|
||||
"headphones": "Escotadors",
|
||||
"phone": "Telefòn",
|
||||
"speaker": "Nautparlaire",
|
||||
"none": ""
|
||||
"none": "Cap de periferic àudio pas disponible"
|
||||
},
|
||||
"audioOnly": {
|
||||
"audioOnly": "Benda passanta febla"
|
||||
@@ -182,7 +182,7 @@
|
||||
"liveStreamingDisabledForGuestTooltip": "Los convidats pòdon pas aviar una difusion en dirècte",
|
||||
"liveStreamingDisabledTooltip": "Difusion en dirècte desactivada.",
|
||||
"lockMessage": "Impossible de verrolhar la conferéncia.",
|
||||
"lockRoom": "",
|
||||
"lockRoom": "Ajustar un $t(lockRoomPasswordUppercase) a la conferéncia",
|
||||
"lockTitle": "Fracàs del verrolhatge",
|
||||
"logoutQuestion": "Sètz segur que vos volètz desconnectar e arrestar la conferéncia ?",
|
||||
"logoutTitle": "Desconnexion",
|
||||
@@ -199,10 +199,10 @@
|
||||
"muteParticipantDialog": "",
|
||||
"muteParticipantTitle": "Copar lo micro als participants ?",
|
||||
"Ok": "D'acòrdi",
|
||||
"passwordLabel": "",
|
||||
"passwordNotSupported": "Ajustar un senhal a una conferéncia es pas suportat.",
|
||||
"passwordNotSupportedTitle": "",
|
||||
"passwordRequired": "",
|
||||
"passwordLabel": "SENHAL",
|
||||
"passwordNotSupported": "Ajustar un $t(lockRoomPassword) a una conferéncia es pas suportat.",
|
||||
"passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) pas suportat",
|
||||
"passwordRequired": "$t(lockRoomPasswordUppercase) requesit",
|
||||
"popupError": "Vòstre navigator bloca las fenèstras que sorgisson a partir d'aqueste site. Mercés d'activar aquelas fenèstras dins los paramètres de vòstre navigator e de tornar ensajar.",
|
||||
"popupErrorTitle": "Fenèstra que sorgís blocada",
|
||||
"recording": "Enregistrament",
|
||||
@@ -217,7 +217,7 @@
|
||||
"remoteControlStopMessage": "La session de contraròtle alonhat es acabada !",
|
||||
"remoteControlTitle": "Contraròtle a distància",
|
||||
"Remove": "Suprimir",
|
||||
"removePassword": "",
|
||||
"removePassword": "Suprimir lo",
|
||||
"removeSharedVideoMsg": "Sètz segur que volètz suprimir vòstra vidèo partejada ?",
|
||||
"removeSharedVideoTitle": "Suprimir la vidèo partejada",
|
||||
"reservationError": "Error del sistèma de reservacion",
|
||||
@@ -250,7 +250,7 @@
|
||||
"tokenAuthFailed": "O planhèm, sètz pas autorizat a rejónher l'apèl.",
|
||||
"tokenAuthFailedTitle": "Fracàs de l'autentificacion",
|
||||
"transcribing": "Transcripcion",
|
||||
"unlockRoom": "",
|
||||
"unlockRoom": "Suprimir lo $t(lockRoomPassword) de la conferéncia",
|
||||
"userPassword": "senhal utilizaire",
|
||||
"WaitForHostMsg": "La conferéncia <b>{{room}}</b> a pas encara començat. Se sètz l’òst volgatz ben vos identificar. Autrament esperatz qu’arribe l’òste.",
|
||||
"WaitForHostMsgWOk": "La conferéncia <b>{{room}}</b> a pas encara començat. Se sètz l’òst volgatz ben clicar Ok per vos identificar. Autrament esperatz qu’arribe l’òste.",
|
||||
@@ -279,8 +279,8 @@
|
||||
},
|
||||
"info": {
|
||||
"accessibilityLabel": "Mostrar las info",
|
||||
"addPassword": "",
|
||||
"cancelPassword": "",
|
||||
"addPassword": "Ajustar un $t(lockRoomPassword)",
|
||||
"cancelPassword": "Anullar lo $t(lockRoomPassword)",
|
||||
"conferenceURL": "Ligam :",
|
||||
"country": "País",
|
||||
"dialANumber": "Per participar a la conferéncia, sonatz un d’aquestes numèros puèi picatz lo senhal.",
|
||||
@@ -355,7 +355,9 @@
|
||||
"getStreamKeyManually": "",
|
||||
"invalidStreamKey": "La clau de difusion en dirècte es benlèu pas corrècta.",
|
||||
"off": "La difusion en dirècte es estada arrestada",
|
||||
"offBy": "",
|
||||
"on": "La difusion en dirècte es estada arrestada",
|
||||
"onBy": "",
|
||||
"pending": "Començar lo dirècte...",
|
||||
"serviceName": "Servici de difusion en dirècte",
|
||||
"signedInAs": "Sètz connectat coma :",
|
||||
@@ -416,8 +418,8 @@
|
||||
"mutedTitle": "Sètz en mut !",
|
||||
"mutedRemotelyTitle": "{{participantDisplayName}} vos a mes en silenci !",
|
||||
"mutedRemotelyDescription": "",
|
||||
"passwordRemovedRemotely": "",
|
||||
"passwordSetRemotely": "",
|
||||
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) tirat per un autre participant",
|
||||
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) definit per un autre participant",
|
||||
"raisedHand": "{{name}} volriá parlar.",
|
||||
"somebody": "Qualqu'un",
|
||||
"startSilentTitle": "Avètz jonch sens cap de sortida àudio !",
|
||||
@@ -468,7 +470,9 @@
|
||||
"live": "DIRÈCTE",
|
||||
"loggedIn": "Session a {{userName}}",
|
||||
"off": "Enregistrament arrestar",
|
||||
"offBy": "",
|
||||
"on": "Enregistrament",
|
||||
"onBy": "",
|
||||
"pending": "Preparacion de l’enregistrament de la conferéncia...",
|
||||
"rec": "ENRG",
|
||||
"serviceDescription": "Vòstre enregistrament serà salvagardat pel servici dedicat.",
|
||||
@@ -508,7 +512,7 @@
|
||||
"alertOk": "D’acòrdi",
|
||||
"alertTitle": "Avertiment",
|
||||
"alertURLText": "L’URL del servidor es pas valida",
|
||||
"buildInfoSection": "",
|
||||
"buildInfoSection": "Informacions de generacion",
|
||||
"conferenceSection": "Conferéncia",
|
||||
"displayName": "Escais-nom",
|
||||
"email": "Corrièl",
|
||||
@@ -553,7 +557,7 @@
|
||||
"fullScreen": "Passar al ecran complèt",
|
||||
"hangup": "Quitar la sonada",
|
||||
"invite": "Convidar de monde",
|
||||
"kick": "",
|
||||
"kick": "Exclure un participan ",
|
||||
"localRecording": "Passar al panèl d’enregistraments locals",
|
||||
"lockRoom": "Tirar lo senhal de la conferéncia",
|
||||
"moreActions": "Passar al menú mai d’accions",
|
||||
@@ -563,7 +567,7 @@
|
||||
"profile": "Modificar vòstre perfil",
|
||||
"raiseHand": "Demandar la paraula",
|
||||
"recording": "Passar al enregistraments",
|
||||
"remoteMute": "",
|
||||
"remoteMute": "Copar lo son del participant",
|
||||
"Settings": "Passar als paramètres",
|
||||
"sharedvideo": "Passar al partatge de vidèo Youtube",
|
||||
"shareRoom": "Convidar qualqu’un",
|
||||
@@ -577,8 +581,8 @@
|
||||
"videoblur": ""
|
||||
},
|
||||
"addPeople": "Ajustar de monde a vòstra sonada",
|
||||
"audioOnlyOff": "",
|
||||
"audioOnlyOn": "",
|
||||
"audioOnlyOff": "Desactivar lo mòde connexion febla",
|
||||
"audioOnlyOn": "Activar lo mòde connexion febla",
|
||||
"audioRoute": "Seleccionar lo periferic àudio",
|
||||
"authenticate": "Autentificatz-vos",
|
||||
"callQuality": "Gerir la qualitat vidèo",
|
||||
@@ -587,9 +591,9 @@
|
||||
"documentClose": "Tampar los documents partejats",
|
||||
"documentOpen": "Dobrir los documents partejats",
|
||||
"enterFullScreen": "Veire l’ecran complèt",
|
||||
"enterTileView": "",
|
||||
"enterTileView": "Dintrar dins la vista mosaïca",
|
||||
"exitFullScreen": "Sortir de l’ecran complèt",
|
||||
"exitTileView": "",
|
||||
"exitTileView": "Quitar la vista mosaïca",
|
||||
"feedback": "Daissar un comentari",
|
||||
"hangup": "Quitar",
|
||||
"invite": "Convidar de monde",
|
||||
@@ -617,8 +621,8 @@
|
||||
"tileViewToggle": "Activar/Desactivar la vista en mosaïc",
|
||||
"toggleCamera": "Passar a la camèra",
|
||||
"videomute": "Aviar / Arrestar la camèra",
|
||||
"startvideoblur": "",
|
||||
"stopvideoblur": ""
|
||||
"startvideoblur": "Trebolar mon rèire-plan",
|
||||
"stopvideoblur": "Desactivar lo borrolatge del rèire-plan"
|
||||
},
|
||||
"transcribing": {
|
||||
"ccButtonTooltip": "Aviar / Arrestat los sostítols",
|
||||
@@ -656,13 +660,13 @@
|
||||
},
|
||||
"videoStatus": {
|
||||
"audioOnly": "AUD",
|
||||
"audioOnlyExpanded": "",
|
||||
"audioOnlyExpanded": "Sètz en mòde connexion febla. Amb aqueste mòde recebretz pas que l’àudio e lo partatge d’ecran.",
|
||||
"callQuality": "Qualitat vidèo",
|
||||
"hd": "HD",
|
||||
"hdTooltip": "Difusion vidèo en nauta definicion",
|
||||
"highDefinition": "Nauta definicion",
|
||||
"labelTooiltipNoVideo": "Pas cap de vidèo",
|
||||
"labelTooltipAudioOnly": "",
|
||||
"labelTooltipAudioOnly": "Mòde connexion febla activat",
|
||||
"ld": "Bassa definicion",
|
||||
"ldTooltip": "Difusion vidèo en bassa definicion",
|
||||
"lowDefinition": "Bassa definicion",
|
||||
@@ -684,7 +688,7 @@
|
||||
"muted": "Mut",
|
||||
"remoteControl": "Contraròtle alonhat",
|
||||
"show": "",
|
||||
"videomute": ""
|
||||
"videomute": "Lo participant a arrestat la camèra"
|
||||
},
|
||||
"welcomepage": {
|
||||
"accessibilityLabel": {
|
||||
@@ -698,11 +702,12 @@
|
||||
},
|
||||
"calendar": "Calendari",
|
||||
"connectCalendarButton": "Connectar lo calendari",
|
||||
"connectCalendarText": "",
|
||||
"connectCalendarText": "Connectatz vòstre calendièr per veire vòstras reünions dins {{app}}. Ajustatz tanben las reünions de {{provider}} a vòstre calendièr e aviatz-las amb un sol clic.",
|
||||
"enterRoomTitle": "Començar una nòva conferéncia",
|
||||
"onlyAsciiAllowed": "",
|
||||
"go": "Crear",
|
||||
"join": "PARTICIPATZ",
|
||||
"info": "",
|
||||
"info": "Infor",
|
||||
"privacy": "Vida privada",
|
||||
"recentList": "Recents",
|
||||
"recentListDelete": "Suprimits",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,10 +21,11 @@
|
||||
"bluetooth": "Bluetooth",
|
||||
"headphones": "Fones de ouvido",
|
||||
"phone": "Celular",
|
||||
"speaker": "Apresentador"
|
||||
"speaker": "Alto-falantes",
|
||||
"none": ""
|
||||
},
|
||||
"audioOnly": {
|
||||
"audioOnly": "Somente áudio"
|
||||
"audioOnly": "Largura de banda baixa"
|
||||
},
|
||||
"calendarSync": {
|
||||
"addMeetingURL": "Adicionar um link da reunião",
|
||||
@@ -49,9 +50,9 @@
|
||||
"messagebox": "Digite uma mensagem",
|
||||
"nickname": {
|
||||
"popover": "Escolha um apelido",
|
||||
"title": "Digite um apelido para usar o chat"
|
||||
"title": "Digite um apelido para usar o bate-papo"
|
||||
},
|
||||
"title": "Chat"
|
||||
"title": "Bate-papo"
|
||||
},
|
||||
"connectingOverlay": {
|
||||
"joiningRoom": "Conectando você à reunião…"
|
||||
@@ -96,8 +97,7 @@
|
||||
"resolution": "Resolução:",
|
||||
"status": "Conexão:",
|
||||
"transport": "Transporte:",
|
||||
"transport_plural": "Transportes:",
|
||||
"turn": " (virar)"
|
||||
"transport_plural": "Transportes:"
|
||||
},
|
||||
"dateUtils": {
|
||||
"earlier": "Mais cedo",
|
||||
@@ -107,7 +107,7 @@
|
||||
"deepLinking": {
|
||||
"appNotInstalled": "Você precisa do aplicativo móvel {{app}} para participar da reunião no seu telefone.",
|
||||
"description": "Nada acontece? Estamos tentando iniciar sua reunião no aplicativo desktop {{app}}. Tente novamente ou inicie ele na aplicação web {{app}}.",
|
||||
"descriptionWithoutWeb": "",
|
||||
"descriptionWithoutWeb": "Nada aconteceu? Tentamos iniciar sua reunião no aplicativo de desktop {{app}}.",
|
||||
"downloadApp": "Baixe o Aplicativo",
|
||||
"launchWebButton": "Iniciar na web",
|
||||
"openApp": "Continue na aplicação",
|
||||
@@ -115,6 +115,7 @@
|
||||
"tryAgainButton": "Tente novamente no desktop"
|
||||
},
|
||||
"defaultLink": "ex.: {{url}}",
|
||||
"defaultNickname": "ex.: João Pedro",
|
||||
"deviceError": {
|
||||
"cameraError": "Falha ao acessar sua câmera",
|
||||
"cameraPermission": "Erro ao obter permissão para a câmera",
|
||||
@@ -132,7 +133,7 @@
|
||||
"liveStreaming": "Transmissão ao vivo"
|
||||
},
|
||||
"allow": "Permitir",
|
||||
"alreadySharedVideoMsg": "",
|
||||
"alreadySharedVideoMsg": "Outro participante já está compartilhando um vídeo. Esta conferência permite apenas um vídeo compartilhado por vez.",
|
||||
"alreadySharedVideoTitle": "Somente um vídeo compartilhado é permitido por vez",
|
||||
"applicationWindow": "Janela de aplicativo",
|
||||
"Back": "Voltar",
|
||||
@@ -158,51 +159,51 @@
|
||||
"contactSupport": "Contate o suporte",
|
||||
"copy": "Copiar",
|
||||
"dismiss": "Dispensar",
|
||||
"displayNameRequired": "",
|
||||
"displayNameRequired": "Oi! Qual o seu nome?",
|
||||
"done": "Feito",
|
||||
"enterDisplayName": "",
|
||||
"enterDisplayName": "Digite seu nome aqui",
|
||||
"error": "Erro",
|
||||
"externalInstallationMsg": "Você precisa instalar nossa extensão de compartilhamento de tela.",
|
||||
"externalInstallationTitle": "Extensão requerida",
|
||||
"goToStore": "Vá para a loja virtual",
|
||||
"gracefulShutdown": "O sistema está em manutenção. Por favor tente novamente mais tarde.",
|
||||
"IamHost": "Eu sou o anfitrião",
|
||||
"incorrectRoomLockPassword": "",
|
||||
"incorrectRoomLockPassword": "Senha incorreta",
|
||||
"incorrectPassword": "Usuário ou senha incorretos",
|
||||
"inlineInstallationMsg": "Você precisa instalar nossa extensão de compartilhamento de tela.",
|
||||
"inlineInstallExtension": "Instalar agora",
|
||||
"internalError": "Oops! Alguma coisa está errada. O seguinte erro ocorreu: {{error}}",
|
||||
"internalErrorTitle": "Erro interno",
|
||||
"kickMessage": "",
|
||||
"kickMessage": "Você pode contatar com {{participantDisplayName}} para obter mais detalhes.",
|
||||
"kickParticipantButton": "Remover",
|
||||
"kickParticipantDialog": "Tem certeza de que deseja remover este participante?",
|
||||
"kickParticipantTitle": "Deixar mudo este participante?",
|
||||
"kickTitle": "",
|
||||
"kickParticipantTitle": "Chutar este participante?",
|
||||
"kickTitle": "Ai! {{participantDisplayName}} expulsou você da reunião",
|
||||
"liveStreaming": "Transmissão ao Vivo",
|
||||
"liveStreamingDisabledForGuestTooltip": "Visitantes não podem iniciar transmissão ao vivo.",
|
||||
"liveStreamingDisabledTooltip": "Iniciar transmissão ao vivo desativada.",
|
||||
"lockMessage": "Falha ao travar a conferência.",
|
||||
"lockRoom": "",
|
||||
"lockRoom": "Adicionar reunião $t(lockRoomPasswordUppercase)",
|
||||
"lockTitle": "Bloqueio falhou",
|
||||
"logoutQuestion": "Deseja encerrar a sessão e finalizar a conferência?",
|
||||
"logoutTitle": "Encerrar sessão",
|
||||
"maxUsersLimitReached": "",
|
||||
"maxUsersLimitReachedTitle": "",
|
||||
"maxUsersLimitReached": "O limite para o número máximo de participantes foi atingido. A conferência está cheia. Entre em contato com o proprietário da reunião ou tente novamente mais tarde!",
|
||||
"maxUsersLimitReachedTitle": "Limite máximo de participantes atingido",
|
||||
"micConstraintFailedError": "Seu microfone não satisfaz algumas condições necessárias.",
|
||||
"micNotFoundError": "O microfone não foi encontrado.",
|
||||
"micNotSendingData": "",
|
||||
"micNotSendingDataTitle": "",
|
||||
"micNotSendingData": "Vá para as configurações do seu computador para ativar o som do microfone e ajustar seu nível",
|
||||
"micNotSendingDataTitle": "Seu microfone está mudo pelas configurações do sistema",
|
||||
"micPermissionDeniedError": "Não foi permitido acessar o seu microfone. Você ainda pode entrar na conferência, mas sem enviar áudio. Clique no botão do microfone para tentar reparar.",
|
||||
"micUnknownError": "Não pode usar o microfone por uma razão desconhecida.",
|
||||
"muteParticipantBody": "Você não está habilitado para tirar o mudo deles, mas eles podem tirar o mudo deles mesmos a qualquer tempo.",
|
||||
"muteParticipantButton": "Mudo",
|
||||
"muteParticipantDialog": "Tem certeza de que deseja silenciar este participante? Você não poderá desativar a opção silenciar dele, mas ele poderá fazer isso quando desejar.",
|
||||
"muteParticipantDialog": "Tem certeza de que deseja silenciar este participante? Você não poderá desfazer isso, mas o participante pode reabilitar o áudio a qualquer momento.",
|
||||
"muteParticipantTitle": "Deixar mudo este participante?",
|
||||
"Ok": "Ok",
|
||||
"passwordLabel": "",
|
||||
"passwordNotSupported": "Configuração de senha para a reunião não é suportada.",
|
||||
"passwordNotSupportedTitle": "",
|
||||
"passwordRequired": "",
|
||||
"passwordLabel": "$t(lockRoomPasswordUppercase)",
|
||||
"passwordNotSupported": "A configuração de uma reunião $t(lockRoomPassword) não é suportada.",
|
||||
"passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) não suportado",
|
||||
"passwordRequired": "$t(lockRoomPasswordUppercase) requerido",
|
||||
"popupError": "Seu navegador está bloqueando janelas popup deste site. Habilite os popups nas configurações de segurança no seu navegador e tente novamente.",
|
||||
"popupErrorTitle": "Popup bloqueado",
|
||||
"recording": "Gravando",
|
||||
@@ -217,7 +218,7 @@
|
||||
"remoteControlStopMessage": "A sessão de controle remoto terminou!",
|
||||
"remoteControlTitle": "Conexão de área de trabalho remota",
|
||||
"Remove": "Remover",
|
||||
"removePassword": "",
|
||||
"removePassword": "Remove $t(lockRoomPassword)",
|
||||
"removeSharedVideoMsg": "Deseja remover seu vídeo compartilhado?",
|
||||
"removeSharedVideoTitle": "Remover vídeo compartilhado",
|
||||
"reservationError": "Erro de sistema de reserva",
|
||||
@@ -250,7 +251,7 @@
|
||||
"tokenAuthFailed": "Desculpe, você não está autorizado a entrar nesta chamada.",
|
||||
"tokenAuthFailedTitle": "Falha de autenticação",
|
||||
"transcribing": "Transcrevendo",
|
||||
"unlockRoom": "",
|
||||
"unlockRoom": "Remove a reunião $t(lockRoomPassword)",
|
||||
"userPassword": "senha do usuário",
|
||||
"WaitForHostMsg": "A conferência <b>{{room}}</b> ainda não começou. Se você é o anfitrião, faça a autenticação. Do contrário, aguarde a chegada do anfitrião.",
|
||||
"WaitForHostMsgWOk": "A conferência <b>{{room}}</b> ainda não começou. Se você é o anfitrião, pressione Ok para autenticar. Do contrário, aguarde a chegada do anfitrião.",
|
||||
@@ -279,8 +280,8 @@
|
||||
},
|
||||
"info": {
|
||||
"accessibilityLabel": "Mostrar info",
|
||||
"addPassword": "",
|
||||
"cancelPassword": "",
|
||||
"addPassword": "Adicione $t(lockRoomPassword)",
|
||||
"cancelPassword": "Cancela $t(lockRoomPassword)",
|
||||
"conferenceURL": "Link:",
|
||||
"country": "País",
|
||||
"dialANumber": "Para entrar na reunião, disque um desses números e depois insira o PIN.",
|
||||
@@ -291,18 +292,18 @@
|
||||
"dialInTollFree": "Chamada gratuita",
|
||||
"genericError": "Oops, alguma coisa deu errado.",
|
||||
"inviteLiveStream": "Para ver a transmissão ao vivo da reunião, clique no link: {{url}}",
|
||||
"invitePhone": "",
|
||||
"invitePhoneAlternatives": "",
|
||||
"invitePhone": "Para participar por telefone, toque aqui: {{number}} ,, {{conferenceID}} # \\ n",
|
||||
"invitePhoneAlternatives": "Procurando um número de discagem diferente?\nVeja os números de discagem da reunião: {{url}} \n\n\nSe você também estiver discando através de um telefone da sala, participe sem conectar-se ao áudio: {{silentUrl}}",
|
||||
"inviteURLFirstPartGeneral": "Você foi convidado para uma reunião.",
|
||||
"inviteURLFirstPartPersonal": "",
|
||||
"inviteURLSecondPart": "",
|
||||
"inviteURLFirstPartPersonal": "{{name}} está convidando você para uma reunião.\n",
|
||||
"inviteURLSecondPart": "\nEntre na reunião:\n{{url}}\n",
|
||||
"liveStreamURL": "Transmissão ao vivo:",
|
||||
"moreNumbers": "Mais números",
|
||||
"noNumbers": "Sem números de discagem.",
|
||||
"noPassword": "Nenhum",
|
||||
"noRoom": "Nenhuma sala foi especificada para entrar.",
|
||||
"numbers": "Números de discagem",
|
||||
"password": "",
|
||||
"password": "$t(lockRoomPasswordUppercase):",
|
||||
"title": "Compartilhar",
|
||||
"tooltip": "Compartilhar link e discagem para esta reunião",
|
||||
"label": "Informações da reunião"
|
||||
@@ -335,7 +336,8 @@
|
||||
"toggleFilmstrip": "Mostrar ou ocultar miniaturas de vídeo",
|
||||
"toggleScreensharing": "Trocar entre câmera e compartilhamento de tela",
|
||||
"toggleShortcuts": "Mostrar ou ocultar atalhos de teclado",
|
||||
"videoMute": "Iniciar ou parar sua câmera"
|
||||
"videoMute": "Iniciar ou parar sua câmera",
|
||||
"videoQuality": "Gerenciar qualidade da chamada"
|
||||
},
|
||||
"liveStreaming": {
|
||||
"busy": "Estamos trabalhando para liberar os recursos de transmissão. Tente novamente em alguns minutos.",
|
||||
@@ -349,15 +351,17 @@
|
||||
"errorLiveStreamNotEnabled": "Transmissão ao vivo não está ativada em {{email}}. Ative a transmissão ao vivo ou registre numa conta com transmissão ao vivo ativada.",
|
||||
"expandedOff": "A transmissão ao vivo foi encerrada",
|
||||
"expandedOn": "A reunião está sendo transmitida pelo YouTube.",
|
||||
"expandedPending": "A transmissão ao vivo está sendo iniciada…",
|
||||
"expandedPending": "Iniciando a transmissão ao vivo...",
|
||||
"failedToStart": "Falha ao iniciar a transmissão ao vivo",
|
||||
"getStreamKeyManually": "",
|
||||
"getStreamKeyManually": "Não conseguimos buscar nenhuma transmissão ao vivo. Tente obter sua chave de transmissão ao vivo no YouTube.",
|
||||
"invalidStreamKey": "A senha para transmissão ao vivo pode estar incorreta.",
|
||||
"off": "Transmissão ao vivo encerrada",
|
||||
"offBy": "",
|
||||
"on": "Transmissão ao Vivo",
|
||||
"onBy": "",
|
||||
"pending": "Iniciando Transmissão ao Vivo...",
|
||||
"serviceName": "Serviço de Transmissão ao Vivo",
|
||||
"signedInAs": "Você está conectado atualmente como:",
|
||||
"signedInAs": "Você está conectado como:",
|
||||
"signIn": "Faça login no Google",
|
||||
"signInCTA": "Faça login ou insira sua chave de transmissão ao vivo do YouTube.",
|
||||
"signOut": "Sair",
|
||||
@@ -367,16 +371,16 @@
|
||||
},
|
||||
"localRecording": {
|
||||
"clientState": {
|
||||
"off": "Off",
|
||||
"on": "On",
|
||||
"off": "Desligado",
|
||||
"on": "Ligado",
|
||||
"unknown": "Desconhecido"
|
||||
},
|
||||
"dialogTitle": "Controles da Gravação Local",
|
||||
"duration": "Duração",
|
||||
"durationNA": "N/A",
|
||||
"durationNA": "N/D",
|
||||
"encoding": "Codificando",
|
||||
"label": "LOR",
|
||||
"labelToolTip": "Gravação local está envolvida",
|
||||
"labelToolTip": "Gravação local ativada",
|
||||
"localRecording": "Gravação local",
|
||||
"me": "Eu",
|
||||
"messages": {
|
||||
@@ -406,30 +410,30 @@
|
||||
"focusFail": "{{component}} não disponĩvel - tente em {{ms}} seg.",
|
||||
"grantedTo": "Direitos de moderador concedido para {{to}}!",
|
||||
"invitedOneMember": "{{displayName}} foi convidado",
|
||||
"invitedThreePlusMembers": "",
|
||||
"invitedTwoMembers": "",
|
||||
"kickParticipant": "",
|
||||
"invitedThreePlusMembers": "{{name}} e {{count}} outros foram convidados",
|
||||
"invitedTwoMembers": "{{first}} e {{second}} foram convidados",
|
||||
"kickParticipant": "{{kicked}} foi chutado por {{kicker}}",
|
||||
"me": "Eu",
|
||||
"moderator": "Direitos de moderador concedidos!",
|
||||
"muted": "Você iniciou uma conversa em mudo.",
|
||||
"mutedTitle": "Você está mudo!",
|
||||
"mutedRemotelyTitle": "",
|
||||
"mutedRemotelyDescription": "",
|
||||
"passwordRemovedRemotely": "",
|
||||
"passwordSetRemotely": "",
|
||||
"mutedRemotelyTitle": "Você foi silenciado por {{participantDisplayName}}!",
|
||||
"mutedRemotelyDescription": "Você sempre pode ativar o som quando estiver pronto para falar. Retire o som quando terminar para manter o ruído longe da reunião.",
|
||||
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) removido por outro participante",
|
||||
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) definido por outro participante",
|
||||
"raisedHand": "{{name}} gostaria de falar.",
|
||||
"somebody": "Alguém",
|
||||
"startSilentTitle": "",
|
||||
"startSilentDescription": "",
|
||||
"suboptimalExperienceDescription": "Eer ... temos medo de que sua experiência com o {{appName}} não seja tão boa aqui. Estamos procurando maneiras de melhorar isso, mas até lá tente usar um dos <a href='static/recommendedBrowsers.html' target='_blank'> navegadores totalmente compatíveis</a>.",
|
||||
"startSilentTitle": "Você entrou sem saída de áudio!",
|
||||
"startSilentDescription": "Volte à reunião para habilitar o áudio",
|
||||
"suboptimalBrowserWarning": "",
|
||||
"suboptimalExperienceTitle": "Alerta do navegador",
|
||||
"unmute": "",
|
||||
"unmute": "Ativar som",
|
||||
"newDeviceCameraTitle": "Nova câmera detectada",
|
||||
"newDeviceAudioTitle": "Novo dispositivo de áudio detectado",
|
||||
"newDeviceAction": "Usar"
|
||||
},
|
||||
"passwordSetRemotely": "Definido por outro participante",
|
||||
"passwordDigitsOnly": "",
|
||||
"passwordDigitsOnly": "Até {{number}} dígitos",
|
||||
"poweredby": "distribuído por",
|
||||
"presenceStatus": {
|
||||
"busy": "Ocupado",
|
||||
@@ -443,7 +447,7 @@
|
||||
"initializingCall": "Iniciando Chamada...",
|
||||
"invited": "Convidar",
|
||||
"rejected": "Rejeitado",
|
||||
"ringing": "Chamando..."
|
||||
"ringing": "Tocando..."
|
||||
},
|
||||
"profile": {
|
||||
"setDisplayNameLabel": "Definir seu nome de exibição",
|
||||
@@ -451,6 +455,7 @@
|
||||
"setEmailLabel": "Definir seu email de gravatar",
|
||||
"title": "Perfil"
|
||||
},
|
||||
"raisedHand": "Gostaria de falar",
|
||||
"recording": {
|
||||
"authDropboxText": "Enviar para o Dropbox.",
|
||||
"availableSpace": "Espaço disponível: {{spaceLeft}} MB (aproximadamente {{duration}} minutos de gravação)",
|
||||
@@ -466,12 +471,14 @@
|
||||
"live": "AOVIVO",
|
||||
"loggedIn": "Conectado como {{userName}}",
|
||||
"off": "Gravação parada",
|
||||
"offBy": "",
|
||||
"on": "Gravando",
|
||||
"onBy": "",
|
||||
"pending": "Preparando para gravar a reunião...",
|
||||
"rec": "REC",
|
||||
"serviceDescription": "Sua gravação será salva pelo serviço de gravação",
|
||||
"serviceName": "Serviço de gravação",
|
||||
"signIn": "entrar",
|
||||
"signIn": "Entrar",
|
||||
"signOut": "Sair",
|
||||
"unavailable": "Oops! O {{serviceName}} está indisponível. Estamos trabalhando para resolver o problema. Por favor, tente mais tarde.",
|
||||
"unavailableTitle": "Gravação indisponível"
|
||||
@@ -518,10 +525,10 @@
|
||||
"version": "Versão"
|
||||
},
|
||||
"share": {
|
||||
"dialInfoText": "",
|
||||
"dialInfoText": "\n\n=====\n\nDeseja apenas discar no seu telefone?\n\n{{defaultDialInNumber}}Clique neste link para ver os números de telefone para esta reunião\n{{dialInfoPageUrl}}",
|
||||
"mainText": "Clique no seguinte link para entrar na reunião:{{roomUrl}}\n"
|
||||
},
|
||||
"speaker": "Apresentador",
|
||||
"speaker": "Alto-falantes",
|
||||
"speakerStats": {
|
||||
"hours": "{{count}}h",
|
||||
"minutes": "{{count}}m",
|
||||
@@ -543,7 +550,7 @@
|
||||
"accessibilityLabel": {
|
||||
"audioOnly": "Alternar para apenas áudio",
|
||||
"audioRoute": "Selecionar o dispositivo de som",
|
||||
"callQuality": "Gerenciar qualidade da chamada",
|
||||
"callQuality": "Gerenciar qualidade do vídeo",
|
||||
"cc": "Alternar legendas",
|
||||
"chat": "Alternar para janela de chat",
|
||||
"document": "Alternar para documento compartilhado",
|
||||
@@ -567,19 +574,19 @@
|
||||
"shareRoom": "Convidar alguém",
|
||||
"shareYourScreen": "Alternar compartilhamento de tela",
|
||||
"shortcuts": "Alternar atalhos",
|
||||
"show": "",
|
||||
"show": "Mostrar no palco",
|
||||
"speakerStats": "Alternar estatísticas do apresentador",
|
||||
"tileView": "Alternar visualização em blocos",
|
||||
"toggleCamera": "Alternar câmera",
|
||||
"videomute": "Alternar mudo do vídeo",
|
||||
"videoblur": ""
|
||||
"videoblur": "Alternar desfoque de vídeo"
|
||||
},
|
||||
"addPeople": "Adicionar pessoas à sua chamada",
|
||||
"audioOnlyOff": "Desativar modo somente áudio",
|
||||
"audioOnlyOn": "Desativar modo somente áudio",
|
||||
"audioOnlyOff": "",
|
||||
"audioOnlyOn": "",
|
||||
"audioRoute": "Selecionar o dispositivo de som",
|
||||
"authenticate": "Autenticar",
|
||||
"callQuality": "Gerenciar qualidade da chamada",
|
||||
"callQuality": "Gerenciar qualidade do vídeo",
|
||||
"chat": "Abrir ou fechar o bate-papo",
|
||||
"closeChat": "Fechar chat",
|
||||
"documentClose": "Fechar documento compartilhado",
|
||||
@@ -615,19 +622,19 @@
|
||||
"tileViewToggle": "Alternar visualização em blocos",
|
||||
"toggleCamera": "Alternar câmera",
|
||||
"videomute": "Iniciar ou parar a câmera",
|
||||
"startvideoblur": "",
|
||||
"stopvideoblur": ""
|
||||
"startvideoblur": "Desfocar meu plano de fundo",
|
||||
"stopvideoblur": "Desativar desfoque de fundo"
|
||||
},
|
||||
"transcribing": {
|
||||
"ccButtonTooltip": "Iniciar/parar legendas",
|
||||
"error": "Transcrição falhou. Tente novamente.",
|
||||
"expandedLabel": "Transcrição ligada",
|
||||
"expandedLabel": "Transcrição ativada",
|
||||
"failedToStart": "Transcrição falhou ao iniciar",
|
||||
"labelToolTip": "A reunião esta sendo transcrita",
|
||||
"off": "Transcrição parada",
|
||||
"pending": "Preparando a transcrição da reunião...",
|
||||
"start": "Iniciar / Parar de mostrar as legendas",
|
||||
"stop": "Iniciar / Parar de mostrar as legendas",
|
||||
"start": "Exibir legendas",
|
||||
"stop": "Não exibir legendas",
|
||||
"tr": "TR"
|
||||
},
|
||||
"userMedia": {
|
||||
@@ -654,20 +661,23 @@
|
||||
},
|
||||
"videoStatus": {
|
||||
"audioOnly": "AUD",
|
||||
"audioOnlyExpanded": "Você está no modo somente áudio. Esse modo economiza internet mas não permite ver o vídeo dos outros.",
|
||||
"callQuality": "",
|
||||
"audioOnlyExpanded": "",
|
||||
"callQuality": "Qualidade de vídeo",
|
||||
"hd": "HD",
|
||||
"hdTooltip": "Ver vídeo em alta definição",
|
||||
"highDefinition": "Alta definição (HD)",
|
||||
"labelTooiltipNoVideo": "Sem vídeo",
|
||||
"labelTooltipAudioOnly": "Modo somente de áudio habilitado",
|
||||
"labelTooltipAudioOnly": "",
|
||||
"ld": "LD",
|
||||
"ldTooltip": "Ver vídeo em baixa definição",
|
||||
"lowDefinition": "Baixa definição (LD)",
|
||||
"onlyAudioAvailable": "Somente áudio disponível",
|
||||
"onlyAudioSupported": "Suportamos somente áudio neste navegador.",
|
||||
"p2pEnabled": "Ponto-a-ponto habilitada",
|
||||
"p2pVideoQualityDescription": "",
|
||||
"p2pVideoQualityDescription": "No modo ponto a ponto, a qualidade do vídeo recebido só pode ser alternada entre alta e apenas áudio. Outras configurações não serão respeitadas até que o ponto a ponto seja encerrado.",
|
||||
"recHighDefinitionOnly": "Preferência para alta definição",
|
||||
"sd": "SD",
|
||||
"sdTooltip": "Ver vídeo em definição padrão",
|
||||
"standardDefinition": "Definição padrão"
|
||||
},
|
||||
"videothumbnail": {
|
||||
@@ -678,8 +688,8 @@
|
||||
"mute": "Participante está mudo",
|
||||
"muted": "Mudo",
|
||||
"remoteControl": "Controle remoto",
|
||||
"show": "",
|
||||
"videomute": ""
|
||||
"show": "Mostrar no palco",
|
||||
"videomute": "O participante parou a câmera"
|
||||
},
|
||||
"welcomepage": {
|
||||
"accessibilityLabel": {
|
||||
@@ -695,6 +705,7 @@
|
||||
"connectCalendarButton": "Conectar seu calendário",
|
||||
"connectCalendarText": "Conecte seu calendário para ver todas as reuniões em {{app}}. Além disso, adicione reuniões de {{provider}} ao seu calendário e inicie-as com apenas um clique.",
|
||||
"enterRoomTitle": "Iniciar uma nova reunião",
|
||||
"onlyAsciiAllowed": "",
|
||||
"go": "IR",
|
||||
"join": "Entrar",
|
||||
"info": "Informações",
|
||||
@@ -702,7 +713,7 @@
|
||||
"recentList": "Recente",
|
||||
"recentListDelete": "Remover",
|
||||
"recentListEmpty": "Sua lista recente está vazia. As reuniões que você realizar serão exibidas aqui.",
|
||||
"reducedUIText": "",
|
||||
"reducedUIText": "Bem-vindo ao {{app}}!",
|
||||
"roomname": "Digite o nome da sala",
|
||||
"roomnameHint": "Digite o nome ou a URL da sala que você deseja entrar. Você pode digitar um nome, e apenas deixe para as pessoas que você quer se reunir digitem o mesmo nome.",
|
||||
"sendFeedback": "Enviar comentários",
|
||||
|
||||
@@ -46,13 +46,16 @@
|
||||
"today": "Today"
|
||||
},
|
||||
"chat": {
|
||||
"error": "Error: your message \"{{originalText}}\" was not sent. Reason: {{error}}",
|
||||
"error": "Error: your message was not sent. Reason: {{error}}",
|
||||
"messagebox": "Type a message",
|
||||
"messageTo": "Private message to {{recipient}}",
|
||||
"nickname": {
|
||||
"popover": "Choose a nickname",
|
||||
"title": "Enter a nickname to use chat"
|
||||
},
|
||||
"title": "Chat"
|
||||
"privateNotice": "Private message to {{recipient}}",
|
||||
"title": "Chat",
|
||||
"you": "you"
|
||||
},
|
||||
"connectingOverlay": {
|
||||
"joiningRoom": "Connecting you to your meeting..."
|
||||
@@ -235,6 +238,10 @@
|
||||
"screenSharingFirefoxPermissionDeniedError": "Something went wrong while we were trying to share your screen. Please make sure that you have given us permission to do so. ",
|
||||
"screenSharingFirefoxPermissionDeniedTitle": "Oops! We weren’t able to start screen sharing!",
|
||||
"screenSharingPermissionDeniedError": "Oops! Something went wrong with your screen sharing extension permissions. Please reload and try again.",
|
||||
"sendPrivateMessage": "You recently received a private message. Did you intend to reply to that privately, or you want to send your message to the group?",
|
||||
"sendPrivateMessageCancel": "Send to the group",
|
||||
"sendPrivateMessageOk": "Send privately",
|
||||
"sendPrivateMessageTitle": "Send privately?",
|
||||
"serviceUnavailable": "Service unavailable",
|
||||
"sessTerminated": "Call terminated",
|
||||
"Share": "Share",
|
||||
@@ -268,6 +275,9 @@
|
||||
"dialOut": {
|
||||
"statusMessage": "is now {{status}}"
|
||||
},
|
||||
"documentSharing" : {
|
||||
"title": "Shared Document"
|
||||
},
|
||||
"feedback": {
|
||||
"average": "Average",
|
||||
"bad": "Bad",
|
||||
@@ -362,7 +372,9 @@
|
||||
"getStreamKeyManually": "We weren’t able to fetch any live streams. Try getting your live stream key from YouTube.",
|
||||
"invalidStreamKey": "Live stream key may be incorrect.",
|
||||
"off": "Live Streaming stopped",
|
||||
"offBy": "{{name}} stopped the live streaming",
|
||||
"on": "Live Streaming",
|
||||
"onBy": "{{name}} started the live streaming",
|
||||
"pending": "Starting Live Stream...",
|
||||
"serviceName": "Live Streaming service",
|
||||
"signedInAs": "You are currently signed in as:",
|
||||
@@ -475,7 +487,9 @@
|
||||
"live": "LIVE",
|
||||
"loggedIn": "Logged in as {{userName}}",
|
||||
"off": "Recording stopped",
|
||||
"offBy": "{{name}} stopped the recording",
|
||||
"on": "Recording",
|
||||
"onBy": "{{name}} started the recording",
|
||||
"pending": "Preparing to record the meeting...",
|
||||
"rec": "REC",
|
||||
"serviceDescription": "Your recording will be saved by the recording service",
|
||||
@@ -512,16 +526,20 @@
|
||||
"title": "Settings"
|
||||
},
|
||||
"settingsView": {
|
||||
"advanced": "Advanced",
|
||||
"alertOk": "OK",
|
||||
"alertTitle": "Warning",
|
||||
"alertURLText": "The entered server URL is invalid",
|
||||
"buildInfoSection": "Build Information",
|
||||
"conferenceSection": "Conference",
|
||||
"disableCallIntegration": "Disable native call integration",
|
||||
"disableP2P": "Disable Peer-To-Peer mode",
|
||||
"displayName": "Display name",
|
||||
"email": "Email",
|
||||
"header": "Settings",
|
||||
"profileSection": "Profile",
|
||||
"serverURL": "Server URL",
|
||||
"showAdvanced": "Show advanced settings",
|
||||
"startWithAudioMuted": "Start with audio muted",
|
||||
"startWithVideoMuted": "Start with video muted",
|
||||
"version": "Version"
|
||||
@@ -556,9 +574,11 @@
|
||||
"cc": "Toggle subtitles",
|
||||
"chat": "Toggle chat window",
|
||||
"document": "Toggle shared document",
|
||||
"download": "Download our apps",
|
||||
"feedback": "Leave feedback",
|
||||
"fullScreen": "Toggle full screen",
|
||||
"hangup": "Leave the call",
|
||||
"help": "Help",
|
||||
"invite": "Invite people",
|
||||
"kick": "Kick participant",
|
||||
"localRecording": "Toggle local recording controls",
|
||||
@@ -567,6 +587,7 @@
|
||||
"moreActionsMenu": "More actions menu",
|
||||
"mute": "Toggle mute audio",
|
||||
"pip": "Toggle Picture-in-Picture mode",
|
||||
"privateMessage": "Send private message",
|
||||
"profile": "Edit your profile",
|
||||
"raiseHand": "Toggle raise hand",
|
||||
"recording": "Toggle recording",
|
||||
@@ -593,12 +614,14 @@
|
||||
"closeChat": "Close chat",
|
||||
"documentClose": "Close shared document",
|
||||
"documentOpen": "Open shared document",
|
||||
"download": "Download our apps",
|
||||
"enterFullScreen": "View full screen",
|
||||
"enterTileView": "Enter tile view",
|
||||
"exitFullScreen": "Exit full screen",
|
||||
"exitTileView": "Exit tile view",
|
||||
"feedback": "Leave feedback",
|
||||
"hangup": "Leave",
|
||||
"help": "Help",
|
||||
"invite": "Invite people",
|
||||
"login": "Login",
|
||||
"logout": "Logout",
|
||||
@@ -607,6 +630,7 @@
|
||||
"mute": "Mute / Unmute",
|
||||
"openChat": "Open chat",
|
||||
"pip": "Enter Picture-in-Picture mode",
|
||||
"privateMessage": "Send private message",
|
||||
"profile": "Edit your profile",
|
||||
"raiseHand": "Raise / Lower your hand",
|
||||
"raiseYourHand": "Raise your hand",
|
||||
@@ -707,7 +731,9 @@
|
||||
"connectCalendarButton": "Connect your calendar",
|
||||
"connectCalendarText": "Connect your calendar to view all your meetings in {{app}}. Plus, add {{provider}} meetings to your calendar and start them with one click.",
|
||||
"enterRoomTitle": "Start a new meeting",
|
||||
"roomNameAllowedChars": "Meeting name should not contain any of these characters: ?, &, :, ', \", %, #.",
|
||||
"go": "GO",
|
||||
"goSmall": "GO",
|
||||
"join": "JOIN",
|
||||
"info": "Info",
|
||||
"privacy": "Privacy",
|
||||
|
||||
@@ -7,13 +7,29 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
transformer: {
|
||||
getTransformOptions: async () => ({
|
||||
transform: {
|
||||
experimentalImportSupport: false,
|
||||
inlineRequires: false,
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
const { getDefaultConfig } = require('metro-config');
|
||||
|
||||
module.exports = (async () => {
|
||||
const {
|
||||
resolver: {
|
||||
sourceExts,
|
||||
assetExts
|
||||
}
|
||||
} = await getDefaultConfig();
|
||||
|
||||
return {
|
||||
transformer: {
|
||||
babelTransformerPath: require.resolve('react-native-svg-transformer'),
|
||||
getTransformOptions: async () => ({
|
||||
transform: {
|
||||
experimentalImportSupport: false,
|
||||
inlineRequires: false,
|
||||
},
|
||||
}),
|
||||
},
|
||||
resolver: {
|
||||
assetExts: assetExts.filter(ext => ext !== 'svg'),
|
||||
sourceExts: [...sourceExts, 'svg']
|
||||
}
|
||||
}
|
||||
})();
|
||||
@@ -15,7 +15,7 @@ import Filmstrip from './videolayout/Filmstrip';
|
||||
|
||||
import { getLocalParticipant } from '../../react/features/base/participants';
|
||||
import { toggleChat } from '../../react/features/chat';
|
||||
import { setEtherpadHasInitialzied } from '../../react/features/etherpad';
|
||||
import { setDocumentUrl } from '../../react/features/etherpad';
|
||||
import { setFilmstripVisible } from '../../react/features/filmstrip';
|
||||
import { setNotificationsEnabled } from '../../react/features/notifications';
|
||||
import {
|
||||
@@ -240,10 +240,12 @@ UI.initEtherpad = name => {
|
||||
return;
|
||||
}
|
||||
logger.log('Etherpad is enabled');
|
||||
etherpadManager
|
||||
= new EtherpadManager(config.etherpad_base, name, eventEmitter);
|
||||
|
||||
APP.store.dispatch(setEtherpadHasInitialzied());
|
||||
etherpadManager = new EtherpadManager(eventEmitter);
|
||||
|
||||
const url = new URL(name, config.etherpad_base);
|
||||
|
||||
APP.store.dispatch(setDocumentUrl(url.toString()));
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,22 +1,12 @@
|
||||
/* global $, APP, interfaceConfig */
|
||||
|
||||
import { setDocumentEditingState } from '../../../react/features/etherpad';
|
||||
import { getSharedDocumentUrl, setDocumentEditingState } from '../../../react/features/etherpad';
|
||||
import { getToolboxHeight } from '../../../react/features/toolbox';
|
||||
|
||||
import VideoLayout from '../videolayout/VideoLayout';
|
||||
import LargeContainer from '../videolayout/LargeContainer';
|
||||
import Filmstrip from '../videolayout/Filmstrip';
|
||||
|
||||
/**
|
||||
* Etherpad options.
|
||||
*/
|
||||
const options = $.param({
|
||||
showControls: true,
|
||||
showChat: false,
|
||||
showLineNumbers: true,
|
||||
useMonospaceFont: false
|
||||
});
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@@ -70,13 +60,13 @@ class Etherpad extends LargeContainer {
|
||||
/**
|
||||
* Creates new Etherpad object
|
||||
*/
|
||||
constructor(domain, name) {
|
||||
constructor(url) {
|
||||
super();
|
||||
|
||||
const iframe = document.createElement('iframe');
|
||||
|
||||
iframe.id = 'etherpadIFrame';
|
||||
iframe.src = `${domain + name}?${options}`;
|
||||
iframe.src = url;
|
||||
iframe.frameBorder = 0;
|
||||
iframe.scrolling = 'no';
|
||||
iframe.width = DEFAULT_WIDTH;
|
||||
@@ -199,13 +189,7 @@ export default class EtherpadManager {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
constructor(domain, name, eventEmitter) {
|
||||
if (!domain || !name) {
|
||||
throw new Error('missing domain or name');
|
||||
}
|
||||
|
||||
this.domain = domain;
|
||||
this.name = name;
|
||||
constructor(eventEmitter) {
|
||||
this.eventEmitter = eventEmitter;
|
||||
this.etherpad = null;
|
||||
}
|
||||
@@ -228,7 +212,7 @@ export default class EtherpadManager {
|
||||
* Create new Etherpad frame.
|
||||
*/
|
||||
openEtherpad() {
|
||||
this.etherpad = new Etherpad(this.domain, this.name);
|
||||
this.etherpad = new Etherpad(getSharedDocumentUrl(APP.store.getState));
|
||||
VideoLayout.addLargeVideoContainer(
|
||||
ETHERPAD_CONTAINER_TYPE,
|
||||
this.etherpad
|
||||
|
||||
@@ -273,7 +273,7 @@ LocalVideo.prototype._updateVideoElement = function() {
|
||||
// case video does not autoplay.
|
||||
const video = this.container.querySelector('video');
|
||||
|
||||
video && video.play();
|
||||
video && !config.testing?.noAutoPlayVideo && video.play();
|
||||
};
|
||||
|
||||
export default LocalVideo;
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Provider } from 'react-redux';
|
||||
import { I18nextProvider } from 'react-i18next';
|
||||
import { AtlasKitThemeProvider } from '@atlaskit/theme';
|
||||
|
||||
import { createThumbnailOffsetParentIsNullEvent, sendAnalytics } from '../../../react/features/analytics';
|
||||
import { i18next } from '../../../react/features/base/i18n';
|
||||
import {
|
||||
JitsiParticipantConnectionStatus
|
||||
@@ -486,6 +487,8 @@ RemoteVideo.prototype.hasVideoStarted = function() {
|
||||
|
||||
RemoteVideo.prototype.addRemoteStreamElement = function(stream) {
|
||||
if (!this.container) {
|
||||
logger.debug('Not attaching remote stream due to no container');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -498,6 +501,8 @@ RemoteVideo.prototype.addRemoteStreamElement = function(stream) {
|
||||
}
|
||||
|
||||
if (!stream.getOriginalStream()) {
|
||||
logger.debug('Remote video stream has no original stream');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -508,11 +513,31 @@ RemoteVideo.prototype.addRemoteStreamElement = function(stream) {
|
||||
|
||||
$(streamElement).hide();
|
||||
|
||||
// If the container is currently visible
|
||||
// we attach the stream to the element.
|
||||
if (!isVideo || (this.container.offsetParent !== null && isVideo)) {
|
||||
this.waitForPlayback(streamElement, stream);
|
||||
stream.attach(streamElement);
|
||||
this.waitForPlayback(streamElement, stream);
|
||||
stream.attach(streamElement);
|
||||
|
||||
// TODO: Remove once we verify that this.container.offsetParent === null was the reason for not attached video
|
||||
// streams to the thumbnail.
|
||||
if (isVideo && this.container.offsetParent === null) {
|
||||
sendAnalytics(createThumbnailOffsetParentIsNullEvent(this.id));
|
||||
const parentNodesDisplayProps = [
|
||||
'#filmstripRemoteVideosContainer',
|
||||
'#filmstripRemoteVideos',
|
||||
'#remoteVideos',
|
||||
'.filmstrip',
|
||||
'#videospace',
|
||||
'#videoconference_page',
|
||||
'#react'
|
||||
].map(selector => `${selector} - ${$(selector).css('display')}`);
|
||||
const videoConferencePageParent = $('#videoconference_page').parent();
|
||||
const reactDiv = document.getElementById('react');
|
||||
|
||||
parentNodesDisplayProps.push(
|
||||
`${videoConferencePageParent.attr('class')} - ${videoConferencePageParent.css('display')}`);
|
||||
parentNodesDisplayProps.push(`this.container - ${this.$container.css('display')}`);
|
||||
logger.debug(`this.container.offsetParent is null [user: ${this.id}, ${
|
||||
parentNodesDisplayProps.join(', ')}, #react.offsetParent - ${
|
||||
reactDiv && reactDiv.offsetParent !== null ? 'not null' : 'null'}]`);
|
||||
}
|
||||
|
||||
if (!isVideo) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import { AudioLevelIndicator }
|
||||
from '../../../react/features/audio-level-indicator';
|
||||
import { Avatar as AvatarDisplay } from '../../../react/features/base/avatar';
|
||||
import {
|
||||
getParticipantCount,
|
||||
getPinnedParticipant,
|
||||
pinParticipant
|
||||
} from '../../../react/features/base/participants';
|
||||
@@ -198,7 +199,7 @@ SmallVideo.createStreamElement = function(stream) {
|
||||
element.muted = true;
|
||||
}
|
||||
|
||||
element.autoplay = true;
|
||||
element.autoplay = !config.testing?.noAutoPlayVideo;
|
||||
element.id = SmallVideo.getStreamElementID(stream);
|
||||
|
||||
return element;
|
||||
@@ -510,7 +511,7 @@ SmallVideo.prototype.isCurrentlyOnLargeVideo = function() {
|
||||
* or <tt>false</tt> otherwise.
|
||||
*/
|
||||
SmallVideo.prototype.isVideoPlayable = function() {
|
||||
return this.videoStream && !this.isVideoMuted && !this.videoStream.isMuted();
|
||||
return this.videoStream && !this.isVideoMuted && !APP.conference.isAudioOnly();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -519,40 +520,33 @@ SmallVideo.prototype.isVideoPlayable = function() {
|
||||
* @return {number} one of <tt>DISPLAY_VIDEO</tt>,<tt>DISPLAY_AVATAR</tt>
|
||||
* or <tt>DISPLAY_BLACKNESS_WITH_NAME</tt>.
|
||||
*/
|
||||
SmallVideo.prototype.selectDisplayMode = function() {
|
||||
const isAudioOnly = APP.conference.isAudioOnly();
|
||||
const tileViewEnabled = shouldDisplayTileView(APP.store.getState());
|
||||
const isVideoPlayable = this.isVideoPlayable();
|
||||
const hasVideo = Boolean(this.selectVideoElement().length);
|
||||
SmallVideo.prototype.selectDisplayMode = function(input) {
|
||||
|
||||
// Display name is always and only displayed when user is on the stage
|
||||
if (this.isCurrentlyOnLargeVideo() && !tileViewEnabled) {
|
||||
return isVideoPlayable && !isAudioOnly ? DISPLAY_BLACKNESS_WITH_NAME : DISPLAY_AVATAR_WITH_NAME;
|
||||
} else if (isVideoPlayable && hasVideo && !isAudioOnly) {
|
||||
if (input.isCurrentlyOnLargeVideo && !input.tileViewEnabled) {
|
||||
return input.isVideoPlayable && !input.isAudioOnly ? DISPLAY_BLACKNESS_WITH_NAME : DISPLAY_AVATAR_WITH_NAME;
|
||||
} else if (input.isVideoPlayable && input.hasVideo && !input.isAudioOnly) {
|
||||
// check hovering and change state to video with name
|
||||
return this._isHovered() ? DISPLAY_VIDEO_WITH_NAME : DISPLAY_VIDEO;
|
||||
return input.isHovered ? DISPLAY_VIDEO_WITH_NAME : DISPLAY_VIDEO;
|
||||
}
|
||||
|
||||
// check hovering and change state to avatar with name
|
||||
return this._isHovered() ? DISPLAY_AVATAR_WITH_NAME : DISPLAY_AVATAR;
|
||||
return input.isHovered ? DISPLAY_AVATAR_WITH_NAME : DISPLAY_AVATAR;
|
||||
};
|
||||
|
||||
/**
|
||||
* Prints information about the current display mode.
|
||||
* Computes information that determine the display mode.
|
||||
*
|
||||
* @param {string} mode - The current mode.
|
||||
* @returns {void}
|
||||
* @returns {Object}
|
||||
*/
|
||||
SmallVideo.prototype._printDisplayModeInfo = function(mode) {
|
||||
const isAudioOnly = APP.conference.isAudioOnly();
|
||||
const tileViewEnabled = shouldDisplayTileView(APP.store.getState());
|
||||
const isVideoPlayable = this.isVideoPlayable();
|
||||
const hasVideo = Boolean(this.selectVideoElement().length);
|
||||
const displayModeInfo = {
|
||||
isAudioOnly,
|
||||
tileViewEnabled,
|
||||
isVideoPlayable,
|
||||
hasVideo,
|
||||
SmallVideo.prototype.computeDisplayModeInput = function() {
|
||||
return {
|
||||
isCurrentlyOnLargeVideo: this.isCurrentlyOnLargeVideo(),
|
||||
isHovered: this._isHovered(),
|
||||
isAudioOnly: APP.conference.isAudioOnly(),
|
||||
tileViewEnabled: shouldDisplayTileView(APP.store.getState()),
|
||||
isVideoPlayable: this.isVideoPlayable(),
|
||||
hasVideo: Boolean(this.selectVideoElement().length),
|
||||
connectionStatus: APP.conference.getParticipantConnectionStatus(this.id),
|
||||
mutedWhileDisconnected: this.mutedWhileDisconnected,
|
||||
wasVideoPlayed: this.wasVideoPlayed,
|
||||
@@ -560,8 +554,6 @@ SmallVideo.prototype._printDisplayModeInfo = function(mode) {
|
||||
isVideoMuted: this.isVideoMuted,
|
||||
videoStreamMuted: this.videoStream ? this.videoStream.isMuted() : 'no stream'
|
||||
};
|
||||
|
||||
logger.debug(`Displaying ${mode} for ${this.id}, reason: [${JSON.stringify(displayModeInfo)}]`);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -595,8 +587,10 @@ SmallVideo.prototype.updateView = function() {
|
||||
const oldDisplayMode = this.displayMode;
|
||||
let displayModeString = '';
|
||||
|
||||
const displayModeInput = this.computeDisplayModeInput();
|
||||
|
||||
// Determine whether video, avatar or blackness should be displayed
|
||||
this.displayMode = this.selectDisplayMode();
|
||||
this.displayMode = this.selectDisplayMode(displayModeInput);
|
||||
|
||||
switch (this.displayMode) {
|
||||
case DISPLAY_AVATAR_WITH_NAME:
|
||||
@@ -623,7 +617,7 @@ SmallVideo.prototype.updateView = function() {
|
||||
}
|
||||
|
||||
if (this.displayMode !== oldDisplayMode) {
|
||||
this._printDisplayModeInfo(displayModeString);
|
||||
logger.debug(`Displaying ${displayModeString} for ${this.id}, data: [${JSON.stringify(displayModeInput)}]`);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -836,7 +830,9 @@ SmallVideo.prototype.updateIndicators = function() {
|
||||
const iconSize = UIUtil.getIndicatorFontSize();
|
||||
const showConnectionIndicator = this.videoIsHovered
|
||||
|| !interfaceConfig.CONNECTION_INDICATOR_AUTO_HIDE_ENABLED;
|
||||
const currentLayout = getCurrentLayout(APP.store.getState());
|
||||
const state = APP.store.getState();
|
||||
const currentLayout = getCurrentLayout(state);
|
||||
const participantCount = getParticipantCount(state);
|
||||
let statsPopoverPosition, tooltipPosition;
|
||||
|
||||
if (currentLayout === LAYOUTS.TILE_VIEW) {
|
||||
@@ -871,7 +867,7 @@ SmallVideo.prototype.updateIndicators = function() {
|
||||
iconSize = { iconSize }
|
||||
participantId = { this.id }
|
||||
tooltipPosition = { tooltipPosition } />
|
||||
{ this._showDominantSpeaker
|
||||
{ this._showDominantSpeaker && participantCount > 2
|
||||
? <DominantSpeakerIndicator
|
||||
iconSize = { iconSize }
|
||||
tooltipPosition = { tooltipPosition } />
|
||||
|
||||
@@ -200,7 +200,11 @@ const VideoLayout = {
|
||||
const id = stream.getParticipantId();
|
||||
const remoteVideo = remoteVideos[id];
|
||||
|
||||
logger.debug(`Received a new ${stream.getType()} stream for ${id}`);
|
||||
|
||||
if (!remoteVideo) {
|
||||
logger.debug('No remote video element to add stream');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
6338
package-lock.json
generated
6338
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
34
package.json
34
package.json
@@ -35,9 +35,11 @@
|
||||
"@atlaskit/tooltip": "12.1.13",
|
||||
"@microsoft/microsoft-graph-client": "1.1.0",
|
||||
"@react-native-community/async-storage": "1.3.4",
|
||||
"@react-native-community/google-signin": "3.0.1",
|
||||
"@react-native-community/netinfo": "4.1.5",
|
||||
"@tensorflow-models/body-pix": "^1.0.1",
|
||||
"@tensorflow/tfjs": "^1.1.2",
|
||||
"@svgr/webpack": "4.3.2",
|
||||
"@tensorflow-models/body-pix": "1.1.2",
|
||||
"@tensorflow/tfjs": "1.2.9",
|
||||
"@webcomponents/url": "0.7.1",
|
||||
"amplitude-js": "4.5.2",
|
||||
"bc-css-flags": "3.0.0",
|
||||
@@ -47,7 +49,7 @@
|
||||
"i18next-browser-languagedetector": "3.0.1",
|
||||
"i18next-xhr-backend": "3.0.0",
|
||||
"jQuery-Impromptu": "github:trentrichardson/jQuery-Impromptu#v6.0.0",
|
||||
"jitsi-meet-logger": "github:jitsi/jitsi-meet-logger#a885cc98688ef2c3972284bda901596a26ffee52",
|
||||
"jitsi-meet-logger": "github:jitsi/jitsi-meet-logger#5ec92357570dc8f0b7ffc1528820721c84c6af8b",
|
||||
"jquery": "3.4.0",
|
||||
"jquery-contextmenu": "2.4.5",
|
||||
"jquery-i18next": "1.2.1",
|
||||
@@ -55,36 +57,37 @@
|
||||
"js-utils": "github:jitsi/js-utils#192b1c996e8c05530eb1f19e82a31069c3021e31",
|
||||
"jsrsasign": "8.0.12",
|
||||
"jwt-decode": "2.2.0",
|
||||
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#486c61e2a91eeb3d9b6f179ea0c82044e321dccf",
|
||||
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#1de69abe22aa632c9a4255ee9f6ae48dab9be756",
|
||||
"libflacjs": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d",
|
||||
"lodash": "4.17.13",
|
||||
"moment": "2.19.4",
|
||||
"moment-duration-format": "2.2.2",
|
||||
"postis": "2.2.0",
|
||||
"react": "16.8.6",
|
||||
"react-dom": "16.8.6",
|
||||
"react": "16.9",
|
||||
"react-dom": "16.9",
|
||||
"react-emoji-render": "1.0.0",
|
||||
"react-i18next": "10.11.4",
|
||||
"react-linkify": "1.0.0-alpha",
|
||||
"react-native": "0.60.5",
|
||||
"react-native": "0.61.3",
|
||||
"react-native-background-timer": "2.1.1",
|
||||
"react-native-calendar-events": "github:jitsi/react-native-calendar-events#902e6e92d6bae450a6052f76ba4d02f977ffd8f2",
|
||||
"react-native-callstats": "3.61.0",
|
||||
"react-native-google-signin": "2.0.0",
|
||||
"react-native-immersive": "2.0.0",
|
||||
"react-native-keep-awake": "4.0.0",
|
||||
"react-native-linear-gradient": "2.5.6",
|
||||
"react-native-sound": "0.11.0",
|
||||
"react-native-svg": "9.7.1",
|
||||
"react-native-svg-transformer": "0.13.0",
|
||||
"react-native-swipeout": "2.3.6",
|
||||
"react-native-vector-icons": "6.0.2",
|
||||
"react-native-watch-connectivity": "0.2.0",
|
||||
"react-native-webrtc": "github:react-native-webrtc/react-native-webrtc#b1275ccf1e0e083d2a5c238e7d21c37657766463",
|
||||
"react-native-webview": "5.8.1",
|
||||
"react-native-webrtc": "github:react-native-webrtc/react-native-webrtc#a12a6cdfdefe53d03b388394e4cf10966bd99fca",
|
||||
"react-native-webview": "7.4.1",
|
||||
"react-redux": "7.1.0",
|
||||
"react-textarea-autosize": "7.1.0",
|
||||
"react-transition-group": "2.4.0",
|
||||
"redux": "4.0.4",
|
||||
"redux-thunk": "2.2.0",
|
||||
"rnnoise-wasm": "github:jitsi/rnnoise-wasm.git#db96d11f175a22ef56c7db1ba9550835b716e615",
|
||||
"styled-components": "3.4.9",
|
||||
"util": "0.12.1",
|
||||
"uuid": "3.1.0",
|
||||
@@ -115,18 +118,19 @@
|
||||
"eslint-plugin-react": "7.11.1",
|
||||
"eslint-plugin-react-native": "3.3.0",
|
||||
"expose-loader": "0.7.5",
|
||||
"flow-bin": "0.98.0",
|
||||
"flow-bin": "0.104.0",
|
||||
"imports-loader": "0.7.1",
|
||||
"jetifier": "1.6.4",
|
||||
"metro-react-native-babel-preset": "0.56.0",
|
||||
"node-sass": "4.10.0",
|
||||
"node-sass": "4.12.0",
|
||||
"precommit-hook": "3.0.0",
|
||||
"string-replace-loader": "2.1.1",
|
||||
"style-loader": "0.19.0",
|
||||
"webpack": "4.26.1",
|
||||
"unorm": "1.6.0",
|
||||
"webpack": "4.27.1",
|
||||
"webpack-bundle-analyzer": "3.4.1",
|
||||
"webpack-cli": "3.1.2",
|
||||
"webpack-dev-server": "3.1.14"
|
||||
"webpack-dev-server": "3.8.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user