mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2025-12-31 03:42:29 +00:00
Compare commits
252 Commits
4352
...
react-thum
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d1ed86e49 | ||
|
|
88c02fb658 | ||
|
|
0f64c66f91 | ||
|
|
9f65ae52f1 | ||
|
|
a242e86b23 | ||
|
|
4211db0893 | ||
|
|
9a35026d6a | ||
|
|
9742e90bb5 | ||
|
|
2a01d3550c | ||
|
|
efce5a831b | ||
|
|
e0117e03e8 | ||
|
|
1648e4b407 | ||
|
|
b02136d013 | ||
|
|
734631a7a4 | ||
|
|
9fbb35b6e1 | ||
|
|
f45af351d8 | ||
|
|
1f4cd22875 | ||
|
|
53cc724b3b | ||
|
|
b9ccc3ad8c | ||
|
|
68a0bdce2c | ||
|
|
b71d92a139 | ||
|
|
30fc04ba61 | ||
|
|
d2046c2c8f | ||
|
|
35b5f6df06 | ||
|
|
ca2343c31a | ||
|
|
3657c19e60 | ||
|
|
007183c151 | ||
|
|
9c10ac3028 | ||
|
|
4b429112f2 | ||
|
|
d067c4e731 | ||
|
|
07d8611988 | ||
|
|
b0d55f9450 | ||
|
|
5f2ee6d951 | ||
|
|
ddea7d0294 | ||
|
|
348c6416e5 | ||
|
|
ad265d5815 | ||
|
|
d5b2da02c1 | ||
|
|
fbfaed07b2 | ||
|
|
da33d8a033 | ||
|
|
830817d7b4 | ||
|
|
8c67f1fdf3 | ||
|
|
b57da04553 | ||
|
|
b428c3bca8 | ||
|
|
96c34b7774 | ||
|
|
f2bbc874b3 | ||
|
|
b18398f016 | ||
|
|
a6e58c3101 | ||
|
|
c5f6df5210 | ||
|
|
e67c08d837 | ||
|
|
d854b2cd3d | ||
|
|
ab5c8d49c3 | ||
|
|
820d9b2ba8 | ||
|
|
e4c1046d7c | ||
|
|
223187c640 | ||
|
|
35e8821679 | ||
|
|
3125345793 | ||
|
|
5e6c4d67ed | ||
|
|
a3fb996ff0 | ||
|
|
65a9de346f | ||
|
|
036d810d46 | ||
|
|
b5f9b575ca | ||
|
|
a7fa9d8a97 | ||
|
|
4762d5a153 | ||
|
|
e8c2c89343 | ||
|
|
d77a7cac3a | ||
|
|
6030c32272 | ||
|
|
8e19597e38 | ||
|
|
bf6a1540df | ||
|
|
9434d3c349 | ||
|
|
b891a7526d | ||
|
|
5bf20517e7 | ||
|
|
0d7a730497 | ||
|
|
59caa0cf42 | ||
|
|
bdda8c56c7 | ||
|
|
c239ba71e6 | ||
|
|
1005f8f498 | ||
|
|
f6e2bd1249 | ||
|
|
cd68c72338 | ||
|
|
1740aaf973 | ||
|
|
a270e4300a | ||
|
|
5e2ee3bdcd | ||
|
|
bdd2845917 | ||
|
|
f9888e5dbb | ||
|
|
44d7828e9c | ||
|
|
82b14ba7f1 | ||
|
|
63fe1de789 | ||
|
|
39af6f5943 | ||
|
|
f01869c21c | ||
|
|
6d2f8ae37d | ||
|
|
35bea1a1d0 | ||
|
|
afa4306ae8 | ||
|
|
1d9daa8da7 | ||
|
|
478f1a731e | ||
|
|
9f9e192c3c | ||
|
|
943996e5b6 | ||
|
|
bfde13cb15 | ||
|
|
5939820271 | ||
|
|
b5310573fc | ||
|
|
aa488cb75c | ||
|
|
de8e62ac51 | ||
|
|
f6d375f565 | ||
|
|
c54fed78c8 | ||
|
|
3d7ea52416 | ||
|
|
0c4d649459 | ||
|
|
af416ad487 | ||
|
|
1cd6f2b4da | ||
|
|
1fb37a0216 | ||
|
|
c261682a29 | ||
|
|
49548ba564 | ||
|
|
dc6d3daef7 | ||
|
|
014f3b615f | ||
|
|
25271d7eec | ||
|
|
7ef4de9c1c | ||
|
|
e6e088d197 | ||
|
|
0e034a686f | ||
|
|
d9f85c70f1 | ||
|
|
de8079cc98 | ||
|
|
2a9805f9b1 | ||
|
|
00ec0f03a6 | ||
|
|
91f636a813 | ||
|
|
fa4df19733 | ||
|
|
1d17cc91e0 | ||
|
|
93f4098dc0 | ||
|
|
11ae187ece | ||
|
|
0f9e01a7cf | ||
|
|
ddbd3f292a | ||
|
|
b153bf2fb8 | ||
|
|
919be21912 | ||
|
|
1a339100ab | ||
|
|
ce4ef96941 | ||
|
|
993ded9936 | ||
|
|
a8b9ae2b12 | ||
|
|
812af33a4d | ||
|
|
7f17c2eceb | ||
|
|
09124ad7e9 | ||
|
|
7a9a6855b7 | ||
|
|
8dcf04897a | ||
|
|
69b7301b9d | ||
|
|
794713b930 | ||
|
|
89cd6e8e3e | ||
|
|
7a7937c072 | ||
|
|
4765ab9d63 | ||
|
|
1d5decc14f | ||
|
|
119b79fd84 | ||
|
|
188771751d | ||
|
|
d2ec0ea6f3 | ||
|
|
ed6e75b241 | ||
|
|
dedd3f4ef0 | ||
|
|
bbb4fbd5f8 | ||
|
|
92235ae535 | ||
|
|
ebb1b8d76b | ||
|
|
42d559de93 | ||
|
|
2838aefccc | ||
|
|
ca306f47b6 | ||
|
|
56da400f19 | ||
|
|
ab21e3cd5e | ||
|
|
2c026754ef | ||
|
|
8dbe3e37b9 | ||
|
|
7f67f78db6 | ||
|
|
312949eef6 | ||
|
|
41ea94c0c2 | ||
|
|
e70adef2ef | ||
|
|
57bbe3f75a | ||
|
|
e2731ce73e | ||
|
|
d5dae945a8 | ||
|
|
4d1dba937f | ||
|
|
b6792db65f | ||
|
|
9815b633fc | ||
|
|
b4bf82429c | ||
|
|
53d485b397 | ||
|
|
0354dbe889 | ||
|
|
7cafa205ee | ||
|
|
2b4f33bef8 | ||
|
|
31dee0bb68 | ||
|
|
fc75d45c6c | ||
|
|
25839b18d2 | ||
|
|
43f36c8cfd | ||
|
|
b02d96231c | ||
|
|
651d713206 | ||
|
|
9e5f469e0c | ||
|
|
493ce8249e | ||
|
|
fdffb688c1 | ||
|
|
4807badac8 | ||
|
|
5e3bd746e9 | ||
|
|
8fa41bebb7 | ||
|
|
cb7c280da6 | ||
|
|
0e50f1887e | ||
|
|
476ca54711 | ||
|
|
70aa19e6d9 | ||
|
|
7778a17b90 | ||
|
|
7ff41217ac | ||
|
|
e8c44c10dd | ||
|
|
b087b22d4f | ||
|
|
e988bf6565 | ||
|
|
d169bd5007 | ||
|
|
ac17db9df5 | ||
|
|
322618357c | ||
|
|
79c1358f4b | ||
|
|
5e85b5f63a | ||
|
|
74f7c4141f | ||
|
|
4866ddc2ad | ||
|
|
71d0577a49 | ||
|
|
b7529863d5 | ||
|
|
4ded94d130 | ||
|
|
eb8b730227 | ||
|
|
4bd57692b7 | ||
|
|
5d012c24a7 | ||
|
|
4f52a29120 | ||
|
|
8a4fb72eae | ||
|
|
6453ceb048 | ||
|
|
e51bbe6125 | ||
|
|
d725c0ab8a | ||
|
|
2c2edace2a | ||
|
|
d3d5847605 | ||
|
|
89ad76142d | ||
|
|
1e76b8b6ea | ||
|
|
55175e2e95 | ||
|
|
453c07cb17 | ||
|
|
af71d80150 | ||
|
|
b765adca75 | ||
|
|
92e6cf7618 | ||
|
|
10c2652a4f | ||
|
|
c3329ec931 | ||
|
|
9cf7199c0e | ||
|
|
d82bb0a89b | ||
|
|
295dd8a45d | ||
|
|
25ae83bcf4 | ||
|
|
82b1408454 | ||
|
|
36565f0c50 | ||
|
|
0c48e205d7 | ||
|
|
5e35b69fc9 | ||
|
|
3fd85720bc | ||
|
|
e439d065b7 | ||
|
|
5dcecdbb54 | ||
|
|
d716665f27 | ||
|
|
d05fa32413 | ||
|
|
3da7798e9f | ||
|
|
6fc9606c0d | ||
|
|
c4155575f9 | ||
|
|
b670b29d7f | ||
|
|
9b7e8c98ad | ||
|
|
ad44558153 | ||
|
|
d70f9d6fd6 | ||
|
|
7858f12df2 | ||
|
|
828e578af4 | ||
|
|
4289b23135 | ||
|
|
099820b6ac | ||
|
|
25ded0bdeb | ||
|
|
51fd10278b | ||
|
|
24c75b7332 | ||
|
|
2327a6d0b4 | ||
|
|
b94c357cc2 |
4
.github/ISSUE_TEMPLATE/2-feature-request.md
vendored
4
.github/ISSUE_TEMPLATE/2-feature-request.md
vendored
@@ -1,7 +1,9 @@
|
||||
---
|
||||
name: "Feature request"
|
||||
about: Suggest an idea for this project
|
||||
|
||||
title: ''
|
||||
labels: 'feature-request'
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
<!--
|
||||
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -84,3 +84,10 @@ android/app/google-services.json
|
||||
ios/app/dropbox.key
|
||||
ios/app/GoogleService-Info.plist
|
||||
|
||||
.vscode
|
||||
|
||||
# TWA
|
||||
twa/*.apk
|
||||
twa/*.aab
|
||||
twa/assetlinks.json
|
||||
|
||||
|
||||
@@ -2,10 +2,3 @@
|
||||
* Notifies interested parties that hangup procedure will start.
|
||||
*/
|
||||
export const BEFORE_HANGUP = 'conference.before_hangup';
|
||||
|
||||
/**
|
||||
* Notifies interested parties that desktop sharing enable/disable state is
|
||||
* changed.
|
||||
*/
|
||||
export const DESKTOP_SHARING_ENABLED_CHANGED
|
||||
= 'conference.desktop_sharing_enabled_changed';
|
||||
|
||||
15
Makefile
15
Makefile
@@ -3,8 +3,9 @@ CLEANCSS = ./node_modules/.bin/cleancss
|
||||
DEPLOY_DIR = libs
|
||||
LIBJITSIMEET_DIR = node_modules/lib-jitsi-meet/
|
||||
LIBFLAC_DIR = node_modules/libflacjs/dist/min/
|
||||
OLM_DIR = node_modules/olm
|
||||
RNNOISE_WASM_DIR = node_modules/rnnoise-wasm/dist/
|
||||
NODE_SASS = ./node_modules/.bin/node-sass
|
||||
NODE_SASS = ./node_modules/.bin/sass
|
||||
NPM = npm
|
||||
OUTPUT_DIR = .
|
||||
STYLES_BUNDLE = css/all.bundle.css
|
||||
@@ -22,7 +23,7 @@ clean:
|
||||
rm -fr $(BUILD_DIR)
|
||||
|
||||
.NOTPARALLEL:
|
||||
deploy: deploy-init deploy-appbundle deploy-rnnoise-binary 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-olm deploy-css deploy-local
|
||||
|
||||
deploy-init:
|
||||
rm -fr $(DEPLOY_DIR)
|
||||
@@ -51,12 +52,15 @@ deploy-appbundle:
|
||||
$(BUILD_DIR)/video-blur-effect.min.map \
|
||||
$(BUILD_DIR)/rnnoise-processor.min.js \
|
||||
$(BUILD_DIR)/rnnoise-processor.min.map \
|
||||
$(BUILD_DIR)/close3.min.js \
|
||||
$(BUILD_DIR)/close3.min.map \
|
||||
$(DEPLOY_DIR)
|
||||
|
||||
deploy-lib-jitsi-meet:
|
||||
cp \
|
||||
$(LIBJITSIMEET_DIR)/lib-jitsi-meet.min.js \
|
||||
$(LIBJITSIMEET_DIR)/lib-jitsi-meet.min.map \
|
||||
$(LIBJITSIMEET_DIR)/lib-jitsi-meet.e2ee-worker.js \
|
||||
$(LIBJITSIMEET_DIR)/connection_optimization/external_connect.js \
|
||||
$(LIBJITSIMEET_DIR)/modules/browser/capabilities.json \
|
||||
$(DEPLOY_DIR)
|
||||
@@ -67,6 +71,11 @@ deploy-libflac:
|
||||
$(LIBFLAC_DIR)/libflac4-1.3.2.min.js.mem \
|
||||
$(DEPLOY_DIR)
|
||||
|
||||
deploy-olm:
|
||||
cp \
|
||||
$(OLM_DIR)/olm.wasm \
|
||||
$(DEPLOY_DIR)
|
||||
|
||||
deploy-rnnoise-binary:
|
||||
cp \
|
||||
$(RNNOISE_WASM_DIR)/rnnoise.wasm \
|
||||
@@ -81,7 +90,7 @@ deploy-local:
|
||||
([ ! -x deploy-local.sh ] || ./deploy-local.sh)
|
||||
|
||||
.NOTPARALLEL:
|
||||
dev: deploy-init deploy-css deploy-rnnoise-binary deploy-lib-jitsi-meet deploy-libflac
|
||||
dev: deploy-init deploy-css deploy-rnnoise-binary deploy-lib-jitsi-meet deploy-libflac deploy-olm
|
||||
$(WEBPACK_DEV_SERVER) --detect-circular-deps
|
||||
|
||||
source-package:
|
||||
|
||||
@@ -3,7 +3,7 @@ apply plugin: 'com.android.application'
|
||||
// Crashlytics integration is done as part of Firebase now, so it gets
|
||||
// automagically activated with google-services.json
|
||||
if (googleServicesEnabled) {
|
||||
apply plugin: 'io.fabric'
|
||||
apply plugin: 'com.google.firebase.crashlytics'
|
||||
}
|
||||
|
||||
// Use the number of seconds/10 since Jan 1 2019 as the versionCode.
|
||||
@@ -16,6 +16,10 @@ android {
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
buildToolsVersion rootProject.ext.buildToolsVersion
|
||||
|
||||
packagingOptions {
|
||||
exclude 'lib/*/libhermes*.so'
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId 'org.jitsi.meet'
|
||||
versionCode vcode
|
||||
@@ -70,16 +74,11 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven { url 'https://maven.fabric.io/public' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
|
||||
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.0-beta-5'
|
||||
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.2'
|
||||
|
||||
if (!rootProject.ext.libreBuild) {
|
||||
implementation 'com.google.android.gms:play-services-auth:16.0.1'
|
||||
@@ -87,9 +86,9 @@ dependencies {
|
||||
// Firebase
|
||||
// - Crashlytics
|
||||
// - Dynamic Links
|
||||
implementation 'com.google.firebase:firebase-core:16.0.6'
|
||||
implementation 'com.crashlytics.sdk.android:crashlytics:2.9.8'
|
||||
implementation 'com.google.firebase:firebase-dynamic-links:16.1.5'
|
||||
implementation 'com.google.firebase:firebase-analytics:17.5.0'
|
||||
implementation 'com.google.firebase:firebase-crashlytics:17.2.1'
|
||||
implementation 'com.google.firebase:firebase-dynamic-links:19.1.0'
|
||||
}
|
||||
|
||||
implementation project(':sdk')
|
||||
|
||||
6
android/app/proguard-rules.pro
vendored
6
android/app/proguard-rules.pro
vendored
@@ -85,8 +85,4 @@
|
||||
# ^^^ We added the above when we switched minifyEnabled on.
|
||||
|
||||
# Rule to avoid build errors related to SVGs.
|
||||
-keep public class com.horcrux.svg.** {*;}
|
||||
|
||||
# Hermes
|
||||
-keep class com.facebook.hermes.unicode.** { *; }
|
||||
|
||||
-keep public class com.horcrux.svg.** {*;}
|
||||
@@ -3,9 +3,8 @@ package org.jitsi.meet;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import com.crashlytics.android.Crashlytics;
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics;
|
||||
import com.google.firebase.dynamiclinks.FirebaseDynamicLinks;
|
||||
import io.fabric.sdk.android.Fabric;
|
||||
|
||||
import org.jitsi.meet.sdk.JitsiMeet;
|
||||
import org.jitsi.meet.sdk.JitsiMeetActivity;
|
||||
@@ -22,10 +21,7 @@ final class GoogleServicesHelper {
|
||||
if (BuildConfig.GOOGLE_SERVICES_ENABLED) {
|
||||
Log.d(activity.getClass().getSimpleName(), "Initializing Google Services");
|
||||
|
||||
if (!JitsiMeet.isCrashReportingDisabled(activity)) {
|
||||
Fabric.with(activity, new Crashlytics());
|
||||
}
|
||||
|
||||
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(!JitsiMeet.isCrashReportingDisabled(activity));
|
||||
FirebaseDynamicLinks.getInstance().getDynamicLink(activity.getIntent())
|
||||
.addOnSuccessListener(activity, pendingDynamicLinkData -> {
|
||||
Uri dynamicLink = null;
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.jitsi.meet.sdk.JitsiMeet;
|
||||
@@ -78,6 +79,12 @@ public class MainActivity extends JitsiMeetActivity {
|
||||
// JitsiMeetActivity overrides
|
||||
//
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
JitsiMeet.showSplashScreen(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean extraInitialize() {
|
||||
Log.d(this.getClass().getSimpleName(), "LIBRE_BUILD="+BuildConfig.LIBRE_BUILD);
|
||||
|
||||
70
android/app/src/main/res/drawable/ic_jitsi_logosvg.xml
Normal file
70
android/app/src/main/res/drawable/ic_jitsi_logosvg.xml
Normal file
@@ -0,0 +1,70 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="262.91376dp"
|
||||
android:height="262.91376dp"
|
||||
android:viewportWidth="262.91376"
|
||||
android:viewportHeight="262.91376">
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="m0,0 l262.914,-0L262.914,262.914 0,262.914 0,0Z"/>
|
||||
<path
|
||||
android:pathData="m142.646,105.099c0.117,0.026 0.255,0.036 0.406,0.036 3.186,-0 10.297,-4.615 11.617,-6.721l0.1,-0.17 0.153,-0.135c0.451,-0.441 1.746,-2.773 2.374,-4.17 -6.751,-2.023 -7.49,-5.677 -8.153,-8.919 -0.069,-0.376 -0.138,-0.717 -0.204,-1.019 -0.074,-0.397 -0.153,-0.8 -0.226,-1.112C138.668,86.221 135.593,88.094 133.921,89.483 133.056,90.201 132.542,92.251 135.042,97.926 136.323,100.816 140.727,104.733 142.646,105.099"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#00000000"
|
||||
android:fillType="nonZero"/>
|
||||
<path
|
||||
android:pathData="m115.413,146.042c5.934,-0 18.464,-3.543 26.748,-5.887 1.21,-0.336 2.33,-0.66 3.351,-0.944 0.166,-0.046 0.321,-0.091 0.472,-0.124 -0.463,-0.461 -1.239,-1.159 -2.497,-2.216 -5.521,-3.741 -10.736,-5.484 -16.403,-5.484 -1.237,-0 -2.522,0.071 -3.923,0.231 -4.801,0.55 -8.8,1.69 -10.722,2.237 -0.967,0.284 -1.263,0.366 -1.567,0.366 -0.58,-0 -1.079,-0.341 -1.273,-0.878 -0.194,-0.534 -0.027,-1.121 0.425,-1.507l0.024,-0.011c3.316,-2.784 9.489,-7.951 21.198,-10.256 2.027,-0.401 4.202,-0.605 6.454,-0.605 5.242,-0 10.67,1.086 16.125,3.219 7.436,2.899 12.521,6.625 16.602,9.62 2.199,1.609 4.105,3.007 5.755,3.771 0.421,0.2 0.637,0.255 0.746,0.265 0.074,-0.095 0.23,-0.365 0.474,-1.069 0.066,-0.185 0.529,-2.161 -2.806,-13.374 -1.931,-6.51 -4.264,-13.156 -5.479,-16.104 -2.356,-5.711 -1.778,-9.76 -1.051,-12.125 -1.999,0.735 -4.033,1.87 -6.174,3.446L161.758,98.711C160.694,99.506 159.599,100.404 158.426,101.454 151.517,107.64 146.344,110.864 143.035,111.04l-0.093,0.004 -0.093,-0.009c-2.912,-0.245 -7.324,-4.489 -9.133,-6.634 -0.373,-0.251 -0.8,-0.366 -1.366,-0.366 -0.564,-0 -1.202,0.116 -1.82,0.235C130.086,104.354 129.623,104.441 129.167,104.489 127.708,104.632 125.668,105.106 123.694,105.561 122.746,105.777 121.762,106.005 120.864,106.189 120.851,106.19 120.463,106.272 119.774,106.454 114.903,107.891 111.228,109.55 109.432,111.111 109.414,111.127 109.352,111.174 109.266,111.242 108.048,112.105 105.124,114.567 104.248,118.762L104.237,118.795C102.398,126.516 105.187,136.087 108.892,141.554 110.636,144.125 112.513,145.727 114.048,145.959 114.437,146.015 114.891,146.042 115.413,146.042"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#00000000"
|
||||
android:fillType="nonZero"/>
|
||||
<path
|
||||
android:pathData="m90.093,173.175c-1.252,-1.472 -1.783,-3.324 -1.574,-5.521 0.884,-10.642 -0.329,-13.215 -0.891,-13.829 -0.131,-0.144 -0.207,-0.144 -0.265,-0.144 -0.022,-0 -0.041,0.003 -0.064,0.003 -1.044,0.248 -8.066,5.002 -9.615,19.171 -0.749,6.845 0.561,15.63 1.679,20.974 0.897,-3.155 2.314,-6.624 5.057,-10.204 2.556,-3.326 5.345,-5.955 8.801,-8.253C92.143,174.93 90.991,174.235 90.093,173.175"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#00000000"
|
||||
android:fillType="nonZero"/>
|
||||
<path
|
||||
android:pathData="m94.906,156.389c-0.03,2.229 -0.326,4.36 -0.61,6.445 -0.151,1.119 -0.314,2.286 -0.434,3.46 -0.161,2.341 0.346,3.166 0.571,3.406 0.127,0.136 0.326,0.287 0.76,0.287 0.339,-0 0.741,-0.091 1.161,-0.268 4.202,-1.756 8.195,-4.815 10.115,-6.515C103.522,161.892 98.995,159.058 94.906,156.389"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#00000000"
|
||||
android:fillType="nonZero"/>
|
||||
<path
|
||||
android:pathData="m154.002,81.595c-0.031,0.074 -0.065,0.148 -0.101,0.216 -0.821,2.403 0.306,5.664 2.419,6.898 0.561,0.327 1.106,0.526 1.624,0.596 0.072,0.006 0.148,0.009 0.219,0.009 1.645,-0 2.971,-1.199 3.961,-3.561C162.752,83.959 162.836,81.827 162.37,79.904 162.003,78.409 161.057,76.627 160.453,75.738 159.332,76.509 157.111,78.207 155.585,79.553 154.518,80.582 154.136,81.229 154.002,81.595"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#00000000"
|
||||
android:fillType="nonZero"/>
|
||||
<path
|
||||
android:pathData="M148.97,77.699C153.957,73.194 156.988,65.754 158.253,61.334 153.915,65.513 148.633,67.758 145.25,69.198 144.084,69.695 143.08,70.124 142.477,70.476 142.224,70.623 141.965,70.77 141.708,70.919 139.654,72.109 136.55,73.905 136.1,75.011l-0.012,0.036 -0.012,0.034c-1.406,2.956 -2.199,7.401 -2.457,9.95 3.266,-1.99 6.625,-3.322 9.416,-4.42C145.628,79.585 147.863,78.703 148.97,77.699"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#00000000"
|
||||
android:fillType="nonZero"/>
|
||||
<path
|
||||
android:pathData="m164.464,51.921c-0.84,5.539 -2.205,10.799 -4.751,16.347 2.781,-3.144 4.396,-6.568 4.941,-10.401C164.886,56.275 165.097,54.756 164.464,51.921"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#00000000"
|
||||
android:fillType="nonZero"/>
|
||||
<path
|
||||
android:pathData="M148.749,142.639C148.718,142.598 148.684,142.56 148.658,142.519 148.523,142.539 148.307,142.584 147.972,142.683l-0.14,0.04c-1.726,0.644 -4.899,1.708 -8.556,2.946 -4.396,1.479 -9.365,3.154 -13.526,4.649 -5.297,1.975 -7.021,2.755 -7.557,3.024 -0.098,0.266 -0.203,0.599 -0.327,0.965 -1.254,3.816 -4.125,12.541 -18.276,18.653 2.928,2.956 9.289,8.27 21.809,8.27 1.082,-0 2.21,-0.036 3.341,-0.12 9.451,-0.666 18.342,-4.855 25.026,-11.78 6.087,-6.291 9.538,-14.136 9.585,-21.7C157.876,147.509 155.367,147.135 153.043,146.033 153.014,146.02 150.361,144.745 148.749,142.639"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#00000000"
|
||||
android:fillType="nonZero"/>
|
||||
<path
|
||||
android:pathData="m189.478,117.853c-0.523,9.749 -2.122,18.424 -4.744,25.8 -2.128,5.988 -4.94,11.134 -8.356,15.316 -5.676,6.931 -11.555,9.256 -12.804,9.304 -0.866,-0 -1.313,-0.309 -3.046,-1.528 -0.17,-0.114 -0.37,-0.252 -0.581,-0.4 -3.313,5.953 -8.505,11.097 -15.065,14.959 -7.079,4.144 -15.297,6.423 -23.157,6.423 -9.078,-0 -17.13,-2.924 -23.341,-8.456 -7.467,4.799 -12.31,9.074 -16.267,27.005l-1.363,6.17 -2.971,-5.564c-0.424,-0.786 -1.929,-3.731 -3.332,-8.887 -1.934,-7.104 -2.86,-15.181 -2.758,-24.01 0.117,-10.049 3.154,-16.526 5.68,-20.186 2.98,-4.314 6.837,-6.994 10.076,-6.994 0.216,-0 0.428,0.006 0.616,0.035 5.159,0.575 8.435,2.75 14.396,6.686l1.899,1.252c2.059,1.344 4.481,2.7 5.259,2.989 0.54,-0.284 1.749,-2.3 2.155,-5.271l0.069,-0.451c0.005,-0.045 0.009,-0.091 0.014,-0.131 -0.036,-0.02 -0.065,-0.029 -0.094,-0.041 -4.008,-1.375 -9.539,-7.7 -12.364,-17.134 -2.684,-9.382 -2.129,-17.185 1.644,-23.193 6.12,-9.736 19.198,-11.974 23.466,-12.702 1.331,-0.266 2.716,-0.511 4.041,-0.717 0.255,-0.061 0.469,-0.121 0.642,-0.168 -0.031,-0.126 -0.071,-0.265 -0.114,-0.43 -0.108,-0.417 -0.23,-0.891 -0.354,-1.447 -1.345,-6.035 -0.664,-11.069 0.181,-15.193 0.928,-4.546 1.489,-7.287 3.747,-9.936 3.029,-4.165 8.319,-5.936 11.479,-6.991 0.746,-0.249 1.511,-0.509 1.894,-0.689 8.988,-4.31 11.82,-8.739 12.615,-11.694 0.656,-2.451 1.699,-8.884 1.251,-13.335 -0.085,-0.805 0.129,-1.521 0.621,-2.065 0.45,-0.505 1.101,-0.794 1.778,-0.794 1.515,-0 2.82,-0 7.511,14.598 2.481,7.698 0.645,14.903 -5.45,21.424l-0.226,0.231c0.024,0.044 0.049,0.09 0.08,0.144 2.57,4.236 3.963,9.54 3.553,13.51 -0.099,0.906 -0.265,1.775 -0.419,2.549 -0.003,0.01 -0.003,0.016 -0.004,0.029 0.516,-0.032 1.119,-0.055 1.775,-0.055 3.052,-0 7.435,0.474 10.989,2.735 2.135,1.352 4.845,3.439 6.835,7.615C189.223,102.942 190.076,109.575 189.478,117.853m4.77,-23.191c-2.916,-6.1 -6.989,-9.177 -9.793,-10.96 -2.355,-1.494 -5.064,-2.584 -8.077,-3.24l-0.676,-0.146 -0.111,-0.689c-0.339,-2.119 -0.918,-4.275 -1.715,-6.406l-0.185,-0.49 0.292,-0.434c5.095,-7.594 6.323,-16.17 3.54,-24.802 -2.191,-6.824 -3.895,-11.211 -5.341,-13.799 -2.954,-5.305 -7.006,-6.417 -9.891,-6.417 -2.964,-0 -5.8,1.261 -7.789,3.457 -2.043,2.254 -2.993,5.207 -2.678,8.31 0.316,3.134 -0.494,8.516 -1.014,10.439 -0.04,0.117 -0.975,2.929 -8.201,6.428 -0.162,0.056 -0.512,0.179 -1.053,0.359 -3.729,1.246 -10.666,3.571 -15.258,9.64 -3.465,4.205 -4.332,8.441 -5.338,13.346 -0.586,2.865 -1.236,6.744 -1.079,11.344l0.026,0.841 -0.824,0.188c-11.646,2.585 -20.025,7.835 -24.909,15.605 -5.054,8.04 -5.919,18.055 -2.543,29.853 0.063,0.204 0.126,0.407 0.189,0.615l0.527,1.608 -1.665,-0.286c-0.561,-0.101 -1.135,-0.18 -1.729,-0.241 -0.493,-0.06 -1.001,-0.082 -1.509,-0.082 -5.633,-0 -11.663,3.585 -16.128,9.592 -3.451,4.641 -7.588,12.849 -7.735,25.601 -0.114,9.573 0.906,18.401 3.038,26.228 1.581,5.795 3.326,9.329 4.004,10.577l13.306,24.94 6.096,-27.619c2.454,-11.09 4.864,-15.262 7.725,-18.111l0.561,-0.563 0.679,0.411c6.605,3.977 14.466,6.084 22.73,6.084 9.286,-0 18.965,-2.682 27.259,-7.551 5.38,-3.16 9.974,-7.036 13.649,-11.531l0.45,-0.369 0.85,-0.02c2.156,-0.068 5.16,-1.164 8.222,-3.004 2.6,-1.555 6.543,-4.428 10.501,-9.262 3.997,-4.884 7.274,-10.854 9.716,-17.734 2.876,-8.073 4.625,-17.489 5.204,-28.004 0.689,-9.668 -0.434,-17.641 -3.327,-23.704"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#00000000"
|
||||
android:fillType="nonZero"/>
|
||||
<path
|
||||
android:pathData="m180.026,98.414c-1.67,-2.596 -3.771,-4.206 -5.475,-4.206 -0.313,-0 -0.613,0.051 -0.895,0.161 -0.911,0.361 -2.356,4.532 -1.714,7.566 0.434,2.066 2.938,9.04 4.151,12.394 0.456,1.281 0.68,1.91 0.754,2.142 0.064,0.183 0.145,0.448 0.256,0.774 0.97,2.971 3.467,10.586 4.206,16.761 1.549,-6.579 2.424,-14.512 2.085,-23.997C183.235,105.662 182.04,101.538 180.026,98.414"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#00000000"
|
||||
android:fillType="nonZero"/>
|
||||
<path
|
||||
android:pathData="M168.088,142.604C169.896,142.111 171.33,141.705 172.398,141.395 170.213,139.874 167.689,137.979 164.247,135.304c-8.418,-6.546 -17.449,-9.87 -26.839,-9.87 -5.135,-0 -9.611,0.991 -13.156,2.186 0.882,-0.05 1.779,-0.079 2.7,-0.079 1.1,-0 2.247,0.04 3.411,0.119 3.652,0.246 13.061,1.901 21.565,12.047 1.714,2.039 3.559,3.73 8.794,3.73 1.873,-0 4.051,-0.207 6.662,-0.645C167.544,142.751 167.793,142.678 168.088,142.604"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#00000000"
|
||||
android:fillType="nonZero"/>
|
||||
<path
|
||||
android:pathData="m164.3,147.583c-0.122,1.563 -0.376,4.509 -0.782,6.76 -0.495,2.719 -1.31,5.02 -1.791,6.226 0.85,0.786 1.694,1.553 2.247,2.043 2.214,-1.447 9.47,-6.96 14.483,-19.474C176.847,144.229 174.59,145.178 171.671,146.018 168.701,146.861 165.82,147.357 164.3,147.583"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#00000000"
|
||||
android:fillType="nonZero"/>
|
||||
</group>
|
||||
</vector>
|
||||
11
android/app/src/main/res/layout/launch_screen.xml
Normal file
11
android/app/src/main/res/layout/launch_screen.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/colorPrimary">
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:src="@drawable/ic_jitsi_logosvg"/>
|
||||
</RelativeLayout>
|
||||
5
android/app/src/main/res/values/colors.xml
Normal file
5
android/app/src/main/res/values/colors.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#17A0DB</color>
|
||||
<color name="colorPrimaryDark">#1081B2</color>
|
||||
</resources>
|
||||
@@ -2,6 +2,6 @@
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="android:navigationBarColor">#1081B2</item>
|
||||
<item name="android:navigationBarColor">@color/colorPrimaryDark</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import groovy.json.JsonSlurper
|
||||
import org.gradle.util.VersionNumber
|
||||
|
||||
// Top-level build file where you can add configuration options common to all
|
||||
// sub-projects/modules.
|
||||
@@ -7,26 +8,46 @@ buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
repositories {
|
||||
maven { url 'https://maven.fabric.io/public' }
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.3.2'
|
||||
classpath 'com.android.tools.build:gradle:4.0.2'
|
||||
classpath 'com.google.gms:google-services:4.3.3'
|
||||
classpath 'io.fabric.tools:gradle:1.28.1'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files.
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.3.0'
|
||||
}
|
||||
}
|
||||
|
||||
ext {
|
||||
buildToolsVersion = "29.0.3"
|
||||
compileSdkVersion = 29
|
||||
minSdkVersion = 23
|
||||
targetSdkVersion = 29
|
||||
supportLibVersion = "28.0.0"
|
||||
|
||||
// The Maven artifact groupdId of the third-party react-native modules which
|
||||
// Jitsi Meet SDK for Android depends on and which are not available in
|
||||
// third-party Maven repositories so we have to deploy to a Maven repository
|
||||
// of ours.
|
||||
moduleGroupId = 'com.facebook.react'
|
||||
|
||||
// Maven repo where artifacts will be published
|
||||
mavenRepo = System.env.MVN_REPO ?: ""
|
||||
mavenUser = System.env.MVN_USER ?: ""
|
||||
mavenPassword = System.env.MVN_PASSWORD ?: ""
|
||||
|
||||
// Libre build
|
||||
libreBuild = (System.env.LIBRE_BUILD ?: "false").toBoolean()
|
||||
|
||||
googleServicesEnabled = project.file('app/google-services.json').exists() && !libreBuild
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
// React Native (JS, Obj-C sources, Android binaries) is installed from npm.
|
||||
maven { url "$rootDir/../node_modules/react-native/android" }
|
||||
// Android JSC is installed from npm.
|
||||
maven { url("$rootDir/../node_modules/jsc-android/dist") }
|
||||
}
|
||||
|
||||
// Make sure we use the react-native version in node_modules and not the one
|
||||
@@ -141,30 +162,6 @@ allprojects {
|
||||
}
|
||||
}
|
||||
|
||||
ext {
|
||||
buildToolsVersion = "29.0.3"
|
||||
compileSdkVersion = 29
|
||||
minSdkVersion = 23
|
||||
targetSdkVersion = 29
|
||||
supportLibVersion = "28.0.0"
|
||||
|
||||
// The Maven artifact groupdId of the third-party react-native modules which
|
||||
// Jitsi Meet SDK for Android depends on and which are not available in
|
||||
// third-party Maven repositories so we have to deploy to a Maven repository
|
||||
// of ours.
|
||||
moduleGroupId = 'com.facebook.react'
|
||||
|
||||
// Maven repo where artifacts will be published
|
||||
mavenRepo = System.env.MVN_REPO ?: ""
|
||||
mavenUser = System.env.MVN_USER ?: ""
|
||||
mavenPassword = System.env.MVN_PASSWORD ?: ""
|
||||
|
||||
// Libre build
|
||||
libreBuild = (System.env.LIBRE_BUILD ?: "false").toBoolean()
|
||||
|
||||
googleServicesEnabled = project.file('app/google-services.json').exists() && !libreBuild
|
||||
}
|
||||
|
||||
// Force the version of the Android build tools we have chosen on all
|
||||
// subprojects. The forcing was introduced for react-native and the third-party
|
||||
// modules that we utilize such as react-native-background-timer.
|
||||
|
||||
@@ -10,15 +10,20 @@
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
# Default value: -Xmx10248m -XX:MaxPermSize=256m
|
||||
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
|
||||
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
|
||||
# This one fixes a weird WebRTC runtime problem on some devices.
|
||||
# https://github.com/jitsi/jitsi-meet/issues/7911#issuecomment-714323255
|
||||
android.enableDexingArtifactTransform.desugaring=false
|
||||
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
||||
appVersion=20.4.0
|
||||
sdkVersion=2.10.0
|
||||
appVersion=20.5.0
|
||||
sdkVersion=2.11.0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#Fri Mar 08 13:36:51 CET 2019
|
||||
#Wed Sep 23 11:48:00 EEST 2020
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip
|
||||
|
||||
@@ -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 '.version' ${THIS_DIR}/../../node_modules/react-native/package.json)
|
||||
HERMES_VERSION=$(jq -r '.dependencies."hermes-engine"' ${THIS_DIR}/../../node_modules/react-native/package.json | cut -c 2-)
|
||||
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
|
||||
@@ -38,19 +38,17 @@ if [[ $MVN_HTTP == 1 ]]; then
|
||||
-DgeneratePom=false \
|
||||
-DpomFile=react-native-${RN_VERSION}.pom || true
|
||||
popd
|
||||
# Push Hermes
|
||||
echo "Pushing Hermes ${HERMES_VERSION} to the Maven repo"
|
||||
pushd ${THIS_DIR}/../../node_modules/hermes-engine/android/
|
||||
# Push JSC
|
||||
echo "Pushing JSC ${JSC_VERSION} to the Maven repo"
|
||||
pushd ${THIS_DIR}/../../node_modules/jsc-android/dist/org/webkit/android-jsc/${JSC_VERSION}
|
||||
mvn \
|
||||
deploy:deploy-file \
|
||||
-Durl=${MVN_REPO} \
|
||||
-DrepositoryId=${MVN_REPO_ID} \
|
||||
-Dfile=hermes-release.aar \
|
||||
-Dfile=android-jsc-${JSC_VERSION}.aar \
|
||||
-Dpackaging=aar \
|
||||
-DgroupId=com.facebook \
|
||||
-DartifactId=hermes \
|
||||
-Dversion=${HERMES_VERSION} \
|
||||
-DgeneratePom=true || true
|
||||
-DgeneratePom=false \
|
||||
-DpomFile=android-jsc-${JSC_VERSION}.pom || true
|
||||
popd
|
||||
else
|
||||
# Push React Native, if necessary
|
||||
@@ -67,19 +65,17 @@ else
|
||||
popd
|
||||
fi
|
||||
|
||||
# Push Hermes, if necessary
|
||||
if [[ ! -d ${MVN_REPO}/com/facebook/hermes/${HERMES_VERSION} ]]; then
|
||||
echo "Pushing Hermes ${HERMES_VERSION} to the Maven repo"
|
||||
pushd ${THIS_DIR}/../../node_modules/hermes-engine/android/
|
||||
# Push JSC, if necessary
|
||||
if [[ ! -d ${MVN_REPO}/org/webkit/android-jsc/${JSC_VERSION} ]]; then
|
||||
echo "Pushing JSC ${JSC_VERSION} to the Maven repo"
|
||||
pushd ${THIS_DIR}/../../node_modules/jsc-android/dist/org/webkit/android-jsc/${JSC_VERSION}
|
||||
mvn \
|
||||
deploy:deploy-file \
|
||||
-Durl=${MVN_REPO} \
|
||||
-Dfile=hermes-release.aar \
|
||||
-Dfile=android-jsc-${JSC_VERSION}.aar \
|
||||
-Dpackaging=aar \
|
||||
-DgroupId=com.facebook \
|
||||
-DartifactId=hermes \
|
||||
-Dversion=${HERMES_VERSION} \
|
||||
-DgeneratePom=true
|
||||
-DgeneratePom=false \
|
||||
-DpomFile=android-jsc-${JSC_VERSION}.pom
|
||||
popd
|
||||
fi
|
||||
|
||||
@@ -93,7 +89,9 @@ fi
|
||||
# Now build and publish the Jitsi Meet SDK and its dependencies
|
||||
echo "Building and publishing the Jitsi Meet SDK"
|
||||
pushd ${THIS_DIR}/../
|
||||
./gradlew clean assembleRelease publish
|
||||
./gradlew clean
|
||||
./gradlew assembleRelease
|
||||
./gradlew publish
|
||||
popd
|
||||
|
||||
if [[ $DO_GIT_TAG == 1 ]]; then
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import groovy.json.JsonSlurper
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
@@ -35,26 +33,19 @@ android {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
pickFirst '**/libc++_shared.so'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.fragment:fragment:1.2.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'androidx.fragment:fragment:1.2.5'
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||
|
||||
//noinspection GradleDynamicVersion
|
||||
api 'com.facebook.react:react-native:+'
|
||||
|
||||
// Hermes JS engine
|
||||
def hermesPath = "../../node_modules/hermes-engine/android/"
|
||||
debugImplementation files(hermesPath + "hermes-debug.aar")
|
||||
releaseImplementation files(hermesPath + "hermes-release.aar")
|
||||
//noinspection GradleDynamicVersion
|
||||
implementation 'org.webkit:android-jsc:+'
|
||||
|
||||
implementation 'com.dropbox.core:dropbox-core-sdk:3.0.8'
|
||||
implementation 'com.jakewharton.timber:timber:4.7.1'
|
||||
@@ -80,6 +71,7 @@ dependencies {
|
||||
implementation project(':react-native-svg')
|
||||
implementation project(':react-native-webrtc')
|
||||
implementation project(':react-native-webview')
|
||||
implementation project(':react-native-splash-screen')
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
}
|
||||
@@ -153,7 +145,7 @@ android.libraryVariants.all { def variant ->
|
||||
mergeResourcesTask.dependsOn(currentBundleTask)
|
||||
|
||||
mergeAssetsTask.doLast {
|
||||
def assetsDir = mergeAssetsTask.outputDir
|
||||
def assetsDir = mergeAssetsTask.outputDir.get()
|
||||
|
||||
// Bundle sounds
|
||||
//
|
||||
@@ -187,7 +179,7 @@ android.libraryVariants.all { def variant ->
|
||||
if (currentBundleTask.enabled) {
|
||||
copy {
|
||||
from(resourcesDir)
|
||||
into(mergeResourcesTask.outputDir)
|
||||
into(mergeResourcesTask.outputDir.get())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -227,14 +219,6 @@ publishing {
|
||||
dependency.appendNode('artifactId', artifactId)
|
||||
dependency.appendNode('version', it.moduleVersion)
|
||||
}
|
||||
|
||||
// Add Hermes dependency.
|
||||
def hermesPkg = new File("$rootDir/../node_modules/hermes-engine/package.json")
|
||||
def hermesVersion = new JsonSlurper().parseText(hermesPkg.text).version
|
||||
def hermesDependency = dependencies.appendNode('dependency')
|
||||
hermesDependency.appendNode('groupId', "com.facebook")
|
||||
hermesDependency.appendNode('artifactId', "hermes")
|
||||
hermesDependency.appendNode('version', hermesVersion)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
||||
<uses-feature
|
||||
android:glEsVersion="0x00020000"
|
||||
@@ -34,8 +34,7 @@
|
||||
android:launchMode="singleTask"
|
||||
android:resizeableActivity="true"
|
||||
android:supportsPictureInPicture="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
</activity>
|
||||
android:windowSoftInputMode="adjustResize"></activity>
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
|
||||
|
||||
<service
|
||||
@@ -46,7 +45,9 @@
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<service android:name="org.jitsi.meet.sdk.JitsiMeetOngoingConferenceService" />
|
||||
<service
|
||||
android:name="org.jitsi.meet.sdk.JitsiMeetOngoingConferenceService"
|
||||
android:foregroundServiceType="mediaProjection" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright @ 2018-present 8x8, Inc.
|
||||
* Copyright @ 2017-2018 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,12 +15,16 @@
|
||||
*/
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
|
||||
import org.devio.rn.splashscreen.SplashScreen;
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
public class JitsiMeet {
|
||||
|
||||
/**
|
||||
@@ -81,4 +84,17 @@ public class JitsiMeet {
|
||||
String value = preferences.getString("isCrashReportingDisabled", "");
|
||||
return Boolean.parseBoolean(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to show the SplashScreen.
|
||||
*
|
||||
* @param activity - The activity on which to show the SplashScreen {@link Activity}.
|
||||
*/
|
||||
public static void showSplashScreen(Activity activity) {
|
||||
try {
|
||||
SplashScreen.show(activity);
|
||||
} catch (Exception e) {
|
||||
JitsiMeetLogger.e(e, "Failed to show splash screen");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,8 @@ import com.facebook.react.bridge.Callback;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.modules.core.PermissionListener;
|
||||
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
/**
|
||||
* Helper class to encapsulate the work which needs to be done on
|
||||
* {@link Activity} lifecycle methods in order for the React side to be aware of
|
||||
@@ -177,6 +179,16 @@ public class JitsiMeetActivityDelegate {
|
||||
|
||||
public static void requestPermissions(Activity activity, String[] permissions, int requestCode, PermissionListener listener) {
|
||||
permissionListener = listener;
|
||||
activity.requestPermissions(permissions, requestCode);
|
||||
|
||||
// The RN Permissions module calls this in a non-UI thread. What we observe is a crash in ViewGroup.dispatchCancelPendingInputEvents,
|
||||
// which is called on the calling (ie, non-UI) thread. This doesn't look very safe, so try to avoid a crash by pretending the permission
|
||||
// was denied.
|
||||
|
||||
try {
|
||||
activity.requestPermissions(permissions, requestCode);
|
||||
} catch (Exception e) {
|
||||
JitsiMeetLogger.e(e, "Error requesting permissions");
|
||||
onRequestPermissionsResult(requestCode, permissions, new int[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ class PictureInPictureModule extends ReactContextBaseJavaModule {
|
||||
private static final String TAG = NAME;
|
||||
|
||||
private static boolean isSupported;
|
||||
private boolean isDisabled;
|
||||
|
||||
public PictureInPictureModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
@@ -83,6 +84,10 @@ class PictureInPictureModule extends ReactContextBaseJavaModule {
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public void enterPictureInPicture() {
|
||||
if (isDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isSupported) {
|
||||
throw new IllegalStateException("Picture-in-Picture not supported");
|
||||
}
|
||||
@@ -126,6 +131,11 @@ class PictureInPictureModule extends ReactContextBaseJavaModule {
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void setPictureInPictureDisabled(Boolean disabled) {
|
||||
this.isDisabled = disabled;
|
||||
}
|
||||
|
||||
public boolean isPictureInPictureSupported() {
|
||||
return isSupported;
|
||||
}
|
||||
|
||||
@@ -20,21 +20,21 @@ import android.app.Activity;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.facebook.hermes.reactexecutor.HermesExecutorFactory;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.common.LifecycleState;
|
||||
import com.facebook.react.devsupport.DevInternalSettings;
|
||||
import com.facebook.react.jscexecutor.JSCExecutorFactory;
|
||||
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
|
||||
import com.oney.WebRTCModule.RTCVideoViewManager;
|
||||
import com.oney.WebRTCModule.WebRTCModule;
|
||||
|
||||
import org.devio.rn.splashscreen.SplashScreenModule;
|
||||
import org.webrtc.SoftwareVideoDecoderFactory;
|
||||
import org.webrtc.SoftwareVideoEncoderFactory;
|
||||
import org.webrtc.audio.AudioDeviceModule;
|
||||
@@ -68,6 +68,7 @@ class ReactInstanceManagerHolder {
|
||||
new JavaScriptSandboxModule(reactContext),
|
||||
new LocaleDetector(reactContext),
|
||||
new LogBridgeModule(reactContext),
|
||||
new SplashScreenModule(reactContext),
|
||||
new PictureInPictureModule(reactContext),
|
||||
new ProximityModule(reactContext),
|
||||
new WiFiStatsModule(reactContext),
|
||||
@@ -216,8 +217,9 @@ class ReactInstanceManagerHolder {
|
||||
// Ignore any error, the module is not compiled when LIBRE_BUILD is enabled.
|
||||
}
|
||||
|
||||
// Use the Hermes JavaScript engine.
|
||||
HermesExecutorFactory jsFactory = new HermesExecutorFactory();
|
||||
// Keep on using JSC, the jury is out on Hermes.
|
||||
JSCExecutorFactory jsFactory
|
||||
= new JSCExecutorFactory("", "");
|
||||
|
||||
reactInstanceManager
|
||||
= ReactInstanceManager.builder()
|
||||
|
||||
@@ -21,6 +21,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-splash-screen'
|
||||
project(':react-native-splash-screen').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-splash-screen/android')
|
||||
include ':react-native-svg'
|
||||
project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-svg/android')
|
||||
include ':react-native-webrtc'
|
||||
|
||||
17
app.js
17
app.js
@@ -4,6 +4,15 @@ import 'jquery';
|
||||
import 'jquery-contextmenu';
|
||||
import 'jQuery-Impromptu';
|
||||
|
||||
import 'olm';
|
||||
|
||||
import 'focus-visible';
|
||||
|
||||
// We need to setup the jitsi-local-storage as early as possible so that we can start using it.
|
||||
// NOTE: If jitsi-local-storage is used before the initial setup is performed this will break the use case when we use
|
||||
// the local storage from the parent page when the localStorage is disabled. Also the setup is relying that
|
||||
// window.location is not changed and still has all URL parameters.
|
||||
import './react/features/base/jitsi-local-storage/setup';
|
||||
import conference from './conference';
|
||||
import API from './modules/API';
|
||||
import UI from './modules/UI/UI';
|
||||
@@ -11,6 +20,14 @@ import keyboardshortcut from './modules/keyboardshortcut/keyboardshortcut';
|
||||
import remoteControl from './modules/remotecontrol/RemoteControl';
|
||||
import translation from './modules/translation/translation';
|
||||
|
||||
// Initialize Olm as early as possible.
|
||||
if (window.Olm) {
|
||||
window.Olm.init().catch(e => {
|
||||
console.error('Failed to initialize Olm, E2EE will be disabled', e);
|
||||
delete window.Olm;
|
||||
});
|
||||
}
|
||||
|
||||
window.APP = {
|
||||
API,
|
||||
conference,
|
||||
|
||||
205
conference.js
205
conference.js
@@ -24,7 +24,6 @@ import {
|
||||
reloadWithStoredParams
|
||||
} from './react/features/app/actions';
|
||||
import {
|
||||
AVATAR_ID_COMMAND,
|
||||
AVATAR_URL_COMMAND,
|
||||
EMAIL_COMMAND,
|
||||
authStatusChanged,
|
||||
@@ -42,8 +41,7 @@ import {
|
||||
lockStateChanged,
|
||||
onStartMutedPolicyChanged,
|
||||
p2pStatusChanged,
|
||||
sendLocalParticipant,
|
||||
setDesktopSharingEnabled
|
||||
sendLocalParticipant
|
||||
} from './react/features/base/conference';
|
||||
import {
|
||||
checkAndNotifyForNewDevice,
|
||||
@@ -66,6 +64,8 @@ import {
|
||||
JitsiTrackEvents
|
||||
} from './react/features/base/lib-jitsi-meet';
|
||||
import {
|
||||
getStartWithAudioMuted,
|
||||
getStartWithVideoMuted,
|
||||
isVideoMutedByUser,
|
||||
MEDIA_TYPE,
|
||||
setAudioAvailable,
|
||||
@@ -97,20 +97,17 @@ import {
|
||||
destroyLocalTracks,
|
||||
getLocalJitsiAudioTrack,
|
||||
getLocalJitsiVideoTrack,
|
||||
isLocalVideoTrackMuted,
|
||||
isLocalCameraTrackMuted,
|
||||
isLocalTrackMuted,
|
||||
isUserInteractionRequiredForUnmute,
|
||||
replaceLocalTrack,
|
||||
trackAdded,
|
||||
trackRemoved
|
||||
} from './react/features/base/tracks';
|
||||
import {
|
||||
getBackendSafePath,
|
||||
getJitsiMeetGlobalNS
|
||||
} from './react/features/base/util';
|
||||
import { downloadJSON } from './react/features/base/util/downloadJSON';
|
||||
import { getConferenceOptions } from './react/features/conference/functions';
|
||||
import { showDesktopPicker } from './react/features/desktop-picker';
|
||||
import { appendSuffix } from './react/features/display-name';
|
||||
import { setE2EEKey } from './react/features/e2ee';
|
||||
import {
|
||||
maybeOpenFeedbackDialog,
|
||||
submitFeedback
|
||||
@@ -121,9 +118,9 @@ import { suspendDetected } from './react/features/power-monitor';
|
||||
import {
|
||||
initPrejoin,
|
||||
isPrejoinPageEnabled,
|
||||
isPrejoinPageVisible
|
||||
isPrejoinPageVisible,
|
||||
makePrecallTest
|
||||
} from './react/features/prejoin';
|
||||
import { createRnnoiseProcessorPromise } from './react/features/rnnoise';
|
||||
import { toggleScreenshotCaptureEffect } from './react/features/screenshot-capture';
|
||||
import { setSharedVideoStatus } from './react/features/shared-video';
|
||||
import { AudioMixerEffect } from './react/features/stream-effects/audio-mixer/AudioMixerEffect';
|
||||
@@ -172,7 +169,6 @@ window.JitsiMeetScreenObtainer = {
|
||||
* Known custom conference commands.
|
||||
*/
|
||||
const commands = {
|
||||
AVATAR_ID: AVATAR_ID_COMMAND,
|
||||
AVATAR_URL: AVATAR_URL_COMMAND,
|
||||
CUSTOM_ROLE: 'custom-role',
|
||||
EMAIL: EMAIL_COMMAND,
|
||||
@@ -444,17 +440,8 @@ export default {
|
||||
* the tracks won't exist).
|
||||
*/
|
||||
_localTracksInitialized: false,
|
||||
isSharingScreen: false,
|
||||
|
||||
/**
|
||||
* Indicates if the desktop sharing functionality has been enabled.
|
||||
* It takes into consideration the status returned by
|
||||
* {@link JitsiMeetJS.isDesktopSharingEnabled()}. The latter can be false
|
||||
* either if the desktop sharing is not supported by the current browser
|
||||
* or if it was disabled through lib-jitsi-meet specific options (check
|
||||
* config.js for listed options).
|
||||
*/
|
||||
isDesktopSharingEnabled: false,
|
||||
isSharingScreen: false,
|
||||
|
||||
/**
|
||||
* The local audio track (if any).
|
||||
@@ -682,14 +669,6 @@ export default {
|
||||
con.addEventListener(JitsiConnectionEvents.CONNECTION_FAILED, _connectionFailedHandler);
|
||||
APP.connection = connection = con;
|
||||
|
||||
// Desktop sharing related stuff:
|
||||
this.isDesktopSharingEnabled
|
||||
= JitsiMeetJS.isDesktopSharingEnabled();
|
||||
eventEmitter.emit(JitsiMeetConferenceEvents.DESKTOP_SHARING_ENABLED_CHANGED, this.isDesktopSharingEnabled);
|
||||
|
||||
APP.store.dispatch(
|
||||
setDesktopSharingEnabled(this.isDesktopSharingEnabled));
|
||||
|
||||
this._createRoom(tracks);
|
||||
APP.remoteControl.init();
|
||||
|
||||
@@ -736,17 +715,15 @@ export default {
|
||||
const initialOptions = {
|
||||
startAudioOnly: config.startAudioOnly,
|
||||
startScreenSharing: config.startScreenSharing,
|
||||
startWithAudioMuted: config.startWithAudioMuted
|
||||
startWithAudioMuted: getStartWithAudioMuted(APP.store.getState())
|
||||
|| config.startSilent
|
||||
|| isUserInteractionRequiredForUnmute(APP.store.getState()),
|
||||
startWithVideoMuted: config.startWithVideoMuted
|
||||
startWithVideoMuted: getStartWithVideoMuted(APP.store.getState())
|
||||
|| isUserInteractionRequiredForUnmute(APP.store.getState())
|
||||
};
|
||||
|
||||
this.roomName = roomName;
|
||||
|
||||
window.addEventListener('hashchange', this.onHashChange.bind(this), false);
|
||||
|
||||
try {
|
||||
// Initialize the device list first. This way, when creating tracks
|
||||
// based on preferred devices, loose label matching can be done in
|
||||
@@ -767,6 +744,8 @@ export default {
|
||||
return c;
|
||||
});
|
||||
|
||||
APP.store.dispatch(makePrecallTest(this._getConferenceOptions()));
|
||||
|
||||
const { tryCreateLocalTracks, errors } = this.createInitialLocalTracks(initialOptions);
|
||||
const tracks = await tryCreateLocalTracks;
|
||||
|
||||
@@ -814,7 +793,7 @@ export default {
|
||||
isLocalVideoMuted() {
|
||||
// If the tracks are not ready, read from base/media state
|
||||
return this._localTracksInitialized
|
||||
? isLocalVideoTrackMuted(
|
||||
? isLocalCameraTrackMuted(
|
||||
APP.store.getState()['features/base/tracks'])
|
||||
: isVideoMutedByUser(APP.store);
|
||||
},
|
||||
@@ -1137,20 +1116,6 @@ export default {
|
||||
return room ? room.getParticipantById(id) : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get participant connection status for the participant.
|
||||
*
|
||||
* @param {string} id participant's identifier(MUC nickname)
|
||||
*
|
||||
* @returns {ParticipantConnectionStatus|null} the status of the participant
|
||||
* or null if no such participant is found or participant is the local user.
|
||||
*/
|
||||
getParticipantConnectionStatus(id) {
|
||||
const participant = this.getParticipantById(id);
|
||||
|
||||
return participant ? participant.getConnectionStatus() : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the display name foe the <tt>JitsiParticipant</tt> identified by
|
||||
* the given <tt>id</tt>.
|
||||
@@ -1221,47 +1186,8 @@ export default {
|
||||
// this can be called from console and will not have reference to this
|
||||
// that's why we reference the global var
|
||||
const logs = APP.connection.getLogs();
|
||||
const data = encodeURIComponent(JSON.stringify(logs, null, ' '));
|
||||
|
||||
const elem = document.createElement('a');
|
||||
|
||||
elem.download = filename;
|
||||
elem.href = `data:application/json;charset=utf-8,\n${data}`;
|
||||
elem.dataset.downloadurl
|
||||
= [ 'text/json', elem.download, elem.href ].join(':');
|
||||
elem.dispatchEvent(new MouseEvent('click', {
|
||||
view: window,
|
||||
bubbles: true,
|
||||
cancelable: false
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* Handled location hash change events.
|
||||
*/
|
||||
onHashChange() {
|
||||
const items = {};
|
||||
const parts = window.location.hash.substr(1).split('&');
|
||||
|
||||
for (const part of parts) {
|
||||
const param = part.split('=');
|
||||
const key = param[0];
|
||||
|
||||
if (!key) {
|
||||
continue; // eslint-disable-line no-continue
|
||||
}
|
||||
|
||||
items[key] = param[1];
|
||||
}
|
||||
|
||||
if (typeof items.e2eekey !== 'undefined') {
|
||||
APP.store.dispatch(setE2EEKey(items.e2eekey));
|
||||
|
||||
// Clean URL in browser history.
|
||||
const cleanUrl = window.location.href.split('#')[0];
|
||||
|
||||
history.replaceState(history.state, document.title, cleanUrl);
|
||||
}
|
||||
downloadJSON(logs, filename);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -1357,53 +1283,7 @@ export default {
|
||||
},
|
||||
|
||||
_getConferenceOptions() {
|
||||
const options = config;
|
||||
const { email, name: nick } = getLocalParticipant(APP.store.getState());
|
||||
|
||||
const state = APP.store.getState();
|
||||
const { locationURL } = state['features/base/connection'];
|
||||
const { tenant } = state['features/base/jwt'];
|
||||
|
||||
if (tenant) {
|
||||
options.siteID = tenant;
|
||||
}
|
||||
|
||||
if (options.enableDisplayNameInStats && nick) {
|
||||
options.statisticsDisplayName = nick;
|
||||
}
|
||||
|
||||
if (options.enableEmailInStats && email) {
|
||||
options.statisticsId = email;
|
||||
}
|
||||
|
||||
options.applicationName = interfaceConfig.APP_NAME;
|
||||
options.getWiFiStatsMethod = this._getWiFiStatsMethod;
|
||||
options.confID = `${locationURL.host}${getBackendSafePath(locationURL.pathname)}`;
|
||||
options.createVADProcessor = createRnnoiseProcessorPromise;
|
||||
|
||||
// Disable CallStats, if requessted.
|
||||
if (options.disableThirdPartyRequests) {
|
||||
delete options.callStatsID;
|
||||
delete options.callStatsSecret;
|
||||
delete options.getWiFiStatsMethod;
|
||||
}
|
||||
|
||||
return options;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the result of getWiFiStats from the global NS or does nothing
|
||||
* (returns empty result).
|
||||
* Fixes a concurrency problem where we need to pass a function when creating
|
||||
* JitsiConference, but that method is added to the context later.
|
||||
*
|
||||
* @returns {Promise}
|
||||
* @private
|
||||
*/
|
||||
_getWiFiStatsMethod() {
|
||||
const gloabalNS = getJitsiMeetGlobalNS();
|
||||
|
||||
return gloabalNS.getWiFiStats ? gloabalNS.getWiFiStats() : Promise.resolve('{}');
|
||||
return getConferenceOptions(APP.store.getState());
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -1634,9 +1514,8 @@ export default {
|
||||
if (this.videoSwitchInProgress) {
|
||||
return Promise.reject('Switch in progress.');
|
||||
}
|
||||
if (!this.isDesktopSharingEnabled) {
|
||||
return Promise.reject(
|
||||
'Cannot toggle screen sharing: not supported.');
|
||||
if (!JitsiMeetJS.isDesktopSharingEnabled()) {
|
||||
return Promise.reject('Cannot toggle screen sharing: not supported.');
|
||||
}
|
||||
|
||||
if (this.isAudioOnly()) {
|
||||
@@ -2113,7 +1992,6 @@ export default {
|
||||
formattedDisplayName
|
||||
|| interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME)
|
||||
});
|
||||
APP.UI.changeDisplayName(id, formattedDisplayName);
|
||||
}
|
||||
);
|
||||
room.on(
|
||||
@@ -2176,10 +2054,7 @@ export default {
|
||||
});
|
||||
|
||||
room.on(JitsiConferenceEvents.KICKED, participant => {
|
||||
APP.UI.hideStats();
|
||||
APP.store.dispatch(kickedOut(room, participant));
|
||||
|
||||
// FIXME close
|
||||
});
|
||||
|
||||
room.on(JitsiConferenceEvents.PARTICIPANT_KICKED, (kicker, kicked) => {
|
||||
@@ -2224,16 +2099,6 @@ export default {
|
||||
}));
|
||||
});
|
||||
|
||||
room.addCommandListener(this.commands.defaults.AVATAR_ID,
|
||||
(data, from) => {
|
||||
APP.store.dispatch(
|
||||
participantUpdated({
|
||||
conference: room,
|
||||
id: from,
|
||||
avatarID: data.value
|
||||
}));
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.NICKNAME_CHANGED,
|
||||
this.changeLocalDisplayName.bind(this));
|
||||
|
||||
@@ -2522,11 +2387,6 @@ export default {
|
||||
APP.keyboardshortcut.init();
|
||||
|
||||
APP.store.dispatch(conferenceJoined(room));
|
||||
|
||||
const displayName
|
||||
= APP.store.getState()['features/base/settings'].displayName;
|
||||
|
||||
APP.UI.changeDisplayName('localVideoContainer', displayName);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -2702,6 +2562,20 @@ export default {
|
||||
// https://bugs.chromium.org/p/chromium/issues/detail?id=997689
|
||||
const hasDefaultMicChanged = newDevices.audioinput === 'default';
|
||||
|
||||
// This is the case when the local video is muted and a preferred device is connected.
|
||||
if (requestedInput.video && this.isLocalVideoMuted()) {
|
||||
// We want to avoid creating a new video track in order to prevent turning on the camera.
|
||||
requestedInput.video = false;
|
||||
APP.store.dispatch(updateSettings({ // Update the current selected camera for the device selection dialog.
|
||||
cameraDeviceId: newDevices.videoinput
|
||||
}));
|
||||
delete newDevices.videoinput;
|
||||
|
||||
// Removing the current video track in order to force the unmute to select the preferred device.
|
||||
this.useVideoStream(null);
|
||||
|
||||
}
|
||||
|
||||
promises.push(
|
||||
mediaDeviceHelper.createLocalTracksAfterDeviceListChanged(
|
||||
createLocalTracksF,
|
||||
@@ -2858,7 +2732,14 @@ export default {
|
||||
this._room = undefined;
|
||||
room = undefined;
|
||||
|
||||
APP.API.notifyReadyToClose();
|
||||
/**
|
||||
* Don't call {@code notifyReadyToClose} if the promotional page flag is set
|
||||
* and let the page take care of sending the message, since there will be
|
||||
* a redirect to the page regardlessly.
|
||||
*/
|
||||
if (!interfaceConfig.SHOW_PROMOTIONAL_CLOSE_PAGE) {
|
||||
APP.API.notifyReadyToClose();
|
||||
}
|
||||
APP.store.dispatch(maybeRedirectToWelcomePage(values[0]));
|
||||
});
|
||||
},
|
||||
@@ -3003,10 +2884,6 @@ export default {
|
||||
APP.store.dispatch(updateSettings({
|
||||
displayName: formattedNickname
|
||||
}));
|
||||
|
||||
if (room) {
|
||||
APP.UI.changeDisplayName(id, formattedNickname);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -3116,7 +2993,7 @@ export default {
|
||||
* @param {boolean} muted - New muted status.
|
||||
*/
|
||||
setVideoMuteStatus(muted) {
|
||||
APP.UI.setVideoMuted(this.getMyUserId(), muted);
|
||||
APP.UI.setVideoMuted(this.getMyUserId());
|
||||
APP.API.notifyVideoMutedStatusChanged(muted);
|
||||
},
|
||||
|
||||
|
||||
85
config.js
85
config.js
@@ -14,9 +14,6 @@ var config = {
|
||||
// Domain for authenticated users. Defaults to <domain>.
|
||||
// authdomain: 'jitsi-meet.example.com',
|
||||
|
||||
// Jirecon recording component domain.
|
||||
// jirecon: 'jirecon.jitsi-meet.example.com',
|
||||
|
||||
// Call control component (Jigasi).
|
||||
// call_control: 'callcontrol.jitsi-meet.example.com',
|
||||
|
||||
@@ -67,6 +64,11 @@ var config = {
|
||||
// adjusted to 2.5 Mbps. This takes a value between 0 and 1 which determines
|
||||
// the probability for this to be enabled.
|
||||
// capScreenshareBitrate: 1 // 0 to disable
|
||||
|
||||
// Enable callstats only for a percentage of users.
|
||||
// This takes a value between 0 and 100 which determines the probability for
|
||||
// the callstats to be enabled.
|
||||
// callStatsThreshold: 5 // enable callstats for 5% of the users.
|
||||
},
|
||||
|
||||
// Disables ICE/UDP by filtering out local and remote UDP candidates in
|
||||
@@ -118,6 +120,9 @@ var config = {
|
||||
// Valid values are in the range 6000 to 510000
|
||||
// opusMaxAverageBitrate: 20000,
|
||||
|
||||
// Enables redundancy for Opus
|
||||
// enableOpusRed: false
|
||||
|
||||
// Video
|
||||
|
||||
// Sets the preferred resolution (height) for local video. Defaults to 720.
|
||||
@@ -125,7 +130,7 @@ var config = {
|
||||
|
||||
// How many participants while in the tile view mode, before the receiving video quality is reduced from HD to SD.
|
||||
// Use -1 to disable.
|
||||
// maxFullResolutionParticipants: 2
|
||||
// maxFullResolutionParticipants: 2,
|
||||
|
||||
// w3c spec-compliant video constraints to use for video capture. Currently
|
||||
// used by browsers that return true from lib-jitsi-meet's
|
||||
@@ -161,6 +166,7 @@ var config = {
|
||||
// Note that it's not recommended to do this because simulcast is not
|
||||
// supported when using H.264. For 1-to-1 calls this setting is enabled by
|
||||
// default and can be toggled in the p2p section.
|
||||
// This option has been deprecated, use preferredCodec under videoQuality section instead.
|
||||
// preferH264: true,
|
||||
|
||||
// If set to true, disable H.264 video codec by stripping it out of the
|
||||
@@ -234,6 +240,18 @@ var config = {
|
||||
|
||||
// Specify the settings for video quality optimizations on the client.
|
||||
// videoQuality: {
|
||||
// // Provides a way to prevent a video codec from being negotiated on the JVB connection. The codec specified
|
||||
// // here will be removed from the list of codecs present in the SDP answer generated by the client. If the
|
||||
// // same codec is specified for both the disabled and preferred option, the disable settings will prevail.
|
||||
// // Note that 'VP8' cannot be disabled since it's a mandatory codec, the setting will be ignored in this case.
|
||||
// disabledCodec: 'H264',
|
||||
//
|
||||
// // Provides a way to set a preferred video codec for the JVB connection. If 'H264' is specified here,
|
||||
// // simulcast will be automatically disabled since JVB doesn't support H264 simulcast yet. This will only
|
||||
// // rearrange the the preference order of the codecs in the SDP answer generated by the browser only if the
|
||||
// // preferred codec specified here is present. Please ensure that the JVB offers the specified codec for this
|
||||
// // to take effect.
|
||||
// preferredCodec: 'VP8',
|
||||
//
|
||||
// // Provides a way to configure the maximum bitrates that will be enforced on the simulcast streams for
|
||||
// // video tracks. The keys in the object represent the type of the stream (LD, SD or HD) and the values
|
||||
@@ -244,6 +262,21 @@ var config = {
|
||||
// low: 200000,
|
||||
// standard: 500000,
|
||||
// high: 1500000
|
||||
// },
|
||||
//
|
||||
// // The options can be used to override default thresholds of video thumbnail heights corresponding to
|
||||
// // the video quality levels used in the application. At the time of this writing the allowed levels are:
|
||||
// // 'low' - for the low quality level (180p at the time of this writing)
|
||||
// // 'standard' - for the medium quality level (360p)
|
||||
// // 'high' - for the high quality level (720p)
|
||||
// // The keys should be positive numbers which represent the minimal thumbnail height for the quality level.
|
||||
// //
|
||||
// // With the default config value below the application will use 'low' quality until the thumbnails are
|
||||
// // at least 360 pixels tall. If the thumbnail height reaches 720 pixels then the application will switch to
|
||||
// // the high quality.
|
||||
// minHeightForQualityLvl: {
|
||||
// 360: 'standard,
|
||||
// 720: 'high'
|
||||
// }
|
||||
// },
|
||||
|
||||
@@ -290,10 +323,6 @@ var config = {
|
||||
// is set in Jicofo and set to 2).
|
||||
// minParticipants: 2,
|
||||
|
||||
// Use the TURN servers discovered via XEP-0215 for the jitsi-videobridge
|
||||
// connection
|
||||
// useStunTurn: true,
|
||||
|
||||
// Use TURN/UDP servers for the jitsi-videobridge connection (by default
|
||||
// we filter out TURN/UDP because it is usually not needed since the
|
||||
// bridge itself is reachable via UDP)
|
||||
@@ -304,11 +333,15 @@ var config = {
|
||||
// 'datachannel'), undefined (treat it as 'datachannel') and false (don't
|
||||
// open any channel).
|
||||
// openBridgeChannel: true,
|
||||
openBridgeChannel: 'websocket',
|
||||
|
||||
|
||||
// UI
|
||||
//
|
||||
|
||||
// Hides lobby button
|
||||
// hideLobbyButton: false,
|
||||
|
||||
// Require users to always specify a display name.
|
||||
// requireDisplayName: true,
|
||||
|
||||
@@ -357,6 +390,10 @@ var config = {
|
||||
// set or the lobby is not enabled.
|
||||
// enableInsecureRoomNameWarning: false,
|
||||
|
||||
// Whether to automatically copy invitation URL after creating a room.
|
||||
// Document should be focused for this option to work
|
||||
// enableAutomaticUrlCopy: false,
|
||||
|
||||
// Stats
|
||||
//
|
||||
|
||||
@@ -401,9 +438,6 @@ var config = {
|
||||
// connection.
|
||||
enabled: true,
|
||||
|
||||
// Use XEP-0215 to fetch STUN and TURN servers.
|
||||
// useStunTurn: true,
|
||||
|
||||
// The STUN servers that will be used in the peer to peer connections
|
||||
stunServers: [
|
||||
|
||||
@@ -420,13 +454,20 @@ var config = {
|
||||
// iceTransportPolicy: 'all',
|
||||
|
||||
// If set to true, it will prefer to use H.264 for P2P calls (if H.264
|
||||
// is supported).
|
||||
// is supported). This setting is deprecated, use preferredCodec instead.
|
||||
// preferH264: true
|
||||
|
||||
// Provides a way to set the video codec preference on the p2p connection. Acceptable
|
||||
// codec values are 'VP8', 'VP9' and 'H264'.
|
||||
// preferredCodec: 'H264',
|
||||
|
||||
// If set to true, disable H.264 video codec by stripping it out of the
|
||||
// SDP.
|
||||
// SDP. This setting is deprecated, use disabledCodec instead.
|
||||
// disableH264: false,
|
||||
|
||||
// Provides a way to prevent a video codec from being negotiated on the p2p connection.
|
||||
// disabledCodec: '',
|
||||
|
||||
// How long we're going to wait, before going back to P2P after the 3rd
|
||||
// participant has left the conference (to filter out page reload).
|
||||
// backToP2PDelay: 5
|
||||
@@ -444,6 +485,12 @@ var config = {
|
||||
// amplitudeAPPKey: '<APP_KEY>'
|
||||
|
||||
// Configuration for the rtcstats server:
|
||||
// By enabling rtcstats server every time a conference is joined the rtcstats
|
||||
// module connects to the provided rtcstatsEndpoint and sends statistics regarding
|
||||
// PeerConnection states along with getStats metrics polled at the specified
|
||||
// interval.
|
||||
// rtcstatsEnabled: true,
|
||||
|
||||
// In order to enable rtcstats one needs to provide a endpoint url.
|
||||
// rtcstatsEndpoint: wss://rtcstats-server-pilot.jitsi.net/,
|
||||
|
||||
@@ -459,6 +506,9 @@ var config = {
|
||||
// ],
|
||||
},
|
||||
|
||||
// Logs that should go be passed through the 'log' event if a handler is defined for it
|
||||
// apiLogLevels: ['warn', 'log', 'error', 'info', 'debug'],
|
||||
|
||||
// Information about the jitsi-meet instance we are connecting to, including
|
||||
// the user region as seen by the server.
|
||||
deploymentInfo: {
|
||||
@@ -581,8 +631,6 @@ var config = {
|
||||
// List of undocumented settings used in jitsi-meet
|
||||
/**
|
||||
_immediateReloadThreshold
|
||||
autoRecord
|
||||
autoRecordToken
|
||||
debug
|
||||
debugAudioLevels
|
||||
deploymentInfo
|
||||
@@ -605,6 +653,13 @@ var config = {
|
||||
tokenAuthUrl
|
||||
*/
|
||||
|
||||
/**
|
||||
* This property can be used to alter the generated meeting invite links (in combination with a branding domain
|
||||
* which is retrieved internally by jitsi meet) (e.g. https://meet.jit.si/someMeeting
|
||||
* can become https://brandedDomain/roomAlias)
|
||||
*/
|
||||
// brandingRoomAlias: null,
|
||||
|
||||
// List of undocumented settings used in lib-jitsi-meet
|
||||
/**
|
||||
_peerConnStatusOutOfLastNTimeout
|
||||
|
||||
@@ -33,6 +33,14 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This will hide the focus indicator if an element receives focus via the mouse,
|
||||
* but it will still show up on keyboard focus, thus preserving accessibility.
|
||||
*/
|
||||
.js-focus-visible :focus:not(.focus-visible) {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* AtlasKit sets a default margin on the rendered modals, so
|
||||
* when the shift-right class is set when the chat opens, we
|
||||
|
||||
@@ -45,10 +45,8 @@
|
||||
@extend .connection-info__icon;
|
||||
}
|
||||
|
||||
.showmore {
|
||||
display: block;
|
||||
.connection-actions {
|
||||
margin: 10px auto;
|
||||
text-align: center;
|
||||
width: 90px;
|
||||
}
|
||||
}
|
||||
|
||||
84
css/_connection-status.scss
Normal file
84
css/_connection-status.scss
Normal file
@@ -0,0 +1,84 @@
|
||||
.con-status {
|
||||
position: absolute;
|
||||
top: 24px;
|
||||
width: 100%;
|
||||
z-index: $toolbarZ + 3;
|
||||
|
||||
&-container {
|
||||
border-radius: 3px;
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
line-height: 13px;
|
||||
margin: 0 auto;
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
&-header {
|
||||
background: rgba(28, 32, 37, .5);
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
&-circle {
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
padding: 4px;
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
&--good {
|
||||
background: #31B76A;
|
||||
}
|
||||
|
||||
&--poor {
|
||||
background: #E12D2D;
|
||||
}
|
||||
|
||||
&--non-optimal {
|
||||
background: #E39623;
|
||||
}
|
||||
|
||||
&-arrow {
|
||||
height: 36px;
|
||||
width: 36px;
|
||||
border-radius: 3px;
|
||||
margin-left: 8px;
|
||||
margin-right: 2px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background-color 0.16s ease-out;
|
||||
|
||||
&--up {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
&>svg {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(1,1,1, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
&-text {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&-details {
|
||||
background: rgba(28, 32, 37, .5);
|
||||
border-top: 1px solid #5E6D7A;
|
||||
padding: 16px;
|
||||
transition: opacity 0.16s ease-out;
|
||||
|
||||
&-visible {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&-hidden {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
#e2ee-section {
|
||||
.title {
|
||||
font-weight: 700;
|
||||
}
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.description {
|
||||
font-size: 13px;
|
||||
@@ -13,29 +12,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
.key-field {
|
||||
align-items: center;
|
||||
.control-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
margin-top: 15px;
|
||||
|
||||
label {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
input {
|
||||
background-color: inherit;
|
||||
border: none;
|
||||
color: inherit;
|
||||
flex: 1;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #6FB1EA;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,19 +14,6 @@
|
||||
margin: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.form {
|
||||
align-items: stretch;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
.participant-info {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,19 +87,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
align-self: stretch;
|
||||
background-color: transparent;
|
||||
border: 1px solid #B8C7E0;
|
||||
border-radius: 4px;
|
||||
color: white;
|
||||
padding: 12px 8px;
|
||||
|
||||
&:focus {
|
||||
border-color: rgb(3, 118, 218);
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
align-self: stretch;
|
||||
margin: 8px 0;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
&-input-area {
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
&-title {
|
||||
@@ -39,6 +38,18 @@
|
||||
margin-bottom: 14px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-error {
|
||||
color: white;
|
||||
background-color: rgba(225, 45, 45, 0.6);
|
||||
border-radius: 3px;
|
||||
width: 100%;
|
||||
padding: 2px;
|
||||
box-sizing: border-box;
|
||||
margin-top: 4px;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin name-placeholder {
|
||||
@@ -48,84 +59,18 @@
|
||||
}
|
||||
|
||||
.prejoin-preview {
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
|
||||
&--no-video {
|
||||
background: radial-gradient(50% 50% at 50% 50%, #5B6F80 0%, #365067 100%), #FFFFFF;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&-video {
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-name {
|
||||
color: #fff;
|
||||
font-size: 19px;
|
||||
line-height: 28px;
|
||||
|
||||
&--editable {
|
||||
background: none;
|
||||
border: 0;
|
||||
border-bottom: 1px solid #D1DBE8;
|
||||
margin: 24px 0 16px 0;
|
||||
outline: none;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
|
||||
&::-webkit-input-placeholder {
|
||||
@include name-placeholder;
|
||||
}
|
||||
&::-moz-placeholder {
|
||||
@include name-placeholder;
|
||||
}
|
||||
&:-ms-input-placeholder {
|
||||
@include name-placeholder;
|
||||
}
|
||||
}
|
||||
|
||||
&--text {
|
||||
margin: 16px 0;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-avatar.avatar {
|
||||
background: #A4B8D1;
|
||||
margin: 200px auto 0 auto;
|
||||
}
|
||||
|
||||
&-overlay {
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
background: linear-gradient(0deg, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3));
|
||||
}
|
||||
|
||||
&-bottom-overlay {
|
||||
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.9) 100%);
|
||||
bottom: 0;
|
||||
height: 50%;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&-status {
|
||||
align-items: center;
|
||||
align-self: stretch;
|
||||
bottom: 0;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
font-size: 13px;
|
||||
min-height: 24px;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
|
||||
&--warning {
|
||||
|
||||
@@ -12,12 +12,23 @@
|
||||
|
||||
.premeeting-screen {
|
||||
align-items: stretch;
|
||||
background: radial-gradient(50% 50% at 50% 50%, #5D95C7 0%, #376288 100%), #FFFFFF;
|
||||
background: radial-gradient(50% 50% at 50% 50%, #2A3A4B 20.83%, #1E2A36 100%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 1.3em;
|
||||
z-index: $toolbarZ + 1;
|
||||
|
||||
&-avatar {
|
||||
background-color: #A4B8D1;
|
||||
margin-bottom: 24px;
|
||||
|
||||
text {
|
||||
fill: black;
|
||||
font-size: 26px;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
border-radius: 3px;
|
||||
color: #fff;
|
||||
@@ -59,22 +70,26 @@
|
||||
fill: #AFB6BC;
|
||||
}
|
||||
}
|
||||
|
||||
.options {
|
||||
border-left: 1px solid #AFB6BC;
|
||||
}
|
||||
}
|
||||
|
||||
.options {
|
||||
border-radius: 3px;
|
||||
align-items: center;
|
||||
border-left: 1px solid #fff;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 40px;
|
||||
width: 36px;
|
||||
|
||||
&:hover {
|
||||
background-color: #0262B6;
|
||||
}
|
||||
|
||||
svg {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +104,7 @@
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
padding-bottom: 24px;
|
||||
z-index: $toolbarZ + 2;
|
||||
|
||||
.title {
|
||||
@@ -111,12 +127,14 @@
|
||||
margin-bottom: 16px;
|
||||
|
||||
.url {
|
||||
background: rgba(28, 32, 37, 0.5);
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
padding: 8px 10px;
|
||||
transition: background 0.16s ease-out;
|
||||
|
||||
&:hover {
|
||||
background: #1C2025;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&.done {
|
||||
@@ -149,20 +167,23 @@
|
||||
}
|
||||
|
||||
input.field {
|
||||
background-color: transparent;
|
||||
border: 1px solid transparent;
|
||||
color: white;
|
||||
outline-width: 0;
|
||||
background-color: white;
|
||||
border: none;
|
||||
outline: none;
|
||||
border-radius: 3px;
|
||||
font-size: 15px;
|
||||
line-height: 24px;
|
||||
color: #1C2025;
|
||||
padding: 8px 0;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
width: 320px;
|
||||
|
||||
&.focused {
|
||||
border-bottom: 1px solid white;
|
||||
&.error {
|
||||
box-shadow: 0px 0px 4px 3px rgba(225, 45, 45, 0.4);
|
||||
}
|
||||
|
||||
&.error::placeholder {
|
||||
color: $defaultWarningColor;
|
||||
&.focused {
|
||||
box-shadow: 0px 0px 4px 3px #0376DA;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,7 +191,7 @@
|
||||
.media-btn-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 32px 0;
|
||||
margin: 24px 0 16px 0;
|
||||
width: 100%;
|
||||
|
||||
&> div {
|
||||
@@ -197,16 +218,9 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.preview-avatar-container {
|
||||
width: 100%;
|
||||
height: 80%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
background: #A4B8D1;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
video {
|
||||
@@ -240,6 +254,7 @@
|
||||
font-size: 13px;
|
||||
height: 40px;
|
||||
margin: 0 auto;
|
||||
transition: background 0.16s ease-out;
|
||||
width: 320px;
|
||||
|
||||
@include flex-centered();
|
||||
@@ -249,7 +264,7 @@
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #1C2025;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
|
||||
@include icon-container(#A4B8D1, #1C2025);
|
||||
}
|
||||
@@ -268,14 +283,6 @@
|
||||
}
|
||||
|
||||
&--toggled {
|
||||
background: #75757A;
|
||||
|
||||
&:hover {
|
||||
background: #75757A;
|
||||
|
||||
@include icon-container(#A4B8D1, #75757A);
|
||||
}
|
||||
|
||||
@include icon-container(#A4B8D1, #75757A);
|
||||
@include icon-container(white, #1C2025);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,5 +102,6 @@ $flagsImagePath: "../images/";
|
||||
@import 'premeeting-screens';
|
||||
@import 'e2ee';
|
||||
@import 'responsive';
|
||||
@import 'connection-status';
|
||||
|
||||
/* Modules END */
|
||||
|
||||
2
debian/control
vendored
2
debian/control
vendored
@@ -47,7 +47,7 @@ Description: Prosody configuration for Jitsi Meet
|
||||
|
||||
Package: jitsi-meet-tokens
|
||||
Architecture: all
|
||||
Depends: ${misc:Depends}, prosody-trunk (>= 1nightly747) | prosody-0.11 | prosody (>= 0.11.2), libssl-dev, luarocks, jitsi-meet-prosody
|
||||
Depends: ${misc:Depends}, prosody-trunk (>= 1nightly747) | prosody-0.11 | prosody (>= 0.11.2), libssl1.0-dev | libssl-dev, luarocks, jitsi-meet-prosody, git
|
||||
Description: Prosody token authentication plugin for Jitsi Meet
|
||||
|
||||
Package: jitsi-meet-turnserver
|
||||
|
||||
8
debian/jitsi-meet-prosody.postrm
vendored
8
debian/jitsi-meet-prosody.postrm
vendored
@@ -45,8 +45,12 @@ case "$1" in
|
||||
rm -rf /var/lib/prosody/$JICOFO_AUTH_DOMAIN.*
|
||||
rm -rf /var/lib/prosody/$JVB_HOSTNAME.*
|
||||
|
||||
# clean created users
|
||||
rm -rf /var/lib/prosody/`echo $JICOFO_AUTH_DOMAIN | sed -e "s/\./%2e/g"`
|
||||
# clean created users, replace '.' with '%2e', replace '-' with '%2d'
|
||||
rm -rf /var/lib/prosody/`echo $JICOFO_AUTH_DOMAIN | sed -e "s/\./%2e/g"| sed -e "s/-/%2d/g"`
|
||||
|
||||
# clean the prosody cert from the trust store
|
||||
rm -rf /usr/local/share/ca-certificates/$JICOFO_AUTH_DOMAIN.*
|
||||
update-ca-certificates -f
|
||||
fi
|
||||
|
||||
# Clear the debconf variable
|
||||
|
||||
11
debian/jitsi-meet-tokens.postinst
vendored
11
debian/jitsi-meet-tokens.postinst
vendored
@@ -48,9 +48,9 @@ case "$1" in
|
||||
db_stop
|
||||
|
||||
if [ -f "$PROSODY_HOST_CONFIG" ] ; then
|
||||
# search for --plugin_paths, if this is not enabled this is the
|
||||
# search for the token auth, if this is not enabled this is the
|
||||
# first time we install tokens package and needs a config change
|
||||
if grep -q "\-\-plugin_paths" "$PROSODY_HOST_CONFIG"; then
|
||||
if ! egrep -q '^\s*authentication\s*=\s*"token"' "$PROSODY_HOST_CONFIG"; then
|
||||
# enable tokens in prosody host config
|
||||
sed -i 's/--plugin_paths/plugin_paths/g' $PROSODY_HOST_CONFIG
|
||||
sed -i 's/authentication = "anonymous"/authentication = "token"/g' $PROSODY_HOST_CONFIG
|
||||
@@ -58,6 +58,7 @@ case "$1" in
|
||||
sed -i "s/ --app_id=\"example_app_id\"/ app_id=\"$APP_ID\"/g" $PROSODY_HOST_CONFIG
|
||||
sed -i "s/ --app_secret=\"example_app_secret\"/ app_secret=\"$APP_SECRET\"/g" $PROSODY_HOST_CONFIG
|
||||
sed -i 's/ --modules_enabled = { "token_verification" }/ modules_enabled = { "token_verification" }/g' $PROSODY_HOST_CONFIG
|
||||
sed -i '/^\s*--\s*"token_verification"/ s/--\s*//' $PROSODY_HOST_CONFIG
|
||||
|
||||
# Install luajwt
|
||||
if ! luarocks install luajwtjitsi; then
|
||||
@@ -73,9 +74,9 @@ case "$1" in
|
||||
PRTRUNK_INSTALL_CHECK="$(dpkg-query -f '${Status}' -W 'prosody-trunk' 2>/dev/null | awk '{print $3}' || true)"
|
||||
PR_VER_INSTALLED=$(dpkg-query -f='${Version}\n' --show prosody 2>/dev/null || true)
|
||||
if [ "$PR10_INSTALL_CHECK" = "installed" ] \
|
||||
|| "$PR10_INSTALL_CHECK" = "unpacked" \
|
||||
|| "$PRTRUNK_INSTALL_CHECK" = "installed" \
|
||||
|| "$PRTRUNK_INSTALL_CHECK" = "unpacked" \
|
||||
|| [ "$PR10_INSTALL_CHECK" = "unpacked" ] \
|
||||
|| [ "$PRTRUNK_INSTALL_CHECK" = "installed" ] \
|
||||
|| [ "$PRTRUNK_INSTALL_CHECK" = "unpacked" ] \
|
||||
|| dpkg --compare-versions "$PR_VER_INSTALLED" lt "0.11" ; then
|
||||
sed -i 's/module:hook_global(/module:hook(/g' /usr/share/jitsi-meet/prosody-plugins/mod_auth_token.lua
|
||||
fi
|
||||
|
||||
3
debian/jitsi-meet-tokens.postrm
vendored
3
debian/jitsi-meet-tokens.postrm
vendored
@@ -37,11 +37,10 @@ case "$1" in
|
||||
APP_SECRET=$RET
|
||||
|
||||
# Revert prosody config
|
||||
sed -i 's/plugin_paths/--plugin_paths/g' $PROSODY_HOST_CONFIG
|
||||
sed -i 's/authentication = "token"/authentication = "anonymous"/g' $PROSODY_HOST_CONFIG
|
||||
sed -i "s/ app_id=\"$APP_ID\"/ --app_id=\"example_app_id\"/g" $PROSODY_HOST_CONFIG
|
||||
sed -i "s/ app_secret=\"$APP_SECRET\"/ --app_secret=\"example_app_secret\"/g" $PROSODY_HOST_CONFIG
|
||||
sed -i 's/ -- "token_verification"/ "token_verification"/g' $PROSODY_HOST_CONFIG
|
||||
sed -i '/^\s*"token_verification"/ s/"token_verification"/-- "token_verification"/' $PROSODY_HOST_CONFIG
|
||||
|
||||
if [ -x "/etc/init.d/prosody" ]; then
|
||||
invoke-rc.d prosody restart || true
|
||||
|
||||
55
debian/jitsi-meet-turnserver.postinst
vendored
55
debian/jitsi-meet-turnserver.postinst
vendored
@@ -36,26 +36,6 @@ case "$1" in
|
||||
NGINX_CONFIG="/etc/nginx/sites-available/$JVB_HOSTNAME.conf"
|
||||
JITSI_MEET_CONFIG="/etc/jitsi/meet/$JVB_HOSTNAME-config.js"
|
||||
|
||||
NGINX_SITES_ENABLED="/etc/nginx/sites-enabled/"
|
||||
NGINX_CONFIG_ENABLED="${NGINX_SITES_ENABLED}${JVB_HOSTNAME}.conf"
|
||||
NGINX_MULTIPLEXING="true"
|
||||
for site in ${NGINX_SITES_ENABLED}*; do
|
||||
# if it is not a file continue
|
||||
[ -f "${site}" ] || continue
|
||||
# if it is our config skip
|
||||
[ "${site}" != "${NGINX_CONFIG_ENABLED}" ] || continue
|
||||
# check whether other enabled hosts has listen 443
|
||||
if cat ${site} | grep -v "^[[:space:]]*#" | grep listen | grep -q "^.*[[:space:]:]443[;[:space:]].*" ; then
|
||||
# nothing to do
|
||||
echo "------------------------------------------------"
|
||||
echo ""
|
||||
echo "turnserver is listening on tcp 5349 as other nginx sites use port 443"
|
||||
echo ""
|
||||
echo "------------------------------------------------"
|
||||
NGINX_MULTIPLEXING="false"
|
||||
fi
|
||||
done
|
||||
|
||||
# if there was a turn config backup it so we can configure
|
||||
# we cannot recognize at the moment is this a user config or default config when installing coturn
|
||||
if [[ -f $TURN_CONFIG ]] && ! grep -q "jitsi-meet coturn config" "$TURN_CONFIG" ; then
|
||||
@@ -133,19 +113,9 @@ denied-peer-ip=240.0.0.0-255.255.255.255" >> $TURN_CONFIG
|
||||
TURN_SECRET="$RET"
|
||||
|
||||
# no turn config exists, lt's copy template and fill it in
|
||||
PUBLIC_IP=$(dig -4 +short myip.opendns.com a @resolver1.opendns.com) || true
|
||||
if [ -z "$PUBLIC_IP" ] ; then
|
||||
PUBLIC_IP="127.0.0.1"
|
||||
echo "------------------------------------------------"
|
||||
echo "Warning! Could not resolve your external ip address! Error:^"
|
||||
echo "Your turn server will not work till you edit your $TURN_CONFIG config file."
|
||||
echo "You need to set your external ip address in external-ip and restart coturn service."
|
||||
echo "------------------------------------------------"
|
||||
fi
|
||||
cp /usr/share/jitsi-meet-turnserver/turnserver.conf $TURN_CONFIG
|
||||
sed -i "s/jitsi-meet.example.com/$JVB_HOSTNAME/g" $TURN_CONFIG
|
||||
sed -i "s/__turnSecret__/$TURN_SECRET/g" $TURN_CONFIG
|
||||
sed -i "s/__external_ip_address__/$PUBLIC_IP/g" $TURN_CONFIG
|
||||
|
||||
# SSL for nginx
|
||||
db_get jitsi-meet/cert-choice
|
||||
@@ -170,23 +140,14 @@ denied-peer-ip=240.0.0.0-255.255.255.255" >> $TURN_CONFIG
|
||||
invoke-rc.d coturn restart || true
|
||||
|
||||
NGINX_STREAM_CONFIG="/etc/nginx/modules-enabled/60-jitsi-meet.conf"
|
||||
if [ $NGINX_MULTIPLEXING = "true" ] && [ ! -f $NGINX_STREAM_CONFIG ] && [ -f $NGINX_CONFIG ] ; then
|
||||
ln -s /usr/share/jitsi-meet-turnserver/jitsi-meet.conf $NGINX_STREAM_CONFIG
|
||||
sed -i "s/listen 443 ssl/listen 4444 ssl http2/g" $NGINX_CONFIG
|
||||
sed -i "s/listen \[\:\:\]\:443 ssl/listen \[\:\:\]\:4444 ssl http2/g" $NGINX_CONFIG
|
||||
invoke-rc.d nginx reload || true
|
||||
else
|
||||
PROSODY_HOST_CONFIG="/etc/prosody/conf.avail/$JVB_HOSTNAME.cfg.lua"
|
||||
if [ -f $PROSODY_HOST_CONFIG ] ; then
|
||||
# If we are not multiplexing we need to change the port in prosody config
|
||||
sed -i 's/"443"/"5349"/g' $PROSODY_HOST_CONFIG
|
||||
invoke-rc.d prosody restart || true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Enable turn server in config.js
|
||||
if [ -f $JITSI_MEET_CONFIG ] ; then
|
||||
sed -i "s/\/\/ useStunTurn: true/useStunTurn: true/g" $JITSI_MEET_CONFIG
|
||||
if [ -f $NGINX_STREAM_CONFIG ] ; then
|
||||
echo "------------------------------------------------"
|
||||
echo ""
|
||||
echo "You have multiplexing enabled, it is recommended to disable it and migrate to using websockets for the bridge channel."
|
||||
echo "The support for sctp data channels is deprecated and will be dropped at some point."
|
||||
echo "How to do it at: https://jitsi.org/multiplexing-to-bridge-ws-howto"
|
||||
echo ""
|
||||
echo "------------------------------------------------"
|
||||
fi
|
||||
|
||||
# and we're done with debconf
|
||||
|
||||
2
debian/jitsi-meet-turnserver.postrm
vendored
2
debian/jitsi-meet-turnserver.postrm
vendored
@@ -24,7 +24,6 @@ set -e
|
||||
|
||||
case "$1" in
|
||||
remove)
|
||||
rm -rf /etc/nginx/modules-enabled/60-jitsi-meet.conf
|
||||
if [ -x "/etc/init.d/nginx" ]; then
|
||||
invoke-rc.d nginx reload || true
|
||||
fi
|
||||
@@ -33,7 +32,6 @@ case "$1" in
|
||||
fi
|
||||
;;
|
||||
purge)
|
||||
rm -rf /etc/nginx/modules-enabled/60-jitsi-meet.conf
|
||||
rm -rf /etc/turnserver.conf
|
||||
if [ -x "/etc/init.d/nginx" ]; then
|
||||
invoke-rc.d nginx reload || true
|
||||
|
||||
2
debian/jitsi-meet-web.install
vendored
2
debian/jitsi-meet-web.install
vendored
@@ -13,3 +13,5 @@ lang /usr/share/jitsi-meet/
|
||||
connection_optimization /usr/share/jitsi-meet/
|
||||
resources/robots.txt /usr/share/jitsi-meet/
|
||||
resources/*.sh /usr/share/jitsi-meet/scripts/
|
||||
pwa-worker.js /usr/share/jitsi-meet/
|
||||
manifest.json /usr/share/jitsi-meet/
|
||||
|
||||
@@ -8,7 +8,7 @@ turncredentials_secret = "__turnSecret__";
|
||||
turncredentials = {
|
||||
{ type = "stun", host = "jitmeet.example.com", port = "3478" },
|
||||
{ type = "turn", host = "jitmeet.example.com", port = "3478", transport = "udp" },
|
||||
{ type = "turns", host = "jitmeet.example.com", port = "443", transport = "tcp" }
|
||||
{ type = "turns", host = "jitmeet.example.com", port = "5349", transport = "tcp" }
|
||||
};
|
||||
|
||||
cross_domain_bosh = false;
|
||||
|
||||
@@ -12,7 +12,6 @@ no-tcp-relay
|
||||
no-tcp
|
||||
listening-port=3478
|
||||
tls-listening-port=5349
|
||||
external-ip=__external_ip_address__
|
||||
no-tlsv1
|
||||
no-tlsv1_1
|
||||
# https://ssl-config.mozilla.org/#server=haproxy&version=2.1&config=intermediate&openssl=1.1.0g&guideline=5.4
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
# this is jitsi-meet nginx module configuration
|
||||
# this forward all http traffic to the nginx virtual host port
|
||||
# and the rest to the turn server
|
||||
|
||||
#
|
||||
# Multiplexing based on ALPN is DEPRECATED. ALPN does not play well with websockets on some browsers and reverse proxies.
|
||||
# To migrate away from using it read: https://jitsi.org/multiplexing-to-bridge-ws-howto
|
||||
# This file will be removed at some point and if deployment is still using it, will break.
|
||||
#
|
||||
stream {
|
||||
upstream web {
|
||||
server 127.0.0.1:4444;
|
||||
|
||||
@@ -87,6 +87,15 @@ server {
|
||||
tcp_nodelay on;
|
||||
}
|
||||
|
||||
# colibri (JVB) websockets for jvb1
|
||||
location ~ ^/colibri-ws/default-id/(.*) {
|
||||
proxy_pass http://127.0.0.1:9090/colibri-ws/default-id/$1$is_args$args;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
tcp_nodelay on;
|
||||
}
|
||||
|
||||
location ~ ^/([^/?&:'"]+)$ {
|
||||
try_files $uri @root_path;
|
||||
}
|
||||
|
||||
13
flow-typed/npm/react-redux_v7.x.x.js
vendored
13
flow-typed/npm/react-redux_v7.x.x.js
vendored
@@ -1,5 +1,5 @@
|
||||
// flow-typed signature: d2ddacbbca9700881249a9435381e689
|
||||
// flow-typed version: c6154227d1/react-redux_v7.x.x/flow_>=v0.89.x <=v0.103.x
|
||||
// flow-typed signature: 8da1e134b3de1d6f6bf9ba1cc7e2dc7e
|
||||
// flow-typed version: 387a235736/react-redux_v7.x.x/flow_>=v0.104.x
|
||||
|
||||
/**
|
||||
The order of type arguments for connect() is as follows:
|
||||
@@ -219,6 +219,7 @@ declare module "react-redux" {
|
||||
declare export class Provider<Store> extends React$Component<{
|
||||
store: Store,
|
||||
children?: React$Node,
|
||||
...
|
||||
}> {}
|
||||
|
||||
declare export function createProvider(
|
||||
@@ -237,6 +238,7 @@ declare module "react-redux" {
|
||||
shouldHandleStateChanges?: boolean,
|
||||
storeKey?: string,
|
||||
forwardRef?: boolean,
|
||||
...
|
||||
};
|
||||
|
||||
declare type SelectorFactoryOptions<Com> = {
|
||||
@@ -249,6 +251,7 @@ declare module "react-redux" {
|
||||
displayName: string,
|
||||
wrappedComponentName: string,
|
||||
WrappedComponent: Com,
|
||||
...
|
||||
};
|
||||
|
||||
declare type MapStateToPropsEx<S: Object, SP: Object, RSP: Object> = (
|
||||
@@ -275,12 +278,14 @@ declare module "react-redux" {
|
||||
OP: Object,
|
||||
CP: Object,
|
||||
EFO: Object,
|
||||
ST: { [_: $Keys<Com>]: any },
|
||||
ST: { [_: $Keys<Com>]: any, ... },
|
||||
>(
|
||||
selectorFactory: SelectorFactory<Com, D, S, OP, EFO, CP>,
|
||||
connectAdvancedOptions: ?(ConnectAdvancedOptions & EFO),
|
||||
): (component: Com) => React$ComponentType<OP> & $Shape<ST>;
|
||||
|
||||
declare export function batch(() => void): void
|
||||
|
||||
declare export default {
|
||||
Provider: typeof Provider,
|
||||
createProvider: typeof createProvider,
|
||||
@@ -289,5 +294,7 @@ declare module "react-redux" {
|
||||
useDispatch: typeof useDispatch,
|
||||
useSelector: typeof useSelector,
|
||||
useStore: typeof useStore,
|
||||
batch: typeof batch,
|
||||
...
|
||||
};
|
||||
}
|
||||
|
||||
26
index.html
26
index.html
@@ -4,11 +4,18 @@
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="content-type" content="text/html;charset=utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="theme-color" content="#2A3A4B">
|
||||
<!--#include virtual="base.html" -->
|
||||
|
||||
<link rel="apple-touch-icon" href="images/apple-touch-icon.png">
|
||||
<link rel="stylesheet" href="css/all.css">
|
||||
<link rel="manifest" id="manifest-placeholder">
|
||||
|
||||
<script>
|
||||
// Dynamically generate the manifest location URL. It must be served from the document origin, and we may have
|
||||
// the base pointing to the CDN. This way we can generate a full URL which will bypass the base.
|
||||
document.querySelector('#manifest-placeholder').setAttribute('href', window.location.origin + '/manifest.json');
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
if (!JitsiMeetJS.app) {
|
||||
return;
|
||||
@@ -17,7 +24,21 @@
|
||||
JitsiMeetJS.app.renderEntryPoint({
|
||||
Component: JitsiMeetJS.app.entryPoints.APP
|
||||
})
|
||||
})
|
||||
|
||||
const isElectron = navigator.userAgent.includes('Electron');
|
||||
const shouldRegisterWorker = !isElectron && 'serviceWorker' in navigator;
|
||||
|
||||
if (shouldRegisterWorker) {
|
||||
navigator.serviceWorker
|
||||
.register(window.location.origin + '/pwa-worker.js')
|
||||
.then(reg => {
|
||||
console.log('Service worker registered.', reg);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
// IE11 and earlier can be identified via their user agent and be
|
||||
@@ -164,6 +185,9 @@
|
||||
<!--#include virtual="static/settingsToolbarAdditionalContent.html" -->
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<div>JavaScript is disabled. </br>For this site to work you have to enable JavaScript.</div>
|
||||
</noscript>
|
||||
<!--#include virtual="body.html" -->
|
||||
<div id="react"></div>
|
||||
</body>
|
||||
|
||||
@@ -5,10 +5,9 @@ require_relative '../node_modules/@react-native-community/cli-platform-ios/nativ
|
||||
target 'jitsi-meet' do
|
||||
project 'app/app.xcodeproj'
|
||||
|
||||
pod 'Crashlytics', '~> 3.14.0'
|
||||
pod 'Fabric', '~> 1.10.2'
|
||||
pod 'Firebase/Core', '~> 6.16.0'
|
||||
pod 'Firebase/DynamicLinks', '~> 6.16.0'
|
||||
pod 'Firebase/Analytics', '~> 6.33.0'
|
||||
pod 'Firebase/Crashlytics', '~> 6.33.0'
|
||||
pod 'Firebase/DynamicLinks', '~> 6.33.0'
|
||||
end
|
||||
|
||||
target 'JitsiMeet' do
|
||||
@@ -67,6 +66,7 @@ target 'JitsiMeet' do
|
||||
pod 'RNSVG', :path => '../node_modules/react-native-svg'
|
||||
pod 'RNWatch', :path => '../node_modules/react-native-watch-connectivity'
|
||||
pod 'RNDefaultPreference', :path => '../node_modules/react-native-default-preference'
|
||||
pod 'react-native-splash-screen', :path => '../node_modules/react-native-splash-screen'
|
||||
|
||||
# Native pod dependencies
|
||||
#
|
||||
|
||||
529
ios/Podfile.lock
529
ios/Podfile.lock
@@ -11,60 +11,59 @@ PODS:
|
||||
- CocoaLumberjack (3.5.3):
|
||||
- CocoaLumberjack/Core (= 3.5.3)
|
||||
- CocoaLumberjack/Core (3.5.3)
|
||||
- Crashlytics (3.14.0):
|
||||
- Fabric (~> 1.10.2)
|
||||
- DoubleConversion (1.1.6)
|
||||
- Fabric (1.10.2)
|
||||
- FBLazyVector (0.61.5-jitsi.1)
|
||||
- FBReactNativeSpec (0.61.5-jitsi.1):
|
||||
- FBLazyVector (0.61.5-jitsi.2)
|
||||
- FBReactNativeSpec (0.61.5-jitsi.2):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- RCTRequired (= 0.61.5-jitsi.1)
|
||||
- RCTTypeSafety (= 0.61.5-jitsi.1)
|
||||
- React-Core (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- ReactCommon/turbomodule/core (= 0.61.5-jitsi.1)
|
||||
- Firebase/Core (6.16.0):
|
||||
- RCTRequired (= 0.61.5-jitsi.2)
|
||||
- RCTTypeSafety (= 0.61.5-jitsi.2)
|
||||
- React-Core (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- ReactCommon/turbomodule/core (= 0.61.5-jitsi.2)
|
||||
- Firebase/Analytics (6.33.0):
|
||||
- Firebase/Core
|
||||
- Firebase/Core (6.33.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseAnalytics (= 6.2.2)
|
||||
- Firebase/CoreOnly (6.16.0):
|
||||
- FirebaseCore (= 6.6.1)
|
||||
- Firebase/DynamicLinks (6.16.0):
|
||||
- FirebaseAnalytics (= 6.8.3)
|
||||
- Firebase/CoreOnly (6.33.0):
|
||||
- FirebaseCore (= 6.10.3)
|
||||
- Firebase/Crashlytics (6.33.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseDynamicLinks (~> 4.0.6)
|
||||
- FirebaseAnalytics (6.2.2):
|
||||
- FirebaseCore (~> 6.6)
|
||||
- FirebaseInstanceID (~> 4.3)
|
||||
- GoogleAppMeasurement (= 6.2.2)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 6.0)
|
||||
- GoogleUtilities/MethodSwizzler (~> 6.0)
|
||||
- GoogleUtilities/Network (~> 6.0)
|
||||
- "GoogleUtilities/NSData+zlib (~> 6.0)"
|
||||
- nanopb (= 0.3.9011)
|
||||
- FirebaseAnalyticsInterop (1.5.0)
|
||||
- FirebaseCore (6.6.1):
|
||||
- FirebaseCoreDiagnostics (~> 1.2)
|
||||
- FirebaseCoreDiagnosticsInterop (~> 1.2)
|
||||
- GoogleUtilities/Environment (~> 6.5)
|
||||
- GoogleUtilities/Logger (~> 6.5)
|
||||
- FirebaseCoreDiagnostics (1.2.2):
|
||||
- FirebaseCoreDiagnosticsInterop (~> 1.2)
|
||||
- GoogleDataTransportCCTSupport (~> 2.0)
|
||||
- GoogleUtilities/Environment (~> 6.5)
|
||||
- GoogleUtilities/Logger (~> 6.5)
|
||||
- nanopb (~> 0.3.901)
|
||||
- FirebaseCoreDiagnosticsInterop (1.2.0)
|
||||
- FirebaseDynamicLinks (4.0.8):
|
||||
- FirebaseAnalyticsInterop (~> 1.3)
|
||||
- FirebaseCore (~> 6.2)
|
||||
- FirebaseInstallations (1.1.1):
|
||||
- FirebaseCore (~> 6.6)
|
||||
- GoogleUtilities/UserDefaults (~> 6.5)
|
||||
- FirebaseCrashlytics (~> 4.6.1)
|
||||
- Firebase/DynamicLinks (6.33.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseDynamicLinks (~> 4.3.1)
|
||||
- FirebaseAnalytics (6.8.3):
|
||||
- FirebaseCore (~> 6.10)
|
||||
- FirebaseInstallations (~> 1.6)
|
||||
- GoogleAppMeasurement (= 6.8.3)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 6.7)
|
||||
- GoogleUtilities/MethodSwizzler (~> 6.7)
|
||||
- GoogleUtilities/Network (~> 6.7)
|
||||
- "GoogleUtilities/NSData+zlib (~> 6.7)"
|
||||
- nanopb (~> 1.30906.0)
|
||||
- FirebaseCore (6.10.3):
|
||||
- FirebaseCoreDiagnostics (~> 1.6)
|
||||
- GoogleUtilities/Environment (~> 6.7)
|
||||
- GoogleUtilities/Logger (~> 6.7)
|
||||
- FirebaseCoreDiagnostics (1.7.0):
|
||||
- GoogleDataTransport (~> 7.4)
|
||||
- GoogleUtilities/Environment (~> 6.7)
|
||||
- GoogleUtilities/Logger (~> 6.7)
|
||||
- nanopb (~> 1.30906.0)
|
||||
- FirebaseCrashlytics (4.6.1):
|
||||
- FirebaseCore (~> 6.10)
|
||||
- FirebaseInstallations (~> 1.6)
|
||||
- GoogleDataTransport (~> 7.2)
|
||||
- nanopb (~> 1.30906.0)
|
||||
- PromisesObjC (~> 1.2)
|
||||
- FirebaseDynamicLinks (4.3.1):
|
||||
- FirebaseCore (~> 6.10)
|
||||
- FirebaseInstallations (1.7.0):
|
||||
- FirebaseCore (~> 6.10)
|
||||
- GoogleUtilities/Environment (~> 6.7)
|
||||
- GoogleUtilities/UserDefaults (~> 6.7)
|
||||
- PromisesObjC (~> 1.2)
|
||||
- FirebaseInstanceID (4.3.2):
|
||||
- FirebaseCore (~> 6.6)
|
||||
- FirebaseInstallations (~> 1.0)
|
||||
- GoogleUtilities/Environment (~> 6.5)
|
||||
- GoogleUtilities/UserDefaults (~> 6.5)
|
||||
- Folly (2018.10.22.00):
|
||||
- boost-for-react-native
|
||||
- DoubleConversion
|
||||
@@ -75,37 +74,36 @@ PODS:
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- glog (0.3.5)
|
||||
- GoogleAppMeasurement (6.2.2):
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 6.0)
|
||||
- GoogleUtilities/MethodSwizzler (~> 6.0)
|
||||
- GoogleUtilities/Network (~> 6.0)
|
||||
- "GoogleUtilities/NSData+zlib (~> 6.0)"
|
||||
- nanopb (= 0.3.9011)
|
||||
- GoogleDataTransport (5.1.0)
|
||||
- GoogleDataTransportCCTSupport (2.0.1):
|
||||
- GoogleDataTransport (~> 5.1)
|
||||
- nanopb (~> 0.3.901)
|
||||
- GoogleAppMeasurement (6.8.3):
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 6.7)
|
||||
- GoogleUtilities/MethodSwizzler (~> 6.7)
|
||||
- GoogleUtilities/Network (~> 6.7)
|
||||
- "GoogleUtilities/NSData+zlib (~> 6.7)"
|
||||
- nanopb (~> 1.30906.0)
|
||||
- GoogleDataTransport (7.4.0):
|
||||
- nanopb (~> 1.30906.0)
|
||||
- GoogleSignIn (5.0.1):
|
||||
- AppAuth (~> 1.2)
|
||||
- GTMAppAuth (~> 1.0)
|
||||
- GTMSessionFetcher/Core (~> 1.1)
|
||||
- GoogleUtilities/AppDelegateSwizzler (6.5.2):
|
||||
- GoogleUtilities/AppDelegateSwizzler (6.7.2):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Network
|
||||
- GoogleUtilities/Environment (6.5.2)
|
||||
- GoogleUtilities/Logger (6.5.2):
|
||||
- GoogleUtilities/Environment (6.7.2):
|
||||
- PromisesObjC (~> 1.2)
|
||||
- GoogleUtilities/Logger (6.7.2):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/MethodSwizzler (6.5.2):
|
||||
- GoogleUtilities/MethodSwizzler (6.7.2):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Network (6.5.2):
|
||||
- GoogleUtilities/Network (6.7.2):
|
||||
- GoogleUtilities/Logger
|
||||
- "GoogleUtilities/NSData+zlib"
|
||||
- GoogleUtilities/Reachability
|
||||
- "GoogleUtilities/NSData+zlib (6.5.2)"
|
||||
- GoogleUtilities/Reachability (6.5.2):
|
||||
- "GoogleUtilities/NSData+zlib (6.7.2)"
|
||||
- GoogleUtilities/Reachability (6.7.2):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/UserDefaults (6.5.2):
|
||||
- GoogleUtilities/UserDefaults (6.7.2):
|
||||
- GoogleUtilities/Logger
|
||||
- GTMAppAuth (1.0.0):
|
||||
- AppAuth/Core (~> 1.0)
|
||||
@@ -115,177 +113,177 @@ PODS:
|
||||
- GTMSessionFetcher/Core (1.2.2)
|
||||
- GTMSessionFetcher/Full (1.2.2):
|
||||
- GTMSessionFetcher/Core (= 1.2.2)
|
||||
- nanopb (0.3.9011):
|
||||
- nanopb/decode (= 0.3.9011)
|
||||
- nanopb/encode (= 0.3.9011)
|
||||
- nanopb/decode (0.3.9011)
|
||||
- nanopb/encode (0.3.9011)
|
||||
- nanopb (1.30906.0):
|
||||
- nanopb/decode (= 1.30906.0)
|
||||
- nanopb/encode (= 1.30906.0)
|
||||
- nanopb/decode (1.30906.0)
|
||||
- nanopb/encode (1.30906.0)
|
||||
- ObjectiveDropboxOfficial (3.9.4)
|
||||
- PromisesObjC (1.2.8)
|
||||
- RCTRequired (0.61.5-jitsi.1)
|
||||
- RCTTypeSafety (0.61.5-jitsi.1):
|
||||
- FBLazyVector (= 0.61.5-jitsi.1)
|
||||
- PromisesObjC (1.2.10)
|
||||
- RCTRequired (0.61.5-jitsi.2)
|
||||
- RCTTypeSafety (0.61.5-jitsi.2):
|
||||
- FBLazyVector (= 0.61.5-jitsi.2)
|
||||
- Folly (= 2018.10.22.00)
|
||||
- RCTRequired (= 0.61.5-jitsi.1)
|
||||
- React-Core (= 0.61.5-jitsi.1)
|
||||
- React (0.61.5-jitsi.1):
|
||||
- React-Core (= 0.61.5-jitsi.1)
|
||||
- React-Core/DevSupport (= 0.61.5-jitsi.1)
|
||||
- React-Core/RCTWebSocket (= 0.61.5-jitsi.1)
|
||||
- React-RCTActionSheet (= 0.61.5-jitsi.1)
|
||||
- React-RCTAnimation (= 0.61.5-jitsi.1)
|
||||
- React-RCTBlob (= 0.61.5-jitsi.1)
|
||||
- React-RCTImage (= 0.61.5-jitsi.1)
|
||||
- React-RCTLinking (= 0.61.5-jitsi.1)
|
||||
- React-RCTNetwork (= 0.61.5-jitsi.1)
|
||||
- React-RCTSettings (= 0.61.5-jitsi.1)
|
||||
- React-RCTText (= 0.61.5-jitsi.1)
|
||||
- React-RCTVibration (= 0.61.5-jitsi.1)
|
||||
- React-Core (0.61.5-jitsi.1):
|
||||
- RCTRequired (= 0.61.5-jitsi.2)
|
||||
- React-Core (= 0.61.5-jitsi.2)
|
||||
- React (0.61.5-jitsi.2):
|
||||
- React-Core (= 0.61.5-jitsi.2)
|
||||
- React-Core/DevSupport (= 0.61.5-jitsi.2)
|
||||
- React-Core/RCTWebSocket (= 0.61.5-jitsi.2)
|
||||
- React-RCTActionSheet (= 0.61.5-jitsi.2)
|
||||
- React-RCTAnimation (= 0.61.5-jitsi.2)
|
||||
- React-RCTBlob (= 0.61.5-jitsi.2)
|
||||
- React-RCTImage (= 0.61.5-jitsi.2)
|
||||
- React-RCTLinking (= 0.61.5-jitsi.2)
|
||||
- React-RCTNetwork (= 0.61.5-jitsi.2)
|
||||
- React-RCTSettings (= 0.61.5-jitsi.2)
|
||||
- React-RCTText (= 0.61.5-jitsi.2)
|
||||
- React-RCTVibration (= 0.61.5-jitsi.2)
|
||||
- React-Core (0.61.5-jitsi.2):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default (= 0.61.5-jitsi.1)
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.1)
|
||||
- React-Core/Default (= 0.61.5-jitsi.2)
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.2)
|
||||
- Yoga
|
||||
- React-Core/CoreModulesHeaders (0.61.5-jitsi.1):
|
||||
- React-Core/CoreModulesHeaders (0.61.5-jitsi.2):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.1)
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.2)
|
||||
- Yoga
|
||||
- React-Core/Default (0.61.5-jitsi.1):
|
||||
- React-Core/Default (0.61.5-jitsi.2):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.1)
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.2)
|
||||
- Yoga
|
||||
- React-Core/DevSupport (0.61.5-jitsi.1):
|
||||
- React-Core/DevSupport (0.61.5-jitsi.2):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default (= 0.61.5-jitsi.1)
|
||||
- React-Core/RCTWebSocket (= 0.61.5-jitsi.1)
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.1)
|
||||
- React-jsinspector (= 0.61.5-jitsi.1)
|
||||
- React-Core/Default (= 0.61.5-jitsi.2)
|
||||
- React-Core/RCTWebSocket (= 0.61.5-jitsi.2)
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.2)
|
||||
- React-jsinspector (= 0.61.5-jitsi.2)
|
||||
- Yoga
|
||||
- React-Core/RCTActionSheetHeaders (0.61.5-jitsi.1):
|
||||
- React-Core/RCTActionSheetHeaders (0.61.5-jitsi.2):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.1)
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.2)
|
||||
- Yoga
|
||||
- React-Core/RCTAnimationHeaders (0.61.5-jitsi.1):
|
||||
- React-Core/RCTAnimationHeaders (0.61.5-jitsi.2):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.1)
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.2)
|
||||
- Yoga
|
||||
- React-Core/RCTBlobHeaders (0.61.5-jitsi.1):
|
||||
- React-Core/RCTBlobHeaders (0.61.5-jitsi.2):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.1)
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.2)
|
||||
- Yoga
|
||||
- React-Core/RCTImageHeaders (0.61.5-jitsi.1):
|
||||
- React-Core/RCTImageHeaders (0.61.5-jitsi.2):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.1)
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.2)
|
||||
- Yoga
|
||||
- React-Core/RCTLinkingHeaders (0.61.5-jitsi.1):
|
||||
- React-Core/RCTLinkingHeaders (0.61.5-jitsi.2):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.1)
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.2)
|
||||
- Yoga
|
||||
- React-Core/RCTNetworkHeaders (0.61.5-jitsi.1):
|
||||
- React-Core/RCTNetworkHeaders (0.61.5-jitsi.2):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.1)
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.2)
|
||||
- Yoga
|
||||
- React-Core/RCTSettingsHeaders (0.61.5-jitsi.1):
|
||||
- React-Core/RCTSettingsHeaders (0.61.5-jitsi.2):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.1)
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.2)
|
||||
- Yoga
|
||||
- React-Core/RCTTextHeaders (0.61.5-jitsi.1):
|
||||
- React-Core/RCTTextHeaders (0.61.5-jitsi.2):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.1)
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.2)
|
||||
- Yoga
|
||||
- React-Core/RCTVibrationHeaders (0.61.5-jitsi.1):
|
||||
- React-Core/RCTVibrationHeaders (0.61.5-jitsi.2):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.1)
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.2)
|
||||
- Yoga
|
||||
- React-Core/RCTWebSocket (0.61.5-jitsi.1):
|
||||
- React-Core/RCTWebSocket (0.61.5-jitsi.2):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core/Default (= 0.61.5-jitsi.1)
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.1)
|
||||
- React-Core/Default (= 0.61.5-jitsi.2)
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- React-jsiexecutor (= 0.61.5-jitsi.2)
|
||||
- Yoga
|
||||
- React-CoreModules (0.61.5-jitsi.1):
|
||||
- FBReactNativeSpec (= 0.61.5-jitsi.1)
|
||||
- React-CoreModules (0.61.5-jitsi.2):
|
||||
- FBReactNativeSpec (= 0.61.5-jitsi.2)
|
||||
- Folly (= 2018.10.22.00)
|
||||
- RCTTypeSafety (= 0.61.5-jitsi.1)
|
||||
- React-Core/CoreModulesHeaders (= 0.61.5-jitsi.1)
|
||||
- React-RCTImage (= 0.61.5-jitsi.1)
|
||||
- ReactCommon/turbomodule/core (= 0.61.5-jitsi.1)
|
||||
- React-cxxreact (0.61.5-jitsi.1):
|
||||
- RCTTypeSafety (= 0.61.5-jitsi.2)
|
||||
- React-Core/CoreModulesHeaders (= 0.61.5-jitsi.2)
|
||||
- React-RCTImage (= 0.61.5-jitsi.2)
|
||||
- ReactCommon/turbomodule/core (= 0.61.5-jitsi.2)
|
||||
- React-cxxreact (0.61.5-jitsi.2):
|
||||
- boost-for-react-native (= 1.63.0)
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-jsinspector (= 0.61.5-jitsi.1)
|
||||
- React-jsi (0.61.5-jitsi.1):
|
||||
- React-jsinspector (= 0.61.5-jitsi.2)
|
||||
- React-jsi (0.61.5-jitsi.2):
|
||||
- boost-for-react-native (= 1.63.0)
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-jsi/Default (= 0.61.5-jitsi.1)
|
||||
- React-jsi/Default (0.61.5-jitsi.1):
|
||||
- React-jsi/Default (= 0.61.5-jitsi.2)
|
||||
- React-jsi/Default (0.61.5-jitsi.2):
|
||||
- boost-for-react-native (= 1.63.0)
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-jsiexecutor (0.61.5-jitsi.1):
|
||||
- React-jsiexecutor (0.61.5-jitsi.2):
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- React-jsinspector (0.61.5-jitsi.1)
|
||||
- react-native-background-timer (2.1.1):
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- React-jsinspector (0.61.5-jitsi.2)
|
||||
- react-native-background-timer (2.4.0):
|
||||
- React
|
||||
- react-native-calendar-events (2.0.0):
|
||||
- React
|
||||
@@ -293,64 +291,66 @@ PODS:
|
||||
- React
|
||||
- react-native-netinfo (4.1.5):
|
||||
- React
|
||||
- react-native-webrtc (1.84.0):
|
||||
- react-native-splash-screen (3.2.0):
|
||||
- React
|
||||
- react-native-webview (7.4.1):
|
||||
- react-native-webrtc (1.84.1):
|
||||
- React-Core
|
||||
- react-native-webview (10.9.0):
|
||||
- React
|
||||
- React-RCTActionSheet (0.61.5-jitsi.1):
|
||||
- React-Core/RCTActionSheetHeaders (= 0.61.5-jitsi.1)
|
||||
- React-RCTAnimation (0.61.5-jitsi.1):
|
||||
- React-Core/RCTAnimationHeaders (= 0.61.5-jitsi.1)
|
||||
- React-RCTBlob (0.61.5-jitsi.1):
|
||||
- React-Core/RCTBlobHeaders (= 0.61.5-jitsi.1)
|
||||
- React-Core/RCTWebSocket (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- React-RCTNetwork (= 0.61.5-jitsi.1)
|
||||
- React-RCTImage (0.61.5-jitsi.1):
|
||||
- React-Core/RCTImageHeaders (= 0.61.5-jitsi.1)
|
||||
- React-RCTNetwork (= 0.61.5-jitsi.1)
|
||||
- React-RCTLinking (0.61.5-jitsi.1):
|
||||
- React-Core/RCTLinkingHeaders (= 0.61.5-jitsi.1)
|
||||
- React-RCTNetwork (0.61.5-jitsi.1):
|
||||
- React-Core/RCTNetworkHeaders (= 0.61.5-jitsi.1)
|
||||
- React-RCTSettings (0.61.5-jitsi.1):
|
||||
- React-Core/RCTSettingsHeaders (= 0.61.5-jitsi.1)
|
||||
- React-RCTText (0.61.5-jitsi.1):
|
||||
- React-Core/RCTTextHeaders (= 0.61.5-jitsi.1)
|
||||
- React-RCTVibration (0.61.5-jitsi.1):
|
||||
- React-Core/RCTVibrationHeaders (= 0.61.5-jitsi.1)
|
||||
- ReactCommon/jscallinvoker (0.61.5-jitsi.1):
|
||||
- React-RCTActionSheet (0.61.5-jitsi.2):
|
||||
- React-Core/RCTActionSheetHeaders (= 0.61.5-jitsi.2)
|
||||
- React-RCTAnimation (0.61.5-jitsi.2):
|
||||
- React-Core/RCTAnimationHeaders (= 0.61.5-jitsi.2)
|
||||
- React-RCTBlob (0.61.5-jitsi.2):
|
||||
- React-Core/RCTBlobHeaders (= 0.61.5-jitsi.2)
|
||||
- React-Core/RCTWebSocket (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- React-RCTNetwork (= 0.61.5-jitsi.2)
|
||||
- React-RCTImage (0.61.5-jitsi.2):
|
||||
- React-Core/RCTImageHeaders (= 0.61.5-jitsi.2)
|
||||
- React-RCTNetwork (= 0.61.5-jitsi.2)
|
||||
- React-RCTLinking (0.61.5-jitsi.2):
|
||||
- React-Core/RCTLinkingHeaders (= 0.61.5-jitsi.2)
|
||||
- React-RCTNetwork (0.61.5-jitsi.2):
|
||||
- React-Core/RCTNetworkHeaders (= 0.61.5-jitsi.2)
|
||||
- React-RCTSettings (0.61.5-jitsi.2):
|
||||
- React-Core/RCTSettingsHeaders (= 0.61.5-jitsi.2)
|
||||
- React-RCTText (0.61.5-jitsi.2):
|
||||
- React-Core/RCTTextHeaders (= 0.61.5-jitsi.2)
|
||||
- React-RCTVibration (0.61.5-jitsi.2):
|
||||
- React-Core/RCTVibrationHeaders (= 0.61.5-jitsi.2)
|
||||
- ReactCommon/jscallinvoker (0.61.5-jitsi.2):
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- ReactCommon/turbomodule (0.61.5-jitsi.1):
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- ReactCommon/turbomodule (0.61.5-jitsi.2):
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core (= 0.61.5-jitsi.1)
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- ReactCommon/jscallinvoker (= 0.61.5-jitsi.1)
|
||||
- ReactCommon/turbomodule/core (= 0.61.5-jitsi.1)
|
||||
- ReactCommon/turbomodule/samples (= 0.61.5-jitsi.1)
|
||||
- ReactCommon/turbomodule/core (0.61.5-jitsi.1):
|
||||
- React-Core (= 0.61.5-jitsi.2)
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- ReactCommon/jscallinvoker (= 0.61.5-jitsi.2)
|
||||
- ReactCommon/turbomodule/core (= 0.61.5-jitsi.2)
|
||||
- ReactCommon/turbomodule/samples (= 0.61.5-jitsi.2)
|
||||
- ReactCommon/turbomodule/core (0.61.5-jitsi.2):
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core (= 0.61.5-jitsi.1)
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- ReactCommon/jscallinvoker (= 0.61.5-jitsi.1)
|
||||
- ReactCommon/turbomodule/samples (0.61.5-jitsi.1):
|
||||
- React-Core (= 0.61.5-jitsi.2)
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- ReactCommon/jscallinvoker (= 0.61.5-jitsi.2)
|
||||
- ReactCommon/turbomodule/samples (0.61.5-jitsi.2):
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React-Core (= 0.61.5-jitsi.1)
|
||||
- React-cxxreact (= 0.61.5-jitsi.1)
|
||||
- React-jsi (= 0.61.5-jitsi.1)
|
||||
- ReactCommon/jscallinvoker (= 0.61.5-jitsi.1)
|
||||
- ReactCommon/turbomodule/core (= 0.61.5-jitsi.1)
|
||||
- React-Core (= 0.61.5-jitsi.2)
|
||||
- React-cxxreact (= 0.61.5-jitsi.2)
|
||||
- React-jsi (= 0.61.5-jitsi.2)
|
||||
- ReactCommon/jscallinvoker (= 0.61.5-jitsi.2)
|
||||
- ReactCommon/turbomodule/core (= 0.61.5-jitsi.2)
|
||||
- RNCAsyncStorage (1.3.4):
|
||||
- React
|
||||
- RNDefaultPreference (1.4.2):
|
||||
@@ -363,7 +363,7 @@ PODS:
|
||||
- RNSound/Core (= 0.11.0)
|
||||
- RNSound/Core (0.11.0):
|
||||
- React
|
||||
- RNSVG (9.7.1):
|
||||
- RNSVG (10.1.0):
|
||||
- React
|
||||
- RNWatch (0.4.3):
|
||||
- React
|
||||
@@ -373,13 +373,12 @@ DEPENDENCIES:
|
||||
- Amplitude-iOS (~> 4.0.4)
|
||||
- BVLinearGradient (from `../node_modules/react-native-linear-gradient`)
|
||||
- CocoaLumberjack (~> 3.5.3)
|
||||
- Crashlytics (~> 3.14.0)
|
||||
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
|
||||
- Fabric (~> 1.10.2)
|
||||
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector/`)
|
||||
- FBReactNativeSpec (from `../node_modules/react-native/Libraries/FBReactNativeSpec/`)
|
||||
- Firebase/Core (~> 6.16.0)
|
||||
- Firebase/DynamicLinks (~> 6.16.0)
|
||||
- Firebase/Analytics (~> 6.33.0)
|
||||
- Firebase/Crashlytics (~> 6.33.0)
|
||||
- Firebase/DynamicLinks (~> 6.33.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)
|
||||
@@ -398,6 +397,7 @@ DEPENDENCIES:
|
||||
- react-native-calendar-events (from `../node_modules/react-native-calendar-events`)
|
||||
- react-native-keep-awake (from `../node_modules/react-native-keep-awake`)
|
||||
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
|
||||
- react-native-splash-screen (from `../node_modules/react-native-splash-screen`)
|
||||
- react-native-webrtc (from `../node_modules/react-native-webrtc`)
|
||||
- react-native-webview (from `../node_modules/react-native-webview`)
|
||||
- React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
|
||||
@@ -424,20 +424,15 @@ SPEC REPOS:
|
||||
- AppAuth
|
||||
- boost-for-react-native
|
||||
- CocoaLumberjack
|
||||
- Crashlytics
|
||||
- Fabric
|
||||
- Firebase
|
||||
- FirebaseAnalytics
|
||||
- FirebaseAnalyticsInterop
|
||||
- FirebaseCore
|
||||
- FirebaseCoreDiagnostics
|
||||
- FirebaseCoreDiagnosticsInterop
|
||||
- FirebaseCrashlytics
|
||||
- FirebaseDynamicLinks
|
||||
- FirebaseInstallations
|
||||
- FirebaseInstanceID
|
||||
- GoogleAppMeasurement
|
||||
- GoogleDataTransport
|
||||
- GoogleDataTransportCCTSupport
|
||||
- GoogleSignIn
|
||||
- GoogleUtilities
|
||||
- GTMAppAuth
|
||||
@@ -485,6 +480,8 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native-keep-awake"
|
||||
react-native-netinfo:
|
||||
:path: "../node_modules/@react-native-community/netinfo"
|
||||
react-native-splash-screen:
|
||||
:path: "../node_modules/react-native-splash-screen"
|
||||
react-native-webrtc:
|
||||
:path: "../node_modules/react-native-webrtc"
|
||||
react-native-webview:
|
||||
@@ -530,65 +527,61 @@ SPEC CHECKSUMS:
|
||||
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
|
||||
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
|
||||
CocoaLumberjack: 2f44e60eb91c176d471fdba43b9e3eae6a721947
|
||||
Crashlytics: 540b7e5f5da5a042647227a5e3ac51d85eed06df
|
||||
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
|
||||
Fabric: 706c8b8098fff96c33c0db69cbf81f9c551d0d74
|
||||
FBLazyVector: 4a5251159a3ed05dc11cc8b74cf937869935814b
|
||||
FBReactNativeSpec: 6fa602a20993212cc9877a81838578ffb0008bc9
|
||||
Firebase: 497158b816d0a86fc31babbd05546fcd7e6083ff
|
||||
FirebaseAnalytics: cf95d3aab897612783020fbd98401d5366f135ee
|
||||
FirebaseAnalyticsInterop: 3f86269c38ae41f47afeb43ebf32a001f58fcdae
|
||||
FirebaseCore: 85064903ed6c28e47fec9c7bd149d94ba1b6b6e7
|
||||
FirebaseCoreDiagnostics: e9b4cd8ba60dee0f2d13347332e4b7898cca5b61
|
||||
FirebaseCoreDiagnosticsInterop: 296e2c5f5314500a850ad0b83e9e7c10b011a850
|
||||
FirebaseDynamicLinks: 417dc6dbb6013233c77558290d73296f429656a6
|
||||
FirebaseInstallations: acb3216eb9784d3b1d2d2d635ff74fa892cc0c44
|
||||
FirebaseInstanceID: 7ee0d6777013bb952f377b41965bf132b6a075be
|
||||
FBLazyVector: ca7f56c8ff6cd8590f7a673d7903b06019805581
|
||||
FBReactNativeSpec: 8136c3cf27de2bb310a69cffbb423c5643f5c1c4
|
||||
Firebase: 8db6f2d1b2c5e2984efba4949a145875a8f65fe5
|
||||
FirebaseAnalytics: 5dd088bd2e67bb9d13dbf792d1164ceaf3052193
|
||||
FirebaseCore: d889d9e12535b7f36ac8bfbf1713a0836a3012cd
|
||||
FirebaseCoreDiagnostics: 770ac5958e1372ce67959ae4b4f31d8e127c3ac1
|
||||
FirebaseCrashlytics: 5777d3462fb8c3ab9e80a2473bd7d667a2e8411c
|
||||
FirebaseDynamicLinks: 6eac37d86910382eafb6315d952cc44c9e176094
|
||||
FirebaseInstallations: 466c7b4d1f58fe16707693091da253726a731ed2
|
||||
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
|
||||
glog: 1f3da668190260b06b429bb211bfbee5cd790c28
|
||||
GoogleAppMeasurement: d0560d915abf15e692e8538ba1d58442217b6aff
|
||||
GoogleDataTransport: b29a21d813e906014ca16c00897827e40e4a24ab
|
||||
GoogleDataTransportCCTSupport: 6f15a89b0ca35d6fa523e1f752ef818588885988
|
||||
GoogleAppMeasurement: 966e88df9d19c15715137bb2ddaf52373f111436
|
||||
GoogleDataTransport: b7f406340a291370045a270c599e53c6fa6ec20f
|
||||
GoogleSignIn: 3a51b9bb8e48b635fd7f4272cee06ca260345b86
|
||||
GoogleUtilities: ad0f3b691c67909d03a3327cc205222ab8f42e0e
|
||||
GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3
|
||||
GTMAppAuth: 4deac854479704f348309e7b66189e604cf5e01e
|
||||
GTMSessionFetcher: 61bb0f61a4cb560030f1222021178008a5727a23
|
||||
nanopb: 18003b5e52dab79db540fe93fe9579f399bd1ccd
|
||||
nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc
|
||||
ObjectiveDropboxOfficial: a5afefc83f6467c42c45f2253f583f2ad1ffc701
|
||||
PromisesObjC: c119f3cd559f50b7ae681fa59dc1acd19173b7e6
|
||||
RCTRequired: f63dd90a89a60602acdd44c42e5d2645ca60ab79
|
||||
RCTTypeSafety: 24a3c6d55684046ed550b1d0ef083a9bf71c8bd4
|
||||
React: 71c5a51135f291c3b32c0b558e167b858ae50e84
|
||||
React-Core: e82c03ff91062abf963f35bf99a357154e570285
|
||||
React-CoreModules: e236aeecd18cec37743c8c50562431db5302f668
|
||||
React-cxxreact: 526ec106aa1bf2b3f6aab2a7d528d1d23d5f59c2
|
||||
React-jsi: 4f35c1a2273d193a80c1c3831c808413840c260c
|
||||
React-jsiexecutor: de1c37cf59ae9adcbf2be82eea0e090dc3f3205e
|
||||
React-jsinspector: b76c4e84a7833bb4c90549d59ed53ec299ff912b
|
||||
react-native-background-timer: 0d34748e53a972507c66963490c775321a88f6f2
|
||||
PromisesObjC: b14b1c6b68e306650688599de8a45e49fae81151
|
||||
RCTRequired: a686731276578c125dff205f08b6ec9cee6ede32
|
||||
RCTTypeSafety: 88e5500e801c00d16a3d1895e3470d13beed6584
|
||||
React: 8b2bcf6a93846e47a7a365a54ec6edeb78b37701
|
||||
React-Core: 3fbdbc87c18c4742b735ff9a0c02fa38c87e0fba
|
||||
React-CoreModules: f6f8a8212aec52a21251c0af58bdb037b57c70b3
|
||||
React-cxxreact: c6ad34143db06a5c3cb0e8e169c775475287ac9c
|
||||
React-jsi: ddb471a56185e4007835a1bba0882ecb5ce3dc0e
|
||||
React-jsiexecutor: 67106691c60030ec888d7cbbc4f48a3168e27a02
|
||||
React-jsinspector: 92ceee6c66dc19886289b52436ade7e020b89602
|
||||
react-native-background-timer: e0384ea2fa5a98f67f84f9c4dc274260ddd674ed
|
||||
react-native-calendar-events: 1442fad71a00388f933cfa25512588fec300fcf8
|
||||
react-native-keep-awake: eba3137546b10003361b37c761f6c429b59814ae
|
||||
react-native-netinfo: 8d8db463bcc5db66a8ac5c48a7d86beb3b92f61a
|
||||
react-native-webrtc: 9268ae9a2bc9730796b0968d012327e92c392adf
|
||||
react-native-webview: 4dbc1d2a4a6b9c5e9e723c62651917aa2b5e579e
|
||||
React-RCTActionSheet: b72ddbfbe15b44ce691d128e4b582f4bb9abb540
|
||||
React-RCTAnimation: cfaefba5024499d336b76ab850e6bd33b232b5e3
|
||||
React-RCTBlob: c427e643bef82999deeab97489ba43298ecfbe24
|
||||
React-RCTImage: 79934bc96f3349da6a75b1d61cad594a932e4097
|
||||
React-RCTLinking: 12b153399567c30efac0b32bb00f9c064587dc26
|
||||
React-RCTNetwork: 603ad75778a54521b7797fd07c67dff562317526
|
||||
React-RCTSettings: 8d45fcf14513582539ea1ddea69391207de7f046
|
||||
React-RCTText: b4c29897c3df0c9f112e29aa3167fa6caf40b690
|
||||
React-RCTVibration: a1bcfcdc0b5a73a1b0829a34cee22bd0e95bacba
|
||||
ReactCommon: 675681aba4fecff5acbc0e440530cc422103c610
|
||||
react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865
|
||||
react-native-webrtc: edd689b0d5a462d7a6f6f52bca3f9414fc0ee11c
|
||||
react-native-webview: 6ee7868ca8eba635dbf7963986d1ab7959da0391
|
||||
React-RCTActionSheet: bcbc311dc3b47bc8efb2737ff0940239a45789a9
|
||||
React-RCTAnimation: 65f61080ce632f6dea23d52e354ffac9948396c6
|
||||
React-RCTBlob: 70d88f7b68b5c44953cdb286ac2e36a7a509a97e
|
||||
React-RCTImage: e0d25b620e42de91ed791ef129e2d3a0df1eb5ab
|
||||
React-RCTLinking: bc2287cfd9e56403ecea5dafdbdac8c57fa1ac36
|
||||
React-RCTNetwork: cd8ae8fc787c02ed5152fe9cbf7521ee70c1bce7
|
||||
React-RCTSettings: f6667271ccd8876a934134b73002b5a2714e1525
|
||||
React-RCTText: 4f1b99f228278d2a5e9008eced8dc9c974c4a270
|
||||
React-RCTVibration: c1041024893fdfdb8371e7c720c437751b711676
|
||||
ReactCommon: 18014e1d98dbeb9141e935cfe35fc93bd511ffb6
|
||||
RNCAsyncStorage: 8e31405a9f12fbf42c2bb330e4560bfd79c18323
|
||||
RNDefaultPreference: 56a405ce61033ac77b95004dccd7ac54c2eb50d1
|
||||
RNGoogleSignin: 39336070b35fc4cea6a98cf111e00480317be0ae
|
||||
RNSound: c980916b596cc15c8dcd2f6ecd3b13c4881dbe20
|
||||
RNSVG: aac12785382e8fd4f28d072fe640612e34914631
|
||||
RNSVG: 069864be08c9fe065a2cf7e63656a34c78653c99
|
||||
RNWatch: a5320c959c75e72845c07985f3e935e58998f1d3
|
||||
Yoga: 7b4209fda2441f99d54dd6cf4c82b094409bb68f
|
||||
Yoga: 96b469c5e81ff51b917b92e8c3390642d4ded30c
|
||||
|
||||
PODFILE CHECKSUM: 082858daebbe170e7a490de433e7f2a99e0c3701
|
||||
PODFILE CHECKSUM: f2400f8e5a52c4d91697cbacba6956569efc5ab8
|
||||
|
||||
COCOAPODS: 1.9.1
|
||||
COCOAPODS: 1.9.3
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
#import "Types.h"
|
||||
#import "ViewController.h"
|
||||
|
||||
@import Crashlytics;
|
||||
@import Fabric;
|
||||
@import Firebase;
|
||||
@import JitsiMeet;
|
||||
|
||||
@@ -48,12 +46,16 @@
|
||||
}];
|
||||
|
||||
// Initialize Crashlytics and Firebase if a valid GoogleService-Info.plist file was provided.
|
||||
if ([FIRUtilities appContainsRealServiceInfoPlist] && ![jitsiMeet isCrashReportingDisabled]) {
|
||||
NSLog(@"Enabling Crashlytics and Firebase");
|
||||
if ([FIRUtilities appContainsRealServiceInfoPlist]) {
|
||||
NSLog(@"Enabling Firebase");
|
||||
[FIRApp configure];
|
||||
[Fabric with:@[[Crashlytics class]]];
|
||||
// Crashlytics defaults to disabled wirth the FirebaseCrashlyticsCollectionEnabled Info.plist key.
|
||||
[[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:![jitsiMeet isCrashReportingDisabled]];
|
||||
}
|
||||
|
||||
ViewController *rootController = (ViewController *)self.window.rootViewController;
|
||||
[jitsiMeet showSplashScreen:rootController.view];
|
||||
|
||||
[jitsiMeet application:application didFinishLaunchingWithOptions:launchOptions];
|
||||
|
||||
return YES;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>20.4.0</string>
|
||||
<string>20.5.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
@@ -66,10 +66,10 @@
|
||||
<string>See your scheduled meetings in the app.</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Participate in meetings with video.</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string></string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Participate in meetings with voice.</string>
|
||||
<key>NSLocalNetworkUsageDescription</key>
|
||||
<string>Local network is used for establishing Peer-to-Peer connections.</string>
|
||||
<key>NSUserActivityTypes</key>
|
||||
<array>
|
||||
<string>org.jitsi.JitsiMeet.ios.conference</string>
|
||||
@@ -99,7 +99,7 @@
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>firebase_crashlytics_collection_enabled</key>
|
||||
<key>FirebaseCrashlyticsCollectionEnabled</key>
|
||||
<string>false</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>20.4.0</string>
|
||||
<string>20.5.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>20.4.0</string>
|
||||
<string>20.5.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>CLKComplicationPrincipalClass</key>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.10.0</string>
|
||||
<string>2.11.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
@@ -67,4 +67,6 @@
|
||||
|
||||
- (BOOL)isCrashReportingDisabled;
|
||||
|
||||
- (void)showSplashScreen:(UIView * _Nonnull) rootView;
|
||||
|
||||
@end
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#import "JitsiMeetView+Private.h"
|
||||
#import "RCTBridgeWrapper.h"
|
||||
#import "ReactUtils.h"
|
||||
#import "RNSplashScreen.h"
|
||||
|
||||
#import <RNGoogleSignin/RNGoogleSignin.h>
|
||||
#import <WebRTC/RTCLogging.h>
|
||||
@@ -183,6 +184,10 @@
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)showSplashScreen:(UIView*)rootView {
|
||||
[RNSplashScreen showSplash:@"LaunchScreen" inRootView:rootView];
|
||||
}
|
||||
|
||||
#pragma mark - Property getter / setters
|
||||
|
||||
- (NSArray<NSString *> *)universalLinkDomains {
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
module.exports = {
|
||||
moduleFileExtensions: [
|
||||
'js'
|
||||
],
|
||||
testMatch: [
|
||||
'<rootDir>/react/**/?(*.)+(test)?(.web).js?(x)'
|
||||
],
|
||||
verbose: true
|
||||
};
|
||||
@@ -20,6 +20,7 @@
|
||||
"ru": "Russisch",
|
||||
"sk": "Slowakisch",
|
||||
"sl": "Slowenisch",
|
||||
"sr": "Serbish",
|
||||
"sv": "Schwedisch",
|
||||
"tr": "Türkisch",
|
||||
"vi": "Vietnamesisch",
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"ru": "Russian",
|
||||
"sk": "",
|
||||
"sl": "Slovenian",
|
||||
"sr": "Serbian",
|
||||
"sv": "Swedish",
|
||||
"tr": "Turkish",
|
||||
"vi": "Vietnamese",
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"ru": "Ruski",
|
||||
"sk": "Slovački",
|
||||
"sl": "Slovenski",
|
||||
"sr": "Srpski",
|
||||
"sv": "Švedski",
|
||||
"tr": "Turski",
|
||||
"vi": "Vijetnamski",
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"pl": "Польский",
|
||||
"ptBR": "Португальский (Бразилия)",
|
||||
"ru": "Русский",
|
||||
"sr": "Сербский",
|
||||
"sv": "Шведский",
|
||||
"tr": "Турецкий",
|
||||
"vi": "Вьетнамский",
|
||||
|
||||
@@ -1,34 +1,39 @@
|
||||
{
|
||||
"en": "",
|
||||
"af": "",
|
||||
"bg": "",
|
||||
"ca": "",
|
||||
"cs": "",
|
||||
"da": "",
|
||||
"de": "",
|
||||
"el": "",
|
||||
"enGB": "",
|
||||
"eo": "",
|
||||
"es": "",
|
||||
"esUS": "",
|
||||
"et": "",
|
||||
"fi": "",
|
||||
"fr": "",
|
||||
"frCA": "",
|
||||
"hr": "",
|
||||
"hu": "",
|
||||
"hy": "",
|
||||
"it": "",
|
||||
"ja": "",
|
||||
"ko": "",
|
||||
"nl": "",
|
||||
"oc": "",
|
||||
"pl": "",
|
||||
"ptBR": "",
|
||||
"ru": "",
|
||||
"sv": "",
|
||||
"tr": "",
|
||||
"vi": "",
|
||||
"zhCN": "",
|
||||
"zhTW": ""
|
||||
"en": "Енглески",
|
||||
"af": "Африкански",
|
||||
"az": "Азербејџански",
|
||||
"bg": "Бугарски",
|
||||
"cs": "Чешки",
|
||||
"de": "Њемачки",
|
||||
"el": "Грчки",
|
||||
"eo": "Есперанто",
|
||||
"es": "Шпански",
|
||||
"fr": "Француски",
|
||||
"hy": "Јерменски",
|
||||
"it": "Италијански",
|
||||
"ja": "Јапански",
|
||||
"ko": "Корејски",
|
||||
"nb": "Норвешки Бокал",
|
||||
"oc": "Окцитански",
|
||||
"pl": "Пољски",
|
||||
"ptBR": "Португалски (Бразил)",
|
||||
"ru": "Руски",
|
||||
"sk": "Словачки",
|
||||
"sl": "Словенски",
|
||||
"sr": "Српски",
|
||||
"sv": "Шведски",
|
||||
"tr": "Турски",
|
||||
"vi": "Вијетнамски",
|
||||
"zhCN": "Кинески (Кина)",
|
||||
"zhTW": "Кинески (Тајван)",
|
||||
"nl": "Холандски",
|
||||
"hu": "Мађарски",
|
||||
"hr": "Хрватски",
|
||||
"frCA": "Француски (Канада)",
|
||||
"fi": "Фински",
|
||||
"et": "Естонски",
|
||||
"esUS": "Шпански (Латинска Америка)",
|
||||
"enGB": "Енглески (Велика Британија)",
|
||||
"da": "Дански",
|
||||
"ca": "Каталонски"
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
"sc": "Sardinian",
|
||||
"sk": "Slovak",
|
||||
"sl": "Slovenian",
|
||||
"sr": "Serbian",
|
||||
"sv": "Swedish",
|
||||
"th": "Thailand",
|
||||
"tr": "Turkish",
|
||||
|
||||
@@ -234,7 +234,7 @@
|
||||
"micPermissionDeniedError": "Die Berechtigung zur Verwendung des Mikrofons wurde nicht erteilt. Sie können trotzdem an der Konferenz teilnehmen, aber die anderen Teilnehmer können Sie nicht hören. Verwenden Sie die Kamera-Schaltfläche in der Adressleiste, um die Berechtigungen zu erteilen.",
|
||||
"micUnknownError": "Das Mikrofon kann aus einem unbekannten Grund nicht verwendet werden.",
|
||||
"muteEveryoneElseDialog": "Einmal stummgeschaltet, können Sie deren Stummschaltung nicht mehr beenden, aber sie können ihre Stummschaltung jederzeit selbst beenden.",
|
||||
"muteEveryoneElseTitle": "Alle außer {{whom}} stummschaten?",
|
||||
"muteEveryoneElseTitle": "Alle außer {{whom}} stummschalten?",
|
||||
"muteEveryoneDialog": "Wollen Sie wirklich alle stummschalten? Sie können deren Stummschaltung nicht mehr beenden, aber sie können ihre Stummschaltung jederzeit selbst beenden.",
|
||||
"muteEveryoneTitle": "Alle stummschalten?",
|
||||
"muteEveryoneSelf": "sich selbst",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"addContacts": "Inviter vos contacts",
|
||||
"copyInvite": "Copier l'invitation à la réunion",
|
||||
"copyLink": "Copier le lien de la réunion",
|
||||
"copyStream": "Copier le lien de diffision en direct",
|
||||
"copyStream": "Copier le lien de diffusion en direct",
|
||||
"countryNotSupported": "Cette destination n'est pas actuellement supportée.",
|
||||
"countryReminder": "Appel hors des États-Unis ? Veuillez débuter par le code du pays !",
|
||||
"defaultEmail": "Votre email par défaut",
|
||||
@@ -139,6 +139,9 @@
|
||||
"description": "Rien ne s'est passé ? Nous avons essayé de lancer votre réunion dans l'application de bureau {{app}}. Essayez à nouveau ou lancez-la dans l'application web {{app}}.",
|
||||
"descriptionWithoutWeb": "Rien ne s'est passé ? Nous avons essayé de démarrer votre réunion dans l'application bureau {{app}}.",
|
||||
"downloadApp": "Télécharger l'application",
|
||||
"ifDoNotHaveApp": "Si vous n'avez pas encore l'application:",
|
||||
"ifHaveApp": "Si vous avez déjà installé l'application:",
|
||||
"joinInApp": "Rejoindre la réunion en utilisant l'application",
|
||||
"launchWebButton": "Lancer dans le navigateur",
|
||||
"openApp": "Continuer vers l'application",
|
||||
"title": "Lancement de votre réunion dans {{app}} en cours...",
|
||||
@@ -194,7 +197,7 @@
|
||||
"done": "Terminé",
|
||||
"enterDisplayName": "Merci de saisir votre nom ici",
|
||||
"error": "Erreur",
|
||||
"grantModeratorDialog": "Êtes vous sûr de vouloir rendre ce participant modérateur?",
|
||||
"grantModeratorDialog": "Êtes-vous sûr de vouloir rendre ce participant modérateur?",
|
||||
"grantModeratorTitle": "Nommer modérateur",
|
||||
"externalInstallationMsg": "Vous devez installer notre extension de partage de bureau.",
|
||||
"externalInstallationTitle": "Extension requise",
|
||||
@@ -230,7 +233,7 @@
|
||||
"micUnknownError": "Vous ne pouvez pas utiliser le microphone pour une raison inconnue.",
|
||||
"muteEveryoneElseDialog": "Une fois leur micro coupé, vous ne pourrez plus le réactiver, mais ils pourront l'activer par eux-mêmes à tout moment.",
|
||||
"muteEveryoneElseTitle": "Couper le micro de tout le monde sauf de {{whom}} ?",
|
||||
"muteEveryoneDialog": "Etes-vous sûr de vouloir couper les micros de tout le monde ? Vous ne pourrez plus réactiver leur micro, mais ils pourront l'activer par eux-mêmes à tout moment.",
|
||||
"muteEveryoneDialog": "Êtes-vous sûr de vouloir couper les micros de tout le monde ? Vous ne pourrez plus réactiver leur micro, mais ils pourront l'activer par eux-mêmes à tout moment.",
|
||||
"muteEveryoneTitle": "Couper le micro de tout le monde ?",
|
||||
"muteEveryoneSelf": "vous",
|
||||
"muteEveryoneStartMuted": "Tout le monde démarre avec le micro coupé",
|
||||
@@ -697,6 +700,8 @@
|
||||
"hangup": "Quitter",
|
||||
"help": "Aide",
|
||||
"invite": "Inviter des participants",
|
||||
"lobbyButtonDisable": "Désactiver le contrôle des participant·e·s",
|
||||
"lobbyButtonEnable": "Activer le contrôle des participant·e·s",
|
||||
"login": "Connexion",
|
||||
"logout": "Déconnexion",
|
||||
"lowerYourHand": "Baisser la main",
|
||||
@@ -725,7 +730,7 @@
|
||||
"stopScreenSharing": "Arrêter le partage d'écran",
|
||||
"stopSubtitles": "Désactiver les sous-titres",
|
||||
"stopSharedVideo": "Arrêter la vidéo YouTube",
|
||||
"talkWhileMutedPopup": "Vous voulez parler ? Vôtre micro est coupé.",
|
||||
"talkWhileMutedPopup": "Vous voulez parler ? Votre micro est coupé.",
|
||||
"tileViewToggle": "Activer/désactiver la vue mosaïque",
|
||||
"toggleCamera": "Changer de caméra",
|
||||
"videomute": "Démarrer / Arrêter la caméra",
|
||||
@@ -764,7 +769,7 @@
|
||||
"errorAlreadyInvited": "{{displayName}} est déjà invité(e)",
|
||||
"errorInvite": "La conférence n'est pas encore établie. Veuillez réessayer plus tard.",
|
||||
"errorInviteFailed": "Nous tentons de résoudre le problème. Veuillez réessayer plus tard.",
|
||||
"errorInviteFailedTitle": "l'invitation de {{displayName}} a échoué",
|
||||
"errorInviteFailedTitle": "L'invitation de {{displayName}} a échoué",
|
||||
"errorInviteTitle": "Erreur lors de l'invitation",
|
||||
"pending": "{{displayName}} a été invité(e)"
|
||||
},
|
||||
@@ -804,7 +809,7 @@
|
||||
"join": "Touchez pour rejoindre",
|
||||
"roomname": "Saisissez un nom de salle"
|
||||
},
|
||||
"appDescription": "Foncez tchater en vidéo avec toute le monde. En fait, vous pouvez inviter tout ceux que vous connaissez. {{app}} est une solution de visioconférence entièrement chiffrée et 100% libre que vous pouvez utiliser en permanence, chaque jours, et sans aucun compte requis.",
|
||||
"appDescription": "Foncez tchater en vidéo avec toute le monde. En fait, vous pouvez inviter tout ceux que vous connaissez. {{app}} est une solution de visioconférence entièrement chiffrée et 100% libre que vous pouvez utiliser en permanence, chaque jour, et sans aucun compte requis.",
|
||||
"audioVideoSwitch": {
|
||||
"audio": "Voix",
|
||||
"video": "Vidéo"
|
||||
@@ -842,10 +847,10 @@
|
||||
"allow": "Autoriser",
|
||||
"backToKnockModeButton": "Aucun mot de passe, demander à rejoindre plutôt",
|
||||
"dialogTitle": "Mode lobby",
|
||||
"disableDialogContent": "Le mode lobby est actuellement activé. Cette fonctionnalité garantit que les participants indésirables ne peuvent pas rejoindre votre réunion. Souhaitez-vous la désactiver?",
|
||||
"disableDialogContent": "Le mode lobby est actuellement activé. Cette fonctionnalité garantit que les participants indésirables ne peuvent pas rejoindre votre réunion. Souhaitez-vous la désactiver ?",
|
||||
"disableDialogSubmit": "Désactiver",
|
||||
"emailField": "Saisissez votre adresse email",
|
||||
"enableDialogPasswordField": "Définir le mot de passe (optionel)",
|
||||
"enableDialogPasswordField": "Définir le mot de passe (optionnel)",
|
||||
"enableDialogSubmit": "Activer",
|
||||
"enableDialogText": "Le mode lobby vous permet de protéger votre réunion en autorisant les personnes à entrer qu'après l'approbation formelle d'un modérateur.",
|
||||
"enterPasswordButton": "Saisissez un mot de passe de réunion",
|
||||
|
||||
1025
lang/main-kab.json
1025
lang/main-kab.json
File diff suppressed because it is too large
Load Diff
@@ -1,60 +1,86 @@
|
||||
{
|
||||
"addPeople": {
|
||||
"add": "초대",
|
||||
"countryNotSupported": "아직 해당 지역을 지원하지 않습니다",
|
||||
"addContacts": "연락처로 초대하세요",
|
||||
"copyInvite": "호의 초대 복사",
|
||||
"copyLink": "회의 링크 복사",
|
||||
"copyStream": "라이브 스트리밍 링크 복사",
|
||||
"countryNotSupported": "아직 해당 지역을 지원하지 않습니다.",
|
||||
"countryReminder": "미국 이외의 지역으로 전화하시겠습니까? 국가 번호로 시작해야합니다!",
|
||||
"disabled": "사람들을 초대 할 수 없습니다",
|
||||
"failedToAdd": "",
|
||||
"footerText": "",
|
||||
"defaultEmail": "기본 이메일",
|
||||
"disabled": "사람들을 초대 할 수 없습니다.",
|
||||
"failedToAdd": "참가자를 추가하지 못했습니다.",
|
||||
"footerText": "전화 걸기가 비활성화되었습니다.",
|
||||
"googleEmail": "Google 이메일",
|
||||
"inviteMoreHeader": "회의에 혼자 참여하고 있습니다.",
|
||||
"inviteMoreMailSubject": "{{appName}} 회의에 참여하세요",
|
||||
"inviteMorePrompt": "더 많은 사람을 초대하세요",
|
||||
"linkCopied": "링크가 클립보드에 복사되었습니다.",
|
||||
"loading": "사람 및 전화번호 검색",
|
||||
"loadingNumber": "전화번호 확인 중",
|
||||
"loadingPeople": "초대할 사람 찾기",
|
||||
"noResults": "일치하는 검색 결과 없음",
|
||||
"noValidNumbers": "전화 번호를 입력하십시오.",
|
||||
"outlookEmail": "Outlook 이메일",
|
||||
"searchNumbers": "전화번호 추가",
|
||||
"searchPeople": "인명 검색",
|
||||
"searchPeopleAndNumbers": "인명 검색 또는 전화번호 추가",
|
||||
"shareInvite": "회의 초대 공유",
|
||||
"shareLink": "다른 사람을 초대하려면 회의 링크를 공유하세요.",
|
||||
"shareStream": "라이브 스트리밍 링크 공유",
|
||||
"telephone": "전화: {{number}}",
|
||||
"title": "이 회의에 사람들을 초대하십시오"
|
||||
"title": "이 회의에 사람들을 초대하십시오",
|
||||
"yahooEmail": "Yahoo 이메일"
|
||||
},
|
||||
"audioDevices": {
|
||||
"bluetooth": "블루투스",
|
||||
"headphones": "헤드폰",
|
||||
"phone": "폰",
|
||||
"speaker": "스피커"
|
||||
"speaker": "스피커",
|
||||
"none": "사용 가능한 오디오 장치가 없습니다."
|
||||
},
|
||||
"audioOnly": {
|
||||
"audioOnly": "음성 전용"
|
||||
},
|
||||
"calendarSync": {
|
||||
"addMeetingURL": "",
|
||||
"confirmAddLink": "",
|
||||
"addMeetingURL": "회의 링크 추가",
|
||||
"confirmAddLink": "이 이벤트에 Jitsi 링크를 추가 하시겠습니까?",
|
||||
"error": {
|
||||
"appConfiguration": "",
|
||||
"generic": "",
|
||||
"notSignedIn": ""
|
||||
"appConfiguration": "캘린더가 제대로 구성되지 않았습니다.",
|
||||
"generic": "오류가 발생했습니다. 캘린더 설정을 확인하거나 캘린더를 새로 고침 해보세요.",
|
||||
"notSignedIn": "캘린더 이벤트를 보기 위해 인증하는 동안 오류가 발생했습니다. 캘린더 설정을 확인하고 다시 로그인하십시오."
|
||||
},
|
||||
"join": "",
|
||||
"joinTooltip": "",
|
||||
"join": "참여",
|
||||
"joinTooltip": "회의에 참여하세요",
|
||||
"nextMeeting": "다음 회의",
|
||||
"noEvents": "",
|
||||
"ongoingMeeting": "",
|
||||
"noEvents": "예정된 예정된 이벤트가 없습니다.",
|
||||
"ongoingMeeting": "진행중인 회의",
|
||||
"permissionButton": "설정 열기",
|
||||
"permissionMessage": "앱에 회의를 나열하려면 캘린더 권한이 필요합니다",
|
||||
"refresh": "",
|
||||
"today": ""
|
||||
"refresh": "달력 새로고침",
|
||||
"today": "오늘"
|
||||
},
|
||||
"chat": {
|
||||
"error": "",
|
||||
"messagebox": "",
|
||||
"error": "오류 : 메시지가 전송되지 않았습니다. 이유 : {{error}}",
|
||||
"fieldPlaceHolder": "메세지를 여기에 입력하세요",
|
||||
"messagebox": "메시지 입력",
|
||||
"messageTo": "{{recipient}}에게 보내는 비공개 메시지",
|
||||
"noMessagesMessage": "아직 회의에 메시지가 없습니다. 여기서 대화를 시작하세요!",
|
||||
"nickname": {
|
||||
"popover": "닉네임을 선택하세요",
|
||||
"title": ""
|
||||
"title": "채팅에서 사용할 닉네임을 입력하세요"
|
||||
},
|
||||
"title": ""
|
||||
"privateNotice": "{{recipient}}에게 보내는 비공개 메시지",
|
||||
"title": "채팅",
|
||||
"you": "당신"
|
||||
},
|
||||
"chromeExtensionBanner": {
|
||||
"installExtensionText": "Google 캘린더 및 Office 365 확장 프로그램을 설치합니다.",
|
||||
"buttonText": "Chrome 확장 프로그램을 설치합니다.",
|
||||
"dontShowAgain": "다시 보지 않기"
|
||||
},
|
||||
"connectingOverlay": {
|
||||
"joiningRoom": ""
|
||||
"joiningRoom": "회의에 연결 중 ..."
|
||||
},
|
||||
"connection": {
|
||||
"ATTACHED": "첨부",
|
||||
@@ -66,7 +92,10 @@
|
||||
"DISCONNECTED": "연결 끊김",
|
||||
"DISCONNECTING": "연결 종료 중",
|
||||
"ERROR": "에러",
|
||||
"RECONNECTING": "네트워크 문제가 발생했습니다. 다시 연결 중..."
|
||||
"RECONNECTING": "네트워크 문제가 발생했습니다. 다시 연결 중...",
|
||||
"GET_SESSION_ID_ERROR": "세션 ID 가져 오기 오류 : {{code}}",
|
||||
"GOT_SESSION_ID": "세션 ID를 가져 오는 중 ... 완료",
|
||||
"LOW_BANDWIDTH": "대역폭을 절약하기 위해 {{displayName}}의 동영상이 중지되었습니다."
|
||||
},
|
||||
"connectionindicator": {
|
||||
"address": "주소:",
|
||||
@@ -95,15 +124,18 @@
|
||||
"turn": " (turn)"
|
||||
},
|
||||
"dateUtils": {
|
||||
"earlier": "",
|
||||
"today": "",
|
||||
"yesterday": ""
|
||||
"earlier": "일찍이",
|
||||
"today": "오늘",
|
||||
"yesterday": "어제"
|
||||
},
|
||||
"deepLinking": {
|
||||
"appNotInstalled": "중계 서비스에 참여하려면 모바일 앱 설치가 필요합니다",
|
||||
"appNotInstalled": "회의에 참여하려면 모바일 앱 설치가 필요합니다",
|
||||
"description": "{{app}} 데스크톱 앱에서 회의를 시작했습니다. {{app}} 웹 응용 프로그램에서 다시 시도하거나 실행하십시오.",
|
||||
"descriptionWithoutWeb": "",
|
||||
"downloadApp": "앱 다운로드",
|
||||
"ifDoNotHaveApp": "앱이 설치되지 않은 경우:",
|
||||
"ifHaveApp": "앱이 설치되어 있는 경우:",
|
||||
"joinInApp": "앱을 사용하여 회의에 참여하세요.",
|
||||
"launchWebButton": "웹에서 실행",
|
||||
"openApp": "방으로 이동하기",
|
||||
"title": "{{app}}에서 회의 시작…",
|
||||
@@ -126,8 +158,9 @@
|
||||
"accessibilityLabel": {
|
||||
"liveStreaming": "실시간 스트리밍:"
|
||||
},
|
||||
"add": "추가",
|
||||
"allow": "허락",
|
||||
"alreadySharedVideoMsg": "",
|
||||
"alreadySharedVideoMsg": "다른 참가자가 이미 비디오를 공유하고 있습니다. 이 회의는 한 번에 하나의 공유 비디오 만 허용합니다.",
|
||||
"alreadySharedVideoTitle": "한 번에 하나의 공유 비디오 만 허용됩니다",
|
||||
"applicationWindow": "응용 프로그램 창",
|
||||
"Back": "뒤로가기",
|
||||
@@ -145,64 +178,64 @@
|
||||
"conferenceReloadMsg": "문제를 해결하려고 노력하고 있습니다. {{seconds}} 초 안에 다시 연결중입니다.",
|
||||
"conferenceReloadTitle": "불행하게도 문제가 발생했습니다",
|
||||
"confirm": "확인",
|
||||
"confirmNo": "",
|
||||
"confirmYes": "",
|
||||
"confirmNo": "아니요",
|
||||
"confirmYes": "예",
|
||||
"connectError": "죄송합니다. 문제가 발생하여 회의에 연결할 수 없습니다",
|
||||
"connectErrorWithMsg": "죄송합니다. 뭔가 잘못되어 회의에 연결할 수 없습니다: {{msg}}",
|
||||
"connecting": "연결 중",
|
||||
"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": "알 수 없는 이유로 마이크를 사용할 수 없습니다",
|
||||
"muteParticipantBody": "당신이 다른 사람들의 음소거를 해제 할 수는 없지만 언제든지 다른 사람들은 스스로 음소거를 해제할 수 있습니다.",
|
||||
"muteParticipantButton": "음소거",
|
||||
"muteParticipantDialog": "",
|
||||
"muteParticipantTitle": "",
|
||||
"muteParticipantTitle": "이 참가자를 음소거 하시겠습니까?",
|
||||
"Ok": "확인",
|
||||
"passwordLabel": "",
|
||||
"passwordNotSupported": "미팅 비밀번호 설정은 지원되지 않습니다",
|
||||
"passwordNotSupportedTitle": "",
|
||||
"passwordRequired": "",
|
||||
"passwordLabel": "잠긴 회의 입니다. 회의에 참여하려면 비밀번호를 입력하세요.",
|
||||
"passwordNotSupported": "회의 비밀번호 설정은 지원되지 않습니다",
|
||||
"passwordNotSupportedTitle": "비밀번호 미지원",
|
||||
"passwordRequired": "비밀번호 필수",
|
||||
"popupError": "브라우저가이 사이트의 팝업 창을 차단하고 있습니다. 브라우저의 보안 설정에서 팝업을 활성화하고 다시 시도하십시오.",
|
||||
"popupErrorTitle": "팝업 차단됨",
|
||||
"recording": "레코딩",
|
||||
"recordingDisabledForGuestTooltip": "",
|
||||
"recordingDisabledTooltip": "",
|
||||
"recordingDisabledForGuestTooltip": "게스트는 녹음을 시작할 수 없습니다.",
|
||||
"recordingDisabledTooltip": "녹화이 비활성화 되었습니다.",
|
||||
"rejoinNow": "지금 재가입",
|
||||
"remoteControlAllowedMessage": "{{user}}이(가) 원격 제어 요청을 수락했습니다",
|
||||
"remoteControlDeniedMessage": "{{user}}이(가) 원격 제어 요청을 거부했습니다",
|
||||
@@ -212,25 +245,30 @@
|
||||
"remoteControlStopMessage": "원격 제어 세션이 종료되었습니다",
|
||||
"remoteControlTitle": "원격 데스크탑 컨트롤",
|
||||
"Remove": "제거",
|
||||
"removePassword": "",
|
||||
"removePassword": "비밀번호 제거",
|
||||
"removeSharedVideoMsg": "공유한 동영상을 삭제하시겠습니까?",
|
||||
"removeSharedVideoTitle": "공유된 동영상 삭제",
|
||||
"reservationError": "예약 시스템 오류",
|
||||
"reservationErrorMsg": "오류 코드: {{code}}, 메시지: {{msg}}",
|
||||
"retry": "재시도",
|
||||
"screenSharingAudio": "오디오 공유",
|
||||
"screenSharingFailedToInstall": "죄송합니다. 화면 공유 확장 프로그램을 설치하지 못했습니다.",
|
||||
"screenSharingFailedToInstallTitle": "화면 공유 확장 프로그램을 설치하지 못했습니다",
|
||||
"screenSharingFirefoxPermissionDeniedError": "화면을 공유하는 동안 문제가 발생했습니다. 그렇게 할 수 있는 권한을 부여했는지 확인하십시오.",
|
||||
"screenSharingFirefoxPermissionDeniedTitle": "죄송합니다. 화면 공유를 시작할 수 없었습니다!",
|
||||
"screenSharingPermissionDeniedError": "죄송합니다. 화면 공유 확장 권한으로 문제가 발생했습니다. 다시 로드하고 재시도하십시오.",
|
||||
"sendPrivateMessage": "최근에 비공개 메시지를 받았습니다. 비공개로 답장을 보내시겠습니까, 아니면 그룹에 메시지를 보내시겠습니까?",
|
||||
"sendPrivateMessageCancel": "그룹에 보내기",
|
||||
"sendPrivateMessageOk": "비공개로 보내기",
|
||||
"sendPrivateMessageTitle": "비공개로 보낼까요?",
|
||||
"serviceUnavailable": "서비스를 사용할 수 없음",
|
||||
"sessTerminated": "통화 종료",
|
||||
"Share": "공유",
|
||||
"shareVideoLinkError": "올바른 YouTube 링크를 제공하십시오",
|
||||
"shareVideoTitle": "비디오 공유",
|
||||
"shareYourScreen": "화면공유",
|
||||
"shareYourScreenDisabled": "",
|
||||
"shareYourScreenDisabledForGuest": "",
|
||||
"shareYourScreenDisabled": "화면 공유가 비활성화 되었습니다.",
|
||||
"shareYourScreenDisabledForGuest": "게스트는 화면을 공유 할 수 없습니다.",
|
||||
"startLiveStreaming": "라이브 스트리밍 시작",
|
||||
"startRecording": "레코딩 시작",
|
||||
"startRemoteControlErrorMessage": "원격 제어 세션을 시작하는 동안 오류가 발생했습니다",
|
||||
@@ -245,17 +283,20 @@
|
||||
"tokenAuthFailed": "죄송합니다. 통화에 참여하실 수 없습니다.",
|
||||
"tokenAuthFailedTitle": "인증 실패",
|
||||
"transcribing": "",
|
||||
"unlockRoom": "",
|
||||
"unlockRoom": "회의 비밀번호 제거",
|
||||
"userPassword": "사용자 비밀번호",
|
||||
"WaitForHostMsg": "",
|
||||
"WaitForHostMsgWOk": "",
|
||||
"WaitForHostMsg": "<b>{{room}}</b> 회의가 시작되지 않았습니다. 호스트 인 경우 인증하십시오. 그렇지 않으면 호스트가 도착할 때까지 기다리십시오.",
|
||||
"WaitForHostMsgWOk": "<b>{{room}}</b> 회의가 아직 시작되지 않았습니다. 호스트 인 경우 확인을 눌러 인증하십시오. 그렇지 않으면 호스트가 도착할 때까지 기다리십시오.",
|
||||
"WaitingForHost": "호스트를 기다리는 중입니다…",
|
||||
"Yes": "",
|
||||
"Yes": "예",
|
||||
"yourEntireScreen": "전체 화면"
|
||||
},
|
||||
"dialOut": {
|
||||
"statusMessage": "지금은 {{status}}입니다"
|
||||
},
|
||||
"documentSharing": {
|
||||
"title": "문서 공유"
|
||||
},
|
||||
"feedback": {
|
||||
"average": "보통",
|
||||
"bad": "나쁨",
|
||||
@@ -266,49 +307,49 @@
|
||||
"veryGood": "매우 좋음"
|
||||
},
|
||||
"incomingCall": {
|
||||
"answer": "",
|
||||
"audioCallTitle": "",
|
||||
"decline": "",
|
||||
"productLabel": "",
|
||||
"videoCallTitle": ""
|
||||
"answer": "응답",
|
||||
"audioCallTitle": "수신 전화",
|
||||
"decline": "거절",
|
||||
"productLabel": "Jitsi Meet에서",
|
||||
"videoCallTitle": "수신 화상 전화"
|
||||
},
|
||||
"info": {
|
||||
"accessibilityLabel": "",
|
||||
"addPassword": "",
|
||||
"cancelPassword": "",
|
||||
"accessibilityLabel": "정보 보기",
|
||||
"addPassword": "$t(lockRoomPassword) 추가",
|
||||
"cancelPassword": "$t(lockRoomPassword) 취소",
|
||||
"conferenceURL": "링크:",
|
||||
"country": "지역",
|
||||
"dialANumber": "",
|
||||
"dialANumber": "회의에 참여하려면이 번호 중 하나를 누른 다음 PIN을 입력하십시오.",
|
||||
"dialInConferenceID": "PIN:",
|
||||
"dialInNotSupported": "죄송합니다. 현재 전화를 걸 수 없습니다.",
|
||||
"dialInNumber": "Dial-in:",
|
||||
"dialInSummaryError": "",
|
||||
"dialInSummaryError": "지금 전화 접속 정보를 가져 오는 중에 오류가 발생했습니다. 나중에 다시 시도하십시오.",
|
||||
"dialInTollFree": "",
|
||||
"genericError": "일반적인 오류가 발생했습니다",
|
||||
"inviteLiveStream": "이 회의의 실시간 스트림을 보려면이 링크를 클릭하십시오: {{url}}",
|
||||
"invitePhone": "",
|
||||
"invitePhoneAlternatives": "",
|
||||
"inviteURLFirstPartGeneral": "",
|
||||
"inviteURLFirstPartPersonal": "",
|
||||
"inviteURLSecondPart": "",
|
||||
"inviteURLFirstPartGeneral": "회의에 초대되었습니다.",
|
||||
"inviteURLFirstPartPersonal": "{{name}}이 회의에 초대하였습니다.\n",
|
||||
"inviteURLSecondPart": "\n회의에 참여하기:\n{{url}}\n",
|
||||
"liveStreamURL": "실시간 스트리밍:",
|
||||
"moreNumbers": "더 많은 번호",
|
||||
"noNumbers": "전화 접속 번호 없음",
|
||||
"noPassword": "없음",
|
||||
"noRoom": "전화 접속이 가능한 방을 지정하지 않았습니다",
|
||||
"numbers": "전화 접속 번호",
|
||||
"password": "",
|
||||
"password": "비밀번호",
|
||||
"title": "공유",
|
||||
"tooltip": "링크 공유 및 회의에 대한 정보",
|
||||
"label": ""
|
||||
"label": "회의 정보"
|
||||
},
|
||||
"inviteDialog": {
|
||||
"alertText": "",
|
||||
"alertText": "일부 참가자를 초대하지 못했습니다.",
|
||||
"header": "초대",
|
||||
"searchCallOnlyPlaceholder": "",
|
||||
"searchPeopleOnlyPlaceholder": "",
|
||||
"searchPlaceholder": "",
|
||||
"send": ""
|
||||
"searchCallOnlyPlaceholder": "전화 번호 입력",
|
||||
"searchPeopleOnlyPlaceholder": "참가자 검색",
|
||||
"searchPlaceholder": "참가자 또는 전화 번호",
|
||||
"send": "전송"
|
||||
},
|
||||
"inlineDialogFailure": {
|
||||
"msg": "약간의 문제가 있습니다",
|
||||
@@ -321,7 +362,7 @@
|
||||
"focusRemote": "다른 발신자의 동영상에 포커스",
|
||||
"fullScreen": "전체화면 표시 또는 종료",
|
||||
"keyboardShortcuts": "키보드 단축키",
|
||||
"localRecording": "",
|
||||
"localRecording": "로컬 녹음 컨트롤 표시 또는 숨기기",
|
||||
"mute": "마이크 음소거 또는 음소거 해제",
|
||||
"pushToTalk": "대화 요청",
|
||||
"raiseHand": "말하기 요청/해제",
|
||||
@@ -341,24 +382,26 @@
|
||||
"enterStreamKey": "YouTube 실시간 스트리밍 키를 입력하십시오",
|
||||
"error": "실시간 스트리밍에 실패했습니다. 다시 시도하십시오.",
|
||||
"errorAPI": "YouTube 방송에 액세스하는 중에 오류가 발생했습니다. 다시 로그인하십시오.",
|
||||
"errorLiveStreamNotEnabled": "",
|
||||
"expandedOff": "",
|
||||
"expandedOn": "",
|
||||
"expandedPending": "",
|
||||
"errorLiveStreamNotEnabled": "{{email}}에 의해 라이브 스트리밍이 활성화되지 않았습니다. 라이브 스트리밍을 활성화하거나 라이브 스트리밍이 활성화 된 계정으로 로그인하십시오.",
|
||||
"expandedOff": "라이브 스트리밍이 중지되었습니다",
|
||||
"expandedOn": "현재 회의가 YouTube로 스트리밍되고 있습니다.",
|
||||
"expandedPending": "라이브 스트리밍이 시작됩니다 ...",
|
||||
"failedToStart": "실시간 스트리밍 시작 실패",
|
||||
"getStreamKeyManually": "",
|
||||
"invalidStreamKey": "",
|
||||
"getStreamKeyManually": "실시간 스트림을 가져올 수 없습니다. YouTube에서 실시간 스트림 키를 받아보세요.",
|
||||
"invalidStreamKey": "라이브 스트림 키가 잘못되었을 수 있습니다.",
|
||||
"off": "실시간 스트리밍이 중지됨",
|
||||
"on": "실시간 스트리밍",
|
||||
"pending": "실시간 스트리밍 시작…",
|
||||
"serviceName": "실시간 스트리밍 서비스",
|
||||
"signedInAs": "",
|
||||
"signedInAs": "현재 다음 계정으로 로그인되어 있습니다.",
|
||||
"signIn": "Google로 로그인",
|
||||
"signInCTA": "YouTube에서 로그인하거나 실시간 스트리밍 키를 입력하십시오",
|
||||
"signOut": "",
|
||||
"signOut": "로그아웃",
|
||||
"start": "실시간 스트리밍 시작",
|
||||
"streamIdHelp": "도움말?",
|
||||
"unavailableTitle": "실시간 스트리밍을 사용할 수 없음"
|
||||
"unavailableTitle": "실시간 스트리밍을 사용할 수 없음",
|
||||
"youtubeTerms": "YouTube 서비스 약관",
|
||||
"googlePrivacyPolicy": "Google 개인 정보 보호 정책"
|
||||
},
|
||||
"localRecording": {
|
||||
"clientState": {
|
||||
@@ -381,50 +424,50 @@
|
||||
"notModerator": ""
|
||||
},
|
||||
"moderator": "",
|
||||
"no": "",
|
||||
"no": "아니요",
|
||||
"participant": "",
|
||||
"participantStats": "",
|
||||
"sessionToken": "",
|
||||
"start": "레코딩 시작",
|
||||
"stop": "레코딩 종료",
|
||||
"yes": ""
|
||||
"yes": "예"
|
||||
},
|
||||
"lockRoomPassword": "패스워드",
|
||||
"lockRoomPasswordUppercase": "패스워드",
|
||||
"me": "Me",
|
||||
"lockRoomPassword": "비밀번호",
|
||||
"lockRoomPasswordUppercase": "비밀번호",
|
||||
"me": "나",
|
||||
"notify": {
|
||||
"connectedOneMember": "",
|
||||
"connectedThreePlusMembers": "",
|
||||
"connectedTwoMembers": "",
|
||||
"connectedOneMember": "{{name}}님이 회의에 참여했습니다.",
|
||||
"connectedThreePlusMembers": "{{name}}님 외 {{count}}명이 회의에 참여했습니다.",
|
||||
"connectedTwoMembers": "{{first}}님과 {{second}}님이 회의에 참여했습니다.",
|
||||
"disconnected": "연결이 끊김",
|
||||
"focus": "컨퍼런스 포커스",
|
||||
"focusFail": "{{component}}을 사용할 수 없음 - {{ms}} 초 후에 다시 시도하십시오",
|
||||
"grantedTo": "{{to}}에게 방장 권한이 부여되었습니다!",
|
||||
"invitedOneMember": "",
|
||||
"invitedThreePlusMembers": "",
|
||||
"invitedTwoMembers": "",
|
||||
"kickParticipant": "",
|
||||
"me": "",
|
||||
"invitedOneMember": "{{name}}님이 초대되었습니다.",
|
||||
"invitedThreePlusMembers": "{{name}}님 외 {{count}}명이 초대되었습니다.",
|
||||
"invitedTwoMembers": "{{first}}님과 {{second}}님이 초대되었습니다.",
|
||||
"kickParticipant": "{{kicker}}님이 {{kicked}}님을 추방했습니다.",
|
||||
"me": "나",
|
||||
"moderator": "방장 권한이 부여되었습니다!",
|
||||
"muted": "음소거로 대화가 시작되었습니다",
|
||||
"mutedTitle": "음소거 상태입니다!",
|
||||
"mutedRemotelyTitle": "",
|
||||
"mutedRemotelyDescription": "",
|
||||
"passwordRemovedRemotely": "",
|
||||
"passwordSetRemotely": "",
|
||||
"raisedHand": "",
|
||||
"mutedRemotelyTitle": "{{participantDisplayName}}에 의해 음소거되었습니다!",
|
||||
"mutedRemotelyDescription": "말할 준비가되면 언제든지 음소거를 해제 할 수 있습니다.",
|
||||
"passwordRemovedRemotely": "다른 참가자가 $t(lockRoomPasswordUppercase)를 제거했습니다.",
|
||||
"passwordSetRemotely": "다른 참가자가 $t(lockRoomPasswordUppercase)를 설정했습니다.",
|
||||
"raisedHand": "{{name}}님이 말하고 싶어합니다.",
|
||||
"somebody": "누군가",
|
||||
"startSilentTitle": "",
|
||||
"startSilentDescription": "",
|
||||
"startSilentTitle": "오디오 출력없이 참여했습니다!",
|
||||
"startSilentDescription": "오디오를 사용하려면 회의에 다시 참여하세요.",
|
||||
"suboptimalExperienceDescription": "{{appName}}에 대한 귀하의 경험이 없으시다면 <a href='{{recommendedBrowserPageLink}}' target='_blank'>완벽하게 지원되는 브라우저</a> 중 하나를 사용해보십시오.",
|
||||
"suboptimalExperienceTitle": "브라우저 경고",
|
||||
"unmute": "",
|
||||
"newDeviceCameraTitle": "",
|
||||
"newDeviceAudioTitle": "",
|
||||
"newDeviceAction": ""
|
||||
"unmute": "음소거 해제",
|
||||
"newDeviceCameraTitle": "새 카메라 감지",
|
||||
"newDeviceAudioTitle": "새 오디오 장치 감지",
|
||||
"newDeviceAction": "사용"
|
||||
},
|
||||
"passwordSetRemotely": "",
|
||||
"passwordDigitsOnly": "",
|
||||
"passwordSetRemotely": "다른 참가자가 설정",
|
||||
"passwordDigitsOnly": "최대 {{number}} 자리",
|
||||
"poweredby": "powered by",
|
||||
"presenceStatus": {
|
||||
"busy": "바쁨",
|
||||
@@ -447,27 +490,27 @@
|
||||
"title": "프로필"
|
||||
},
|
||||
"recording": {
|
||||
"authDropboxText": "",
|
||||
"availableSpace": "",
|
||||
"authDropboxText": "Dropbox에 업로드",
|
||||
"availableSpace": "사용 가능한 공간 : {{spaceLeft}}MB (약 {{duration}}분 녹화)",
|
||||
"beta": "베타",
|
||||
"busy": "레코딩 자원을 확보하고 있습니다. 몇 분 후에 다시 시도하십시오.",
|
||||
"busyTitle": "모든 레코더가 현재 사용 중입니다",
|
||||
"error": "레코딩이 실패했습니다. 다시 시도하십시오.",
|
||||
"expandedOff": "레코딩이 중지됨",
|
||||
"expandedOn": "",
|
||||
"expandedPending": "",
|
||||
"expandedOn": "회의가 현재 녹화 중입니다.",
|
||||
"expandedPending": "녹화가 시작됩니다 ...",
|
||||
"failedToStart": "레코딩을 시작하지 못했습니다",
|
||||
"fileSharingdescription": "",
|
||||
"fileSharingdescription": "회의 참가자와 녹음 공유",
|
||||
"live": "라이브",
|
||||
"loggedIn": "",
|
||||
"loggedIn": "{{userName}}으로 로그인했습니다.",
|
||||
"off": "레코딩이 중지됨",
|
||||
"on": "레코딩",
|
||||
"pending": "참석할 멤버를 기다리는 중입니다…",
|
||||
"rec": "REC",
|
||||
"serviceDescription": "",
|
||||
"rec": "녹음",
|
||||
"serviceDescription": "녹음은 녹음 서비스에 의해 저장됩니다.",
|
||||
"serviceName": "레코딩 서비스",
|
||||
"signIn": "",
|
||||
"signOut": "",
|
||||
"signIn": "로그인",
|
||||
"signOut": "로그아웃",
|
||||
"unavailable": "죄송합니다. {{serviceName}}은 현재 사용할 수 없습니다. 저희는 문제를 해결하기 위해 노력하고 있습니다. 나중에 다시 시도 해주십시오.",
|
||||
"unavailableTitle": "레코딩을 사용할 수 없습니다"
|
||||
},
|
||||
@@ -476,18 +519,18 @@
|
||||
},
|
||||
"settings": {
|
||||
"calendar": {
|
||||
"about": "",
|
||||
"about": "{{appName}} 캘린더 통합은 예정된 일정을 읽을 수 있도록 캘린더에 안전하게 액세스하는 데 사용됩니다.",
|
||||
"disconnect": "연결 끊김",
|
||||
"microsoftSignIn": "",
|
||||
"signedIn": "",
|
||||
"title": ""
|
||||
"microsoftSignIn": "Microsoft로 로그인",
|
||||
"signedIn": "현재 {{email}}의 캘린더 일정에 액세스하고 있습니다. 캘린더 이벤트 액세스를 중지하려면 아래 연결 해제 버튼을 클릭하세요.",
|
||||
"title": "캘린더"
|
||||
},
|
||||
"devices": "",
|
||||
"devices": "장치",
|
||||
"followMe": "모두 나와 같은 설정 상태로",
|
||||
"language": "",
|
||||
"loggedIn": "",
|
||||
"moderator": "",
|
||||
"more": "",
|
||||
"language": "언어",
|
||||
"loggedIn": "{{name}}으로 로그인",
|
||||
"moderator": "마이크",
|
||||
"more": "더보기",
|
||||
"name": "이름",
|
||||
"noDevice": "없음",
|
||||
"selectAudioOutput": "오디오 출력",
|
||||
@@ -495,26 +538,28 @@
|
||||
"selectMic": "오디오",
|
||||
"startAudioMuted": "모두가 음소거를 시작합니다",
|
||||
"startVideoMuted": "모두가 비디오 비활성화로 시작합니다",
|
||||
"title": "세티"
|
||||
"title": "설정"
|
||||
},
|
||||
"settingsView": {
|
||||
"advanced": "고급",
|
||||
"alertOk": "확인",
|
||||
"alertCancel": "취소",
|
||||
"alertTitle": "경고",
|
||||
"alertURLText": "입력된 서버 URL이 잘못되었습니다",
|
||||
"buildInfoSection": "",
|
||||
"buildInfoSection": "빌드 정보",
|
||||
"conferenceSection": "회의",
|
||||
"displayName": "유저이름",
|
||||
"email": "이메일",
|
||||
"header": "세티",
|
||||
"header": "설정",
|
||||
"profileSection": "프로필",
|
||||
"serverURL": "서버 URL",
|
||||
"startWithAudioMuted": "오디오 음소거 상태로 시작",
|
||||
"startWithVideoMuted": "비디오 비활성화 상태로 시작",
|
||||
"version": ""
|
||||
"version": "버전"
|
||||
},
|
||||
"share": {
|
||||
"dialInfoText": "",
|
||||
"mainText": ""
|
||||
"mainText": "회의에 참여하려면 다음 링크를 클릭하십시오.\n{{roomUrl}}"
|
||||
},
|
||||
"speaker": "스피커",
|
||||
"speakerStats": {
|
||||
@@ -561,11 +606,11 @@
|
||||
"sharedvideo": "",
|
||||
"shareRoom": "",
|
||||
"shareYourScreen": "",
|
||||
"shortcuts": "단축키 토그",
|
||||
"shortcuts": "단축키 전환",
|
||||
"show": "",
|
||||
"speakerStats": "",
|
||||
"tileView": "",
|
||||
"toggleCamera": "카메라 토ㄱ",
|
||||
"toggleCamera": "카메라 전환",
|
||||
"videomute": "",
|
||||
"videoblur": ""
|
||||
},
|
||||
@@ -575,54 +620,58 @@
|
||||
"audioRoute": "음성 장비 선택하기",
|
||||
"authenticate": "인증 중",
|
||||
"callQuality": "품질 설정하기",
|
||||
"chat": "",
|
||||
"closeChat": "",
|
||||
"documentClose": "",
|
||||
"documentOpen": "",
|
||||
"chat": "대화 열기/닫기",
|
||||
"closeChat": "대화 닫기",
|
||||
"documentClose": "문서 공유 닫기",
|
||||
"documentOpen": "문서 공유 열기",
|
||||
"download": "앱 다운로드",
|
||||
"enterFullScreen": "전체화면 보기",
|
||||
"enterTileView": "",
|
||||
"enterTileView": "타일보기 시작",
|
||||
"exitFullScreen": "전체화면 취소",
|
||||
"exitTileView": "",
|
||||
"exitTileView": "타일보기 종료",
|
||||
"feedback": "피드백 남기기",
|
||||
"hangup": "",
|
||||
"invite": "",
|
||||
"login": "",
|
||||
"hangup": "떠나기",
|
||||
"invite": "초대",
|
||||
"login": "로그인",
|
||||
"logout": "로그아웃",
|
||||
"lowerYourHand": "",
|
||||
"lowerYourHand": "손을 내려주세요",
|
||||
"moreActions": "추가 액션",
|
||||
"mute": "마이크",
|
||||
"openChat": "",
|
||||
"moreOptions": "옵션 더보기",
|
||||
"mute": "음소거 설정/해제",
|
||||
"muteEveryone": "모두 음소거",
|
||||
"openChat": "대화 열기",
|
||||
"pip": "",
|
||||
"profile": "",
|
||||
"privateMessage": "비공개 메시지 보내기",
|
||||
"profile": "프로필 수정",
|
||||
"raiseHand": "말하기 요청/해제",
|
||||
"raiseYourHand": "",
|
||||
"Settings": "세티",
|
||||
"sharedvideo": "",
|
||||
"shareRoom": "",
|
||||
"shortcuts": "",
|
||||
"raiseYourHand": "손 들어주세요",
|
||||
"Settings": "설정",
|
||||
"sharedvideo": "YouTube 비디오 공유",
|
||||
"shareRoom": "초대하기",
|
||||
"shortcuts": "단축키보기",
|
||||
"speakerStats": "접속자 통계",
|
||||
"startScreenSharing": "",
|
||||
"startSubtitles": "",
|
||||
"stopScreenSharing": "",
|
||||
"stopSubtitles": "",
|
||||
"stopSharedVideo": "",
|
||||
"talkWhileMutedPopup": "",
|
||||
"tileViewToggle": "",
|
||||
"toggleCamera": "카메라 토ㄱ",
|
||||
"videomute": "",
|
||||
"startvideoblur": "",
|
||||
"stopvideoblur": ""
|
||||
"startScreenSharing": "화면 공유 시작",
|
||||
"startSubtitles": "자막 시작",
|
||||
"stopScreenSharing": "화면 공유 중지",
|
||||
"stopSubtitles": "자막 중지",
|
||||
"stopSharedVideo": "UouTube 비디오 공유 중지",
|
||||
"talkWhileMutedPopup": "음소거 상태입니다.",
|
||||
"tileViewToggle": "타일뷰 전환",
|
||||
"toggleCamera": "카메라 전환",
|
||||
"videomute": "카메라 시작/중지",
|
||||
"startvideoblur": "내 배경을 흐리게",
|
||||
"stopvideoblur": "배경 흐림 비활성화"
|
||||
},
|
||||
"transcribing": {
|
||||
"ccButtonTooltip": "",
|
||||
"ccButtonTooltip": "자막 시작/종료",
|
||||
"error": "레코딩이 실패했습니다. 다시 시도하십시오.",
|
||||
"expandedLabel": "",
|
||||
"failedToStart": "",
|
||||
"labelToolTip": "",
|
||||
"off": "",
|
||||
"expandedLabel": "현재 스크립트 작성 중",
|
||||
"failedToStart": "스크립트 작성을 시작하지 못했습니다.",
|
||||
"labelToolTip": "회의가 기록되고 있습니다.",
|
||||
"off": "스크립트 작성이 중지되었습니다.",
|
||||
"pending": "참석할 멤버를 기다리는 중입니다…",
|
||||
"start": "",
|
||||
"stop": "",
|
||||
"start": "자막 표시 시작",
|
||||
"stop": "자막 표시 중지",
|
||||
"tr": ""
|
||||
},
|
||||
"userMedia": {
|
||||
@@ -649,8 +698,8 @@
|
||||
},
|
||||
"videoStatus": {
|
||||
"audioOnly": "오디오 전용",
|
||||
"audioOnlyExpanded": "",
|
||||
"callQuality": "",
|
||||
"audioOnlyExpanded": "낮은 대역폭 모드에 있습니다. 이 모드에서는 오디오 및 화면 공유 만 수신합니다.",
|
||||
"callQuality": "비디오 품질",
|
||||
"hd": "HD",
|
||||
"highDefinition": "고해상도",
|
||||
"labelTooiltipNoVideo": "비디오 없음",
|
||||
@@ -666,12 +715,12 @@
|
||||
"domute": "음소거",
|
||||
"flip": "플립",
|
||||
"kick": "내보내기",
|
||||
"moderator": "",
|
||||
"mute": "",
|
||||
"moderator": "중재자",
|
||||
"mute": "참가자 음소거",
|
||||
"muted": "음소거됨",
|
||||
"remoteControl": "원격 제어",
|
||||
"show": "",
|
||||
"videomute": ""
|
||||
"show": "화면에 표시",
|
||||
"videomute": "참가자가 카메라를 중지했습니다."
|
||||
},
|
||||
"welcomepage": {
|
||||
"accessibilityLabel": {
|
||||
@@ -683,22 +732,33 @@
|
||||
"audio": "음성",
|
||||
"video": "비디오"
|
||||
},
|
||||
"calendar": "",
|
||||
"connectCalendarButton": "",
|
||||
"connectCalendarText": "",
|
||||
"enterRoomTitle": "",
|
||||
"calendar": "캘린더",
|
||||
"connectCalendarButton": "캘린더를 연결하세요",
|
||||
"connectCalendarText": "{{app}}에서 모든 회의를 보려면 캘린더를 연결하세요. 또한 캘린더에 {{provider}} 회의를 추가하고 클릭 한 번으로 시작하세요.",
|
||||
"enterRoomTitle": "새 회의 시작",
|
||||
"getHelp": "도움 받기",
|
||||
"roomNameAllowedChars": "회의 이름은 이러한 문자를 포함 할 수 없습니다.: ?, &, :, ', \", %, #.",
|
||||
"go": "계속",
|
||||
"goSmall": "계속",
|
||||
"join": "가입",
|
||||
"info": "",
|
||||
"info": "정보",
|
||||
"privacy": "개인정보",
|
||||
"recentList": "",
|
||||
"recentListDelete": "",
|
||||
"recentListEmpty": "",
|
||||
"reducedUIText": "",
|
||||
"recentList": "최근",
|
||||
"recentListDelete": "삭제",
|
||||
"recentListEmpty": "최근 목록이 현재 비어 있습니다. 팀과 채팅하면 여기에서 최근 회의를 모두 찾을 수 있습니다.",
|
||||
"reducedUIText": "{{app}}에 오신 것을 환영합니다!",
|
||||
"roomname": "방 이름 입력",
|
||||
"roomnameHint": "",
|
||||
"sendFeedback": "",
|
||||
"roomnameHint": "참여하려는 방의 이름 또는 URL을 입력하십시오. 이름을 정하고 만나는 사람들에게 같은 이름을 입력하도록 알리면됩니다.",
|
||||
"sendFeedback": "피드백 보내기",
|
||||
"terms": "이용약관",
|
||||
"title": ""
|
||||
"title": "안전하고 모든 기능을 갖춘 완전 무료 화상 회의"
|
||||
},
|
||||
"lonelyMeetingExperience": {
|
||||
"button": "초대하기",
|
||||
"youAreAlone": "회의에 참여자가 없습니다."
|
||||
},
|
||||
"helpView": {
|
||||
"header": "지원 센터"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
"kickParticipantButton": "Verwijderen",
|
||||
"kickParticipantDialog": "Weet u zeker dat u deze deelnemer wilt verwijderen?",
|
||||
"kickParticipantTitle": "Deze deelnemer verwijderen?",
|
||||
"kickTitle": "Oei! {{ParticipantDisplayName}} heeft u uit de vergadering verwijderd",
|
||||
"kickTitle": "Oei! {{participantDisplayName}} heeft u uit de vergadering verwijderd",
|
||||
"liveStreaming": "Livestreamen",
|
||||
"liveStreamingDisabledBecauseOfActiveRecordingTooltip": "Niet mogelijk tijdens opnemen",
|
||||
"liveStreamingDisabledForGuestTooltip": "Gasten kunnen geen livestream starten.",
|
||||
|
||||
@@ -512,6 +512,12 @@
|
||||
"sectionList": {
|
||||
"pullToRefresh": "Puxe para atualizar"
|
||||
},
|
||||
"security": {
|
||||
"about": "Voce pode adicionar uma $t(lockRoomPassword) em sua reunião. Participantes irão precisar informar a $t(lockRoomPassword) antes de se juntarem na reunião.",
|
||||
"aboutReadOnly": "Moderadores podem adicionar uma $t(lockRoomPassword) na reunião. Participantes irão precisar informar a $t(lockRoomPassword) antes de se juntarem na reunião",
|
||||
"insecureRoomNameWarning": "Essa sala não está protegida. Participantes indesejados poderão entrar na sua reunião. Considere configurar a segurança da sua reunião utilizando o botão de segurança.",
|
||||
"securityOptions": "Opções de segurança"
|
||||
},
|
||||
"settings": {
|
||||
"calendar": {
|
||||
"about": "A integração do calendário {{appName}} é usada para acessar com segurança o seu calendário para que ele possa ler os próximos eventos.",
|
||||
|
||||
@@ -1,62 +1,77 @@
|
||||
{
|
||||
"addPeople": {
|
||||
"add": "Pozvať",
|
||||
"addContacts": "Pozvať kontakty",
|
||||
"copyInvite": "Skopírovať pozvánku",
|
||||
"copyLink": "Skopírovať odkaz na konferenciu",
|
||||
"copyStream": "Skopírovať odkaz na živé vysielanie",
|
||||
"countryNotSupported": "Zatiaľ nepodporujeme túto krajinu.",
|
||||
"countryReminder": "Medzinárodný hovor? Prosím skontrolujte, či telefónne číslo začína smerovým číslo krajiny.",
|
||||
"disabled": "Nemôžete pozvať ďalších účastníkov.",
|
||||
"defaultEmail": "Predvolený email",
|
||||
"disabled": "Nemôžete pozvať ďalších ľudí.",
|
||||
"failedToAdd": "Nepodarilo sa pridať účastníka.",
|
||||
"footerText": "Odchádzajúce hovory sú zablokované.",
|
||||
"loading": "Hľadanie účastníkov a telefónnych čísiel",
|
||||
"googleEmail": "Google email",
|
||||
"inviteMoreHeader": "Ste sám v tejto konferencii",
|
||||
"inviteMoreMailSubject": "Pozvánka do konferencie {{appName}}",
|
||||
"inviteMorePrompt": "Pozvať ľudí",
|
||||
"linkCopied": "Odkaz skopírovaný do schránky",
|
||||
"loading": "Hľadanie ľudí a telefónnych čísiel",
|
||||
"loadingNumber": "Kontrola telefónneho čísla",
|
||||
"loadingPeople": "Hľadanie účastníkov na pozvanie",
|
||||
"loadingPeople": "Hľadanie ľudí na pozvanie",
|
||||
"noResults": "Žiadne výsledky hľadania",
|
||||
"noValidNumbers": "Prosím zadajte telefónne číslo",
|
||||
"outlookEmail": "Outlook email",
|
||||
"searchNumbers": "Zadajte telefónne čísla",
|
||||
"searchPeople": "Hľadanie účastníkov",
|
||||
"searchPeopleAndNumbers": "Hľadanie účastníkov alebo pridávanie telefónny čísel",
|
||||
"searchPeople": "Hľadanie ľudí",
|
||||
"searchPeopleAndNumbers": "Hľadať ľudí alebo pridať ich telefónne čísla",
|
||||
"shareInvite": "Zdieľať pozvánku do konferencie",
|
||||
"shareLink": "Zdieľať odkaz na pozvanie",
|
||||
"shareStream": "Zdieľať odkaz na živé vysielanie",
|
||||
"telephone": "Telefón: {{number}}",
|
||||
"title": "Pozvať účastníkov do tejto konferencie"
|
||||
"title": "Pozvať ľudí do tejto konferencie",
|
||||
"yahooEmail": "Yahoo email"
|
||||
},
|
||||
"audioDevices": {
|
||||
"bluetooth": "Bluetooth",
|
||||
"headphones": "Sluchátka",
|
||||
"headphones": "Slúchadlá",
|
||||
"phone": "Telefón",
|
||||
"speaker": "Rečník",
|
||||
"speaker": "Reproduktor",
|
||||
"none": "Žiadne zvukové zariadenia"
|
||||
},
|
||||
"audioOnly": {
|
||||
"audioOnly": "Iba zvuk"
|
||||
},
|
||||
"calendarSync": {
|
||||
"addMeetingURL": "Pridať odkaz na stretnutie",
|
||||
"addMeetingURL": "Pridať odkaz na konferenciu",
|
||||
"confirmAddLink": "Chcete pridal Jitsi odkaz do tejto udalosti?",
|
||||
"error": {
|
||||
"appConfiguration": "Integrácia s kalendárom nie je správne nastavená.",
|
||||
"generic": "Stala sa chyba. Skontrolujte si nastavenia kalendáru a skúste aktualizovať kalendár. ",
|
||||
"notSignedIn": "Stala sa chyba počas autentifikácie pre zobrazovanie kaledárových udalosti. Skontrolujte si nastavenia kalendáru a skúste sa znovu prihlásiť."
|
||||
"generic": "Stala sa chyba. Skontrolujte nastavenia kalendára a skúste obnoviť kalendár.",
|
||||
"notSignedIn": "Stala sa chyba počas autentifikácie pre zobrazenie kaledárových udalosti. Skontrolujte nastavenia kalendára a skúste sa znovu prihlásiť."
|
||||
},
|
||||
"join": "Zúčastniť sa",
|
||||
"joinTooltip": "Zúčastniť sa stretnutia",
|
||||
"nextMeeting": "nasledujúce stretnutie",
|
||||
"noEvents": "Niesú naplánované žiadne ďalšie udalosti.",
|
||||
"ongoingMeeting": "prebiehajúce stretnutie",
|
||||
"joinTooltip": "Zúčastniť sa konferencie",
|
||||
"nextMeeting": "nasledujúca konferencia",
|
||||
"noEvents": "Nie sú naplánované žiadne ďalšie udalosti.",
|
||||
"ongoingMeeting": "prebiehajúca konferencia",
|
||||
"permissionButton": "Otvoriť nastavenia",
|
||||
"permissionMessage": "Aplikácia potrebuje kalendárové oprávnenie pre zobranie termínov a stretnutí ",
|
||||
"refresh": "Aktualizovať kalendár",
|
||||
"permissionMessage": "Aplikácia potrebuje kalendárové oprávnenie pre zobranie termínov a stretnutí.",
|
||||
"refresh": "Obnoviť kalendár",
|
||||
"today": "Dnes"
|
||||
},
|
||||
"chat": {
|
||||
"error": "Chyba: vaša správa \"{{originalText}}\" nebola poslaná. Dôvod: {{error}}",
|
||||
"fieldPlaceHolder": "Zadajte sem vašu správu",
|
||||
"messagebox": "Napíšte správu",
|
||||
"messageTo": "Správa pre {{recipient}}",
|
||||
"noMessagesMessage": "V tejto konferencií ešte nie je žiadna správa. Začnite tu vašu diskusiu!",
|
||||
"messageTo": "Súkromná správa pre {{recipient}}",
|
||||
"noMessagesMessage": "V tejto konferencii ešte nie je žiadna správa. Začnite tu vašu diskusiu!",
|
||||
"nickname": {
|
||||
"popover": "Zvoľte meno",
|
||||
"title": "Zadajte sem vašu prezývku"
|
||||
"title": "Zadajte vašu prezývku"
|
||||
},
|
||||
"privateNotice": "Súkromná správa pre {{recipient}}",
|
||||
"title": "Písanie",
|
||||
"title": "Chat",
|
||||
"you": "Vy"
|
||||
},
|
||||
"chromeExtensionBanner": {
|
||||
@@ -65,54 +80,54 @@
|
||||
"dontShowAgain": "Upozornenie viac nezobrazovať"
|
||||
},
|
||||
"connectingOverlay": {
|
||||
"joiningRoom": "Vytvára sa spojenie do vašej konferencie…"
|
||||
"joiningRoom": "Pripájanie do konferencie..."
|
||||
},
|
||||
"connection": {
|
||||
"ATTACHED": "Priložený",
|
||||
"AUTHENTICATING": "Overujem",
|
||||
"AUTHENTICATING": "Overovanie",
|
||||
"AUTHFAIL": "Overenie zlyhalo",
|
||||
"CONNECTED": "Pripojený",
|
||||
"CONNECTING": "Pripájam",
|
||||
"CONNECTING": "Pripájanie",
|
||||
"CONNFAIL": "Spojenie zlyhalo",
|
||||
"DISCONNECTED": "Odpojený",
|
||||
"DISCONNECTING": "Odpájam",
|
||||
"DISCONNECTING": "Odpájanie",
|
||||
"ERROR": "Chyba",
|
||||
"RECONNECTING": "Chyba siete. Skúšam sa znova pripojiť ...",
|
||||
"FETCH_SESSION_ID": "Získavanie session-id...",
|
||||
"GET_SESSION_ID_ERROR": "Chyba pri získavaní session-id: {{code}}",
|
||||
"GOT_SESSION_ID": "Získavanie session-id... Hotovo",
|
||||
"LOW_BANDWIDTH": "Video pre {{displayName}} bolo vypnuté, aby sa ušetrila prenosová kapacita"
|
||||
},
|
||||
"connectionindicator": {
|
||||
"address": "Adresa:",
|
||||
"bandwidth": "Predpokladaný dat. tok:",
|
||||
"bitrate": "Prenos. rýchlosť",
|
||||
"bridgeCount": "Počet serverov:",
|
||||
"bandwidth": "Dátový tok:",
|
||||
"bitrate": "Prenos. rýchlosť:",
|
||||
"bridgeCount": "Počet serverov: ",
|
||||
"connectedTo": "Spojenie s:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Rýchlosť snímkovania:",
|
||||
"less": "Zobraz menej",
|
||||
"localaddress_0": "Lokálna adresa:",
|
||||
"localaddress_1": "Lokálne adresy:",
|
||||
"localaddress_2": "",
|
||||
"localport_0": "Lokálny port:",
|
||||
"localport_1": "Lokálne porty:",
|
||||
"localport_2": "",
|
||||
"more": "Zobraz viac",
|
||||
"packetloss": "Strata packetov:",
|
||||
"less": "Zobraziť menej",
|
||||
"localaddress": "Lokálna adresa:",
|
||||
"localaddress_plural": "Lokálne adresy:",
|
||||
"localport": "Lokálny port:",
|
||||
"localport_plural": "Lokálne porty:",
|
||||
"maxEnabledResolution": "send max",
|
||||
"more": "Zobraziť viac",
|
||||
"packetloss": "Strata paketov:",
|
||||
"quality": {
|
||||
"good": "Dobré",
|
||||
"inactive": "Neaktívne",
|
||||
"lost": "Stratené",
|
||||
"nonoptimal": "Nie je optimálne",
|
||||
"nonoptimal": "Neoptimálne",
|
||||
"poor": "Slabé"
|
||||
},
|
||||
"remoteaddress_0": "Vzdialená adresa:",
|
||||
"remoteaddress_1": "Vzdialené adresy:",
|
||||
"remoteaddress_2": "",
|
||||
"remoteport_0": "Vzdialený port:",
|
||||
"remoteport_1": "Vzdialené porty:",
|
||||
"remoteport_2": "",
|
||||
"remoteaddress": "Vzdialená adresa:",
|
||||
"remoteaddress_plural": "Vzdialené adresy:",
|
||||
"remoteport": "Vzdialený port:",
|
||||
"remoteport_plural": "Vzdialené porty:",
|
||||
"resolution": "Rozlíšenie:",
|
||||
"status": "Spojenie:",
|
||||
"transport": "Prenos:"
|
||||
"transport": "Prenos:",
|
||||
"transport_plural": "Prenosy:"
|
||||
},
|
||||
"dateUtils": {
|
||||
"earlier": "Skôr",
|
||||
@@ -121,16 +136,18 @@
|
||||
},
|
||||
"deepLinking": {
|
||||
"appNotInstalled": "Potrebujete aplikáciu {{app}}, aby ste sa mohli pripojiť do tejto konferencie na vašom telefóne.",
|
||||
"description": "Nič sa nestalo? Snažili sme sa otvoriť konferenciu v {{app}}. Skúste to znovu, alebo sa pripojte na konferenciu v {{app}} cez Web.",
|
||||
"descriptionWithoutWeb": "Nič sa nestalo? Snažili sme sa spustiť váš rozhovor v desktopovej aplikácií {{app}}.",
|
||||
"description": "Nič sa nestalo? Snažili sme sa otvoriť konferenciu v {{app}}. Skúste to znovu, alebo sa pripojte na konferenciu v {{app}} cez web.",
|
||||
"descriptionWithoutWeb": "Nič sa nestalo? Snažili sme sa spustiť konferenciu v desktopovej aplikácií {{app}}.",
|
||||
"downloadApp": "Stiahnutie aplikácie",
|
||||
"ifDoNotHaveApp": "Ak nemáte aplikáciu:",
|
||||
"ifHaveApp": "Ak máte aplikáciu:",
|
||||
"joinInApp": "Vstúpiť do konferencie cez aplikáciu",
|
||||
"launchWebButton": "Otvoriť na webe",
|
||||
"openApp": "Pokračovať na aplikáciu",
|
||||
"title": "Konferencia sa otvára v {{app}}...",
|
||||
"tryAgainButton": "Skúsiť znova s natívnou aplikáciou"
|
||||
},
|
||||
"defaultLink": "napr. {{url}}",
|
||||
"defaultNickname": "napr. Jane Pink",
|
||||
"defaultNickname": "napr. Ján Kováč",
|
||||
"deviceError": {
|
||||
"cameraError": "Chyba pri prístupe ku kamere",
|
||||
"cameraPermission": "Aplikácia nemá oprávnenie pristupovať ku kamere",
|
||||
@@ -140,79 +157,84 @@
|
||||
"deviceSelection": {
|
||||
"noPermission": "Oprávnenie nie je poskytnuté",
|
||||
"previewUnavailable": "Náhľad nie je dostupný",
|
||||
"selectADevice": "Vyberte zvukové zariadenie",
|
||||
"selectADevice": "Vybrať zariadenie",
|
||||
"testAudio": "Vyskúšať zvuk"
|
||||
},
|
||||
"dialog": {
|
||||
"accessibilityLabel": {
|
||||
"liveStreaming": "Živé vysielanie"
|
||||
},
|
||||
"add": "Pridať",
|
||||
"allow": "Povoliť",
|
||||
"alreadySharedVideoMsg": "Iný účastník už poskytuje video. Pri tejto konferencií môže poskytovať súčasne iba jeden účastník.",
|
||||
"alreadySharedVideoTitle": "Naraz sa dá poskytovať iba jedno video",
|
||||
"alreadySharedVideoMsg": "Iný účastník už zdieľa video. Pri tejto konferencií môže zdieľať video iba jeden účastník.",
|
||||
"alreadySharedVideoTitle": "Je možné zdieľať iba jedno video",
|
||||
"applicationWindow": "Okno aplikácie",
|
||||
"Back": "Späť",
|
||||
"cameraConstraintFailedError": "Vaša kamera nespĺňa potrebné požiadavky.",
|
||||
"cameraNotFoundError": "Kamera nebola nájdená.",
|
||||
"cameraNotSendingData": "Kamera nie je dostupná. Skontrolujte či iná aplikácia používa kameru, vyberte inú kameru v nastaveniach ale znovu spustite aplikáciu.",
|
||||
"cameraNotSendingData": "Kamera nie je dostupná. Skontrolujte či iná aplikácia používa kameru, vyberte inú kameru v nastaveniach alebo znovu spustite aplikáciu.",
|
||||
"cameraNotSendingDataTitle": "Prístup na kameru nie je možný.",
|
||||
"cameraPermissionDeniedError": "Nebolo udelené oprávnenie používať kameru. Napriek tomu sa môže zúčastniť na konferencií, ale ostatný účastníci vás nebudu vidieť. Pre pridelenie oprávnenia môžete použiť ikonu kamery na adresnej lište.",
|
||||
"cameraPermissionDeniedError": "Nebolo udelené oprávnenie používať kameru. Napriek tomu sa môže zúčastniť na konferencií, ale ostatní účastníci vás nebudu vidieť. Pre pridelenie oprávnenia môžete použiť ikonu kamery na adresnej lište.",
|
||||
"cameraUnknownError": "Z neznámeho dôvodu sa kamera nedá použiť.",
|
||||
"cameraUnsupportedResolutionError": "Táto kamera nepodporuje požadované rozlíšenie.",
|
||||
"cameraUnsupportedResolutionError": "Kamera nepodporuje požadované rozlíšenie.",
|
||||
"Cancel": "Zrušiť",
|
||||
"close": "Zatvoriť",
|
||||
"conferenceDisconnectMsg": "Skontrolujte prípadne vaše sieťové pripojenie. Pripájam znovu o {{seconds}} sekúnd...",
|
||||
"conferenceDisconnectTitle": "Vaše spojenie bolo prerušené.",
|
||||
"conferenceReloadMsg": "Snažíme sa to napraviť. Pripájam znovu o {{seconds}} sekund...",
|
||||
"conferenceReloadTitle": "Žiaľ niečo sa nepodarilo.",
|
||||
"conferenceReloadTitle": "Spojenie sa prerušilo.",
|
||||
"confirm": "Potvrdiť",
|
||||
"confirmNo": "Nie",
|
||||
"confirmYes": "Áno",
|
||||
"connectError": "Oops! Niečo je zle a nemôžem sa pripojiť do konferencie.",
|
||||
"connectErrorWithMsg": "Oops! Niečo je zle a nemôžem sa pripojiť do konferencie. Správa: {{msg}}",
|
||||
"connectError": "Niečo je zle a nemôžem sa pripojiť do konferencie.",
|
||||
"connectErrorWithMsg": "Niečo je zle a nemôžem sa pripojiť do konferencie. Správa: {{msg}}",
|
||||
"connecting": "Pripájam",
|
||||
"contactSupport": "Spojiť sa s podporou",
|
||||
"copy": "Kopírovať",
|
||||
"dismiss": "Zavrieť",
|
||||
"displayNameRequired": "Ahoj! Ako sa voláš?",
|
||||
"done": "Hotovo",
|
||||
"e2eeDescription": "Koncové šifrovanie (End-to-End Encryption, E2EE) je momentálne EXPERIMENTÁLNE. Zapnutie koncového šifrovania znemožní použitie serverových služieb ako: nahrávanie, živé vysielanie a účasť cez telefón. Do konferencie je možné vstúpiť len s prehliadačom, ktorý podporuje vložiteľné prúdy (insertable streams).",
|
||||
"e2eeLabel": "E2EE kľúč",
|
||||
"e2eeNoKey": "žiadny",
|
||||
"e2eeToggleSet": "Nastaviť kľúč",
|
||||
"e2eeSet": "Nastaviť",
|
||||
"e2eeWarning": "VAROVANIE: NIektorí účastníci nemajú podporu pre koncové šifrovanie. Ak ho zapnete, nebudú Vás vidieť ani počuť.",
|
||||
"enterDisplayName": "Prosím zadajte sem vaše meno",
|
||||
"error": "Chyba",
|
||||
"externalInstallationMsg": "Zlyhanie pri inštalácií rozšírenia pre zdieľanie prac. plochy",
|
||||
"externalInstallationTitle": "Potrebné rozšírenie:",
|
||||
"goToStore": "",
|
||||
"gracefulShutdown": "Naša služba je momentálne vypnutá pre údržbu. Skúste to neskor.",
|
||||
"gracefulShutdown": "Služba je momentálne vypnutá pre údržbu. Skúste to neskor.",
|
||||
"grantModeratorDialog": "Chcete naozaj tohoto účastníka urobiť moderatorom?",
|
||||
"grantModeratorTitle": "Urobiť moderatorom",
|
||||
"IamHost": "Ja som hostiteľ",
|
||||
"incorrectRoomLockPassword": "Nesprávne heslo",
|
||||
"incorrectPassword": "Používateľské meno alebo heslo je nesprávne",
|
||||
"inlineInstallationMsg": "Musí byť nainštalované rozšírenie pre zdieľanie pracovnej prochy.",
|
||||
"inlineInstallExtension": "Teraz inštalovať",
|
||||
"internalError": "Ups! Niečo nefunguje. Vyskytla sa nasledujúca chyba: {{error}}",
|
||||
"internalErrorTitle": "Interná chyba",
|
||||
"kickMessage": "Pre podrobnosti sa môžete spojiť s {{participantDisplayName}}.",
|
||||
"kickParticipantButton": "Odstrániť",
|
||||
"kickParticipantDialog": "Skutočne chcete odstrániť tohto účastnika?",
|
||||
"kickParticipantTitle": "Odstrániť účastníka?",
|
||||
"kickTitle": "Ouch! {{participantDisplayName}} vás odstránil zo stretnutia.",
|
||||
"kickTitle": "{{participantDisplayName}} vás odstránil z konferencie.",
|
||||
"liveStreaming": "Živé vysielanie",
|
||||
"liveStreamingDisabledBecauseOfActiveRecordingTooltip": "Nie je možné keď je aktívne nahrávanie",
|
||||
"liveStreamingDisabledForGuestTooltip": "Hostia nemôžu začať živé vysielanie.",
|
||||
"liveStreamingDisabledTooltip": "Štartovanie živého vysielania je vypnuté.",
|
||||
"liveStreamingDisabledTooltip": "Spustenie živého vysielania je zakázané.",
|
||||
"lockMessage": "Zlyhanie pri pokuse o zabezpečenie konferencie.",
|
||||
"lockRoom": "Pridať stretnutie $t(lockRoomPasswordUppercase)",
|
||||
"lockRoom": "Pridať $t(lockRoomPassword)",
|
||||
"lockTitle": "Zabezpečenie zlyhalo",
|
||||
"logoutQuestion": "Ste si istý, že sa chcete odhlásiť a skončiť konferenciu?",
|
||||
"logoutTitle": "Odhlásiť",
|
||||
"maxUsersLimitReached": "Bol dosiahnutý maximálny počet účastníkov. Konferencia je plná. Spojte sa prosím s organizátorom stretnutia, alebo to skúste neskôr.",
|
||||
"maxUsersLimitReached": "Bol dosiahnutý maximálny počet účastníkov. Konferencia je plná. Spojte sa prosím s organizátorom konferencie, alebo to skúste neskôr.",
|
||||
"maxUsersLimitReachedTitle": "Dosiahnutý maximálny počet účastníkov",
|
||||
"micConstraintFailedError": "Váš mikrofón nespĺňa potrebné požiadavky.",
|
||||
"micNotFoundError": "Mikrofón nebol nájdený.",
|
||||
"micNotSendingData": "Choďte do nastavení vašeho počítača, aby ste odblokovali stlmenie vášho mikrofónu a upravte jeho úroveň.",
|
||||
"micNotSendingDataTitle": "Mikrofón je stlmený vašimi systémovými nastaveniami.",
|
||||
"micPermissionDeniedError": "Nebolo udelené oprávnenie používať mikrofón. Napriek tomu sa môže zúčastniť na konferencií, ale ostatný účastníci vás nebudú počuť. Pre pridelenie oprávnenia môžete použiť ikonu kamery na adresnej lište.",
|
||||
"micPermissionDeniedError": "Nebolo udelené oprávnenie používať mikrofón. Napriek tomu sa môže zúčastniť na konferencií, ale ostatní účastníci vás nebudú počuť. Pre pridelenie oprávnenia môžete použiť ikonu kamery na adresnej lište.",
|
||||
"micUnknownError": "Mikrofón sa nedá použiť z neznámeho dôvodu.",
|
||||
"muteEveryoneElseDialog": "Keď všetkým vypnete mikrofón, nedokážete spať zapnuť mikrofóny. Účastníci si ale môžu zapnúť mikrofóny sami.",
|
||||
"muteEveryoneElseDialog": "Keď všetkým vypnete mikrofóny, nedokážete ich späť zapnúť. Účastníci si ale môžu zapnúť mikrofóny sami.",
|
||||
"muteEveryoneElseTitle": "Vypnúť mikrofón všetkým okrem {{whom}}?",
|
||||
"muteEveryoneDialog": "Chcete naozaj všetkým vypnúť mikrofón. Keď všetkým vypnete mikrofón, nedokážete spať zapnúť mikrofóny. Účastníci si ale môžu zapnúť mikrofóny sami.",
|
||||
"muteEveryoneDialog": "Chcete naozaj všetkým vypnúť mikrofón. Keď všetkým vypnete mikrofóny, nedokážete ich späť zapnúť. Účastníci si ale môžu zapnúť mikrofóny sami.",
|
||||
"muteEveryoneTitle": "Všetkým vypnúť mikrofón?",
|
||||
"muteEveryoneSelf": "seba samého",
|
||||
"muteEveryoneStartMuted": "Všetci odteraz začínajú s vypnutým mikrofónom",
|
||||
@@ -222,33 +244,34 @@
|
||||
"muteParticipantTitle": "Vypnúť účastníkovi mikrofón?",
|
||||
"Ok": "Ok",
|
||||
"passwordLabel": "$t(lockRoomPasswordUppercase)",
|
||||
"passwordNotSupported": "Nastavovanie $t(lockRoomPassword) nie je podporované.",
|
||||
"passwordNotSupported": "$t(lockRoomPasswordUppercase) nie je podporované.",
|
||||
"passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) nie je podporované",
|
||||
"passwordRequired": "$t(lockRoomPasswordUppercase) je potrebné",
|
||||
"popupError": "Váš prehliadať blokuje vyskakovacie okná tejto stránky. Prosím aktivujte vyskakovacie okná v bezpečnostných nastaveniach vašeho prehliadača a skúste znovu.",
|
||||
"passwordRequired": "Prihlásenie",
|
||||
"popupError": "Váš prehliadač blokuje vyskakovacie okná tejto stránky. Prosím aktivujte vyskakovacie okná v bezpečnostných nastaveniach vašeho prehliadača a skúste znovu.",
|
||||
"popupErrorTitle": "Vyskakovacie okná sú zablokované",
|
||||
"readMore": "viac",
|
||||
"recording": "Nahrávanie",
|
||||
"recordingDisabledBecauseOfActiveLiveStreamingTooltip": "Nie je možné keď je aktívny živý prenos",
|
||||
"recordingDisabledForGuestTooltip": "Hostia nemôžu začať nahrávanie.",
|
||||
"recordingDisabledTooltip": "Štartovanie nahrávania je vypnuté.",
|
||||
"rejoinNow": "Teraz sa znovu pridať.",
|
||||
"recordingDisabledTooltip": "Spustenie nahrávania je zakázané.",
|
||||
"rejoinNow": "Pripojiť hneď",
|
||||
"remoteControlAllowedMessage": "{{user}} prijal požiadavku o vzdialené ovládanie.",
|
||||
"remoteControlDeniedMessage": "{{user}} odmietol prijal požiadavku o vzdialené ovládanie.",
|
||||
"remoteControlDeniedMessage": "{{user}} odmietol požiadavku o vzdialené ovládanie.",
|
||||
"remoteControlErrorMessage": "Stala sa chyba počas žiadania o vzdialené ovládanie od {{user}}",
|
||||
"remoteControlRequestMessage": "Povolíte {{user}} ovládať vášu pracovnú plochu?",
|
||||
"remoteControlShareScreenWarning": "Pozor, keď povolíte požiadavku budete zdielať vašu obrazovku!",
|
||||
"remoteControlStopMessage": "Vzdialené ovládanie bolo ukončené.",
|
||||
"remoteControlTitle": "Vzdialené ovládanie",
|
||||
"Remove": "Odstrániť",
|
||||
"removePassword": "$t(lockRoomPassword) odstránené",
|
||||
"removeSharedVideoMsg": "Ste si istý že chcete odstrániť zdielané video?",
|
||||
"removeSharedVideoTitle": "Odstrániť zdielané video",
|
||||
"removePassword": "$t(lockRoomPasswordUppercase) odstránené",
|
||||
"removeSharedVideoMsg": "Naozaj chcete odstrániť zdieľané video?",
|
||||
"removeSharedVideoTitle": "Odstrániť zdieľané video",
|
||||
"reservationError": "Systémová chyba rezervácie",
|
||||
"reservationErrorMsg": "Chyba: {{code}}, správa: {{msg}}",
|
||||
"retry": "Skúsiť znovu",
|
||||
"screenSharingFailedToInstall": "Ups! Nepodarilo sa nainštalovať rozšírenie pre zdieľanie obrazovky.",
|
||||
"screenSharingFailedToInstallTitle": "Chyba v inštalácii rozšírenie pre zdieľanie obrazovky",
|
||||
"screenSharingFirefoxPermissionDeniedError": "Niečo sa nepodarilo pri pokuse o zdielanie obrazovky. Skontrolujte prosím či ste dali oprávnenie v prehliadači.",
|
||||
"screenSharingFirefoxPermissionDeniedTitle": "Nepodarilo sa zdielať obrazovku",
|
||||
"screenSharingAudio": "Zdieľať zvuk",
|
||||
"screenSharingFailed": "Nie je možné spustiť zdieľanie obrazovky!",
|
||||
"screenSharingFailedTitle": "Zdieľanie obrazovky zlyhalo!",
|
||||
"screenSharingPermissionDeniedError": "Ups! Niečo sa nepodarilo pri žiadaní o oprávnenie zdielať obrazovku. Prosím aktualizovať a skúsiť znovu.",
|
||||
"sendPrivateMessage": "Dostali ste súkromnú správu. Chceli ste na ňu odpovedať súkromne, alebo chcete poslať správu skupine?",
|
||||
"sendPrivateMessageCancel": "Poslať skupine",
|
||||
@@ -258,26 +281,26 @@
|
||||
"sessTerminated": "Volanie ukončené",
|
||||
"Share": "Zdieľať",
|
||||
"shareVideoLinkError": "Prosím, zadajte správny Youtube odkaz.",
|
||||
"shareVideoTitle": "Zdielať video",
|
||||
"shareVideoTitle": "Zdieľať video",
|
||||
"shareYourScreen": "Zdielať obrazovku",
|
||||
"shareYourScreenDisabled": "Zdieľanie obrazovky vypnuté.",
|
||||
"shareYourScreenDisabledForGuest": "Hostia nemôžu zdielať obrazovku.",
|
||||
"startLiveStreaming": "Spustiť priamy prenos",
|
||||
"startLiveStreaming": "Spustiť živý prenos",
|
||||
"startRecording": "Začať záznam",
|
||||
"startRemoteControlErrorMessage": "Chyba pri pokuse o začatie vzdialeného riadenia!",
|
||||
"stopLiveStreaming": "Prerušiť priamy prenos",
|
||||
"startRemoteControlErrorMessage": "Chyba pri pokuse o začatie vzdialeného ovládania!",
|
||||
"stopLiveStreaming": "Zastaviť živý prenos",
|
||||
"stopRecording": "Zastaviť záznam",
|
||||
"stopRecordingWarning": "Chcete zastaviť záznam?",
|
||||
"stopStreamingWarning": "Chcete prerušiť priamy prenos",
|
||||
"streamKey": "Klúč živého vysielania",
|
||||
"stopStreamingWarning": "Chcete zastaviť priamy prenos?",
|
||||
"streamKey": "Kľúč živého vysielania",
|
||||
"Submit": "OK",
|
||||
"thankYou": "Ďakujeme vám za používanie {{appName}}!",
|
||||
"thankYou": "Ďakujeme za používanie {{appName}}!",
|
||||
"token": "token",
|
||||
"tokenAuthFailed": "Prepáčte, nie ste oprávnený zúčastniť tejto sa konferencie.",
|
||||
"tokenAuthFailedTitle": "Overenie zlyhalo",
|
||||
"transcribing": "",
|
||||
"unlockRoom": "Odstrániť stretnutie $t(lockRoomPassword)",
|
||||
"userPassword": "užívateľské heslo",
|
||||
"unlockRoom": "Odstrániť $t(lockRoomPassword)",
|
||||
"userPassword": "heslo",
|
||||
"WaitForHostMsg": "Konferencia <b>{{room}}</b> sa ešte nezačala. Autorizujte sa prosím ak ste hostiteľ. V opačnom prípade čakajte na hostiteľa.",
|
||||
"WaitForHostMsgWOk": "Konferencia <b>{{room}}</b> sa ešte nezačala. Ak ste hostiteľ autorizujte sa stlačením Ok. V opačnom prípade čakajte na hostiteľa.",
|
||||
"WaitingForHost": "Čakám na hostiteľa ...",
|
||||
@@ -288,7 +311,10 @@
|
||||
"statusMessage": "je teraz {{status}}"
|
||||
},
|
||||
"documentSharing": {
|
||||
"title": "Zdielaný dokument"
|
||||
"title": "Zdieľaný dokument"
|
||||
},
|
||||
"e2ee": {
|
||||
"labelToolTip": "Zvuková a obrazová komunikácia je koncovo šifrovaná"
|
||||
},
|
||||
"feedback": {
|
||||
"average": "Priemerný",
|
||||
@@ -308,8 +334,8 @@
|
||||
},
|
||||
"info": {
|
||||
"accessibilityLabel": "Zobraziť informácie",
|
||||
"addPassword": "$t(lockRoomPassword) pridať",
|
||||
"cancelPassword": "$t(lockRoomPassword) zmazať",
|
||||
"addPassword": "Nastaviť $t(lockRoomPassword)",
|
||||
"cancelPassword": "Zrušiť $t(lockRoomPassword)",
|
||||
"conferenceURL": "Odkaz:",
|
||||
"country": "Krajina",
|
||||
"dialANumber": "Aby ste sa zúčastnili stretnutia, zavolajte jedno z týchto čísel a zadajte pin.",
|
||||
@@ -322,9 +348,9 @@
|
||||
"inviteLiveStream": "Kliknite túto linku {{url}}, pre zobrazenie živého vysielania z tohto stretnutia.",
|
||||
"invitePhone": "Keď sa chcete pripojiť cez telefón, klikni na: {{number}},,{{conferenceID}}#\n",
|
||||
"invitePhoneAlternatives": "Hľadáte iné pripojovacie číslo? Pripojovacie čísla pre konferenciu: {{{url}}\n\n\n\nTaktiež pokiaľ sa telefonicky pripájate cez konferenčný celomiestnostný telefón pripojte sa bez prenosu zvuku {{silentUrl}}",
|
||||
"inviteURLFirstPartGeneral": "Ste pozývaný pripojiť sa na stretnutie.",
|
||||
"inviteURLFirstPartPersonal": "{{name}} vás pozýva na stretnutie.",
|
||||
"inviteURLSecondPart": "\n Zúčastniť sa stretnutia:\n{{url}}\n",
|
||||
"inviteURLFirstPartGeneral": "Ste pozvaný do konferencie.",
|
||||
"inviteURLFirstPartPersonal": "{{name}} vás pozýva do konferencie.\n",
|
||||
"inviteURLSecondPart": "\nVstúpiť do konferencie:\n{{url}}\n",
|
||||
"liveStreamURL": "Živý prenos:",
|
||||
"moreNumbers": "Ďalšie telefónne čísla",
|
||||
"noNumbers": "Žiadne pripojovacie telefónne čísla.",
|
||||
@@ -368,6 +394,8 @@
|
||||
"videoQuality": "Nastavenie kvality volania"
|
||||
},
|
||||
"liveStreaming": {
|
||||
"limitNotificationDescriptionWeb": "Živé vysielanie je obmedzené na {{limit}} minút. Pre neobmedzené vysielanie skúste <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"limitNotificationDescriptionNative": "Živé vysielanie je obmedzené na {{limit}} minút. Pre neobmedzené vysielanie skúste {{app}}.",
|
||||
"busy": "Chystajú sa zdroje pre vysielanie. Skúste znova za pár minút.",
|
||||
"busyTitle": "Všetky vysielacie inštancie sú obsadené",
|
||||
"changeSignIn": "Prepnúť konto",
|
||||
@@ -375,19 +403,19 @@
|
||||
"chooseCTA": "Vyberte vysielaciu možnosť. Ste prihlásený ako {{email}}",
|
||||
"enterStreamKey": "Zadajte meno/heslo pre YouTube vysielanie.",
|
||||
"error": "Živé vysielanie zlyhalo. Prosím skúste to znovu.",
|
||||
"errorAPI": "Došlo chybe pri prístupe k vašemu YouTube vysielaniu. Prosím skúste sa znovu prihlásiť.",
|
||||
"errorAPI": "Došlo k chybe pri prístupe k vašemu YouTube vysielaniu. Prosím skúste sa znovu prihlásiť.",
|
||||
"errorLiveStreamNotEnabled": "Živé vysielanie pre {{email}} nie je aktivované. Aktivujte živé vysielanie, alebo sa prihláste pomocou konta s aktivovaným živým vysielaním.",
|
||||
"expandedOff": "Živé vysielanie bolo zastavené",
|
||||
"expandedOn": "Stretnutie je momentálne vysielané na YouTube.",
|
||||
"expandedPending": "Spúšťa živé vysielanie...",
|
||||
"failedToStart": "Nepodarilo sa naštartovať živé vysielanie",
|
||||
"failedToStart": "Nepodarilo sa spustiť živé vysielanie",
|
||||
"getStreamKeyManually": "Nepodarilo sa získať žiadne živé vysielania. Skúste získať kľúč pre živé vysielanie z YouTube.",
|
||||
"invalidStreamKey": "Kľúč pre živé vysielanie je nesprávny.",
|
||||
"off": "Živé vysielanie ukončené",
|
||||
"offBy": "{{name}} ukončil živé vysielanie",
|
||||
"on": "Živé vysielanie",
|
||||
"onBy": "{{name}} začal živé vysielanie",
|
||||
"pending": "Štartuje sa živé vysielanie...",
|
||||
"pending": "Spúšťa sa živé vysielanie...",
|
||||
"serviceName": "Služba pre živé vysielanie",
|
||||
"signedInAs": "Ste prihlásený ako:",
|
||||
"signIn": "Prihlásiť sa pomocou Google",
|
||||
@@ -395,7 +423,9 @@
|
||||
"signOut": "Odhlásiť",
|
||||
"start": "Začať živé vysielanie",
|
||||
"streamIdHelp": "Čo je to?",
|
||||
"unavailableTitle": "Živé vysielanie nie je k dispozícií"
|
||||
"unavailableTitle": "Živé vysielanie nie je k dispozícií",
|
||||
"youtubeTerms": "Podmienky poskytovania služby YouTube",
|
||||
"googlePrivacyPolicy": "Pravidlá ochrany súkromia Google"
|
||||
},
|
||||
"localRecording": {
|
||||
"clientState": {
|
||||
@@ -403,19 +433,19 @@
|
||||
"on": "Zapnutý",
|
||||
"unknown": "Neznámy"
|
||||
},
|
||||
"dialogTitle": "Lokálne ovládacie prvky nahrávania",
|
||||
"dialogTitle": "Ovládacie prvky lokálneho nahrávania",
|
||||
"duration": "Dĺžka",
|
||||
"durationNA": "neznáma",
|
||||
"encoding": "Kódovanie",
|
||||
"label": "",
|
||||
"labelToolTip": "Lokálny nahrávanie je aktivovaný",
|
||||
"labelToolTip": "Lokálne nahrávanie je aktivovaný",
|
||||
"localRecording": "Lokálne nahrávanie",
|
||||
"me": "Ja",
|
||||
"messages": {
|
||||
"engaged": "Lokálne nahrávanie je spustené",
|
||||
"finished": "Nahrávanie sedenia {{token}} je ukončené. Prosím pošlite nahratý súbor moderátorovi.",
|
||||
"finishedModerator": "Nahrávanie sedenia {{token}} je ukončené. Bola uložená nahrávka lokálnej stopy. Poproste ostatných účastníkov, aby vám poslali ich nahrávky.",
|
||||
"notModerator": "Nieste moderátor. Nemôže začať, alebo skončiť lokálne nahrávanie."
|
||||
"notModerator": "Nie ste moderátor. Nemôže začať, alebo skončiť lokálne nahrávanie."
|
||||
},
|
||||
"moderator": "Moderátor",
|
||||
"no": "Nie",
|
||||
@@ -438,17 +468,17 @@
|
||||
"focusFail": "{{component}} je nedostupný - skúste znova za {{ms}} sek",
|
||||
"grantedTo": "Práva moderátora boli udelené {{to}}!",
|
||||
"invitedOneMember": "{{displayName}} bol pozvaný",
|
||||
"invitedThreePlusMembers": "{{name}} a {{count}} ďalší boli pozvaný",
|
||||
"invitedTwoMembers": "{{first}} a {{second}} boli pozvaný",
|
||||
"kickParticipant": "Pre ďalšie podrobnosti sa môže obrátiť na {{participantDisplayName}}",
|
||||
"invitedThreePlusMembers": "{{name}} a {{count}} ďalší boli pozvaní",
|
||||
"invitedTwoMembers": "{{first}} a {{second}} boli pozvaní",
|
||||
"kickParticipant": "{{kicked}} bol odstránený účastníkom {{kicker}}",
|
||||
"me": "Ja",
|
||||
"moderator": "Boli vám udelené práva moderátora!",
|
||||
"muted": "Začali ste rozhovor s vypnutým mikrofónom.",
|
||||
"mutedTitle": "Boli ste stíšený!",
|
||||
"mutedRemotelyTitle": "{{participantDisplayName}} vás stíšil",
|
||||
"mutedRemotelyTitle": "{{participantDisplayName}} vám vypol mikrofón",
|
||||
"mutedRemotelyDescription": "Kedykoľvek môžete stíšenie zrušiť, keď ste prichystaný rozprávať. Keď skončite môžete sa znova stíšiť, aby ste znížili hluk na stretnutí.",
|
||||
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) bolo odstránené iným účastníkom",
|
||||
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) bolo nastavené iným účastníkom",
|
||||
"passwordRemovedRemotely": "Iný účastník odstránil $t(lockRoomPassword)",
|
||||
"passwordSetRemotely": "Iný účastník nastavil $t(lockRoomPassword)",
|
||||
"raisedHand": "{{name}} chce hovoriť",
|
||||
"somebody": "Niekto",
|
||||
"startSilentTitle": "Pripojili ste sa bez zvukového výstupu!",
|
||||
@@ -458,11 +488,49 @@
|
||||
"unmute": "Zapnúť mikrofón",
|
||||
"newDeviceCameraTitle": "Bola zistená nová kamera",
|
||||
"newDeviceAudioTitle": "Bolo zistené nové audio zariadenie",
|
||||
"newDeviceAction": "Použiť"
|
||||
"newDeviceAction": "Použiť",
|
||||
"OldElectronAPPTitle": "Bezpečnostná hrozba!",
|
||||
"oldElectronClientDescription1": "Používate starú verziu klienta Jitsi Meet, ktorá má známe zraniteľnosti. Aktualizujte na ",
|
||||
"oldElectronClientDescription2": "najnovšiu verziu",
|
||||
"oldElectronClientDescription3": " teraz!"
|
||||
},
|
||||
"passwordSetRemotely": "nastavené iným účastníkom",
|
||||
"passwordDigitsOnly": "až {{number}} číslic",
|
||||
"poweredby": "založené na",
|
||||
"prejoin": {
|
||||
"audioAndVideoError": "Chyba zvuku a videa:",
|
||||
"audioOnlyError": "Chyba zvuku:",
|
||||
"audioTrackError": "Nemôžem vytvoriť zvukovú stopu.",
|
||||
"callMe": "Zavolať mi",
|
||||
"callMeAtNumber": "Zavolajte mi na toto číslo:",
|
||||
"configuringDevices": "Konfigurácia zariedení...",
|
||||
"connectedWithAudioQ": "Ste pripojení so zvukom?",
|
||||
"copyAndShare": "Kopírovať a zdieľať odkaz",
|
||||
"dialInMeeting": "Volanie dnu do konferencie",
|
||||
"dialInPin": "Volajte dnu do konferencie a zadajte PIN kód:",
|
||||
"dialing": "Vytáčanie",
|
||||
"doNotShow": "Viac nezobrazovať",
|
||||
"errorDialOut": "Nemôžem volať von",
|
||||
"errorDialOutDisconnected": "Nemôžem volať von. Odpojené",
|
||||
"errorDialOutFailed": "Nemôžem volať von. Volanie zlyhalo",
|
||||
"errorDialOutStatus": "Chyba pri získavaní stavu volania",
|
||||
"errorStatusCode": "Chyba volania von, kód: {{status}}",
|
||||
"errorValidation": "Overenie čísla zlyhalo",
|
||||
"iWantToDialIn": "Chcem volať dnu",
|
||||
"joinAudioByPhone": "Vstúpiť so zvukom cez telefón",
|
||||
"joinMeeting": "Vstúpiť do konferencie",
|
||||
"joinWithoutAudio": "Vstúpiť bez zvuku",
|
||||
"initiated": "Hovor začatý",
|
||||
"linkCopied": "Odkaz skopírovaný do schránky",
|
||||
"lookGood": "Váš mikrofón funguje správne",
|
||||
"or": "alebo",
|
||||
"calling": "Volanie",
|
||||
"startWithPhone": "Začať so zvukom cez telefón",
|
||||
"screenSharingError": "Chyba pri zdieľaní obrazovky:",
|
||||
"videoOnlyError": "Chyba videa:",
|
||||
"videoTrackError": "Nemôžem vytvoriť video stopu.",
|
||||
"viewAllNumbers": "zobraziť všetky čísla"
|
||||
},
|
||||
"presenceStatus": {
|
||||
"busy": "Obsadený",
|
||||
"calling": "Je volaný",
|
||||
@@ -485,6 +553,8 @@
|
||||
},
|
||||
"raisedHand": "Chcel by som hovoriť",
|
||||
"recording": {
|
||||
"limitNotificationDescriptionWeb": "Nahrávanie je obmedzené na {{limit}} minút. Pre neobmedzené nahrávanie skúste <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"limitNotificationDescriptionNative": "Nahrávanie je obmedzené na {{limit}} minút. Pre neobmedzené nahrávanie skúste <3>{{app}}</3>.",
|
||||
"authDropboxText": "Nahrať na Dropbox",
|
||||
"availableSpace": "Dostupná kapacita {{spaceLeft}} MB (ca. {{duration}} minút nahrávania)",
|
||||
"beta": "BETA",
|
||||
@@ -514,6 +584,12 @@
|
||||
"sectionList": {
|
||||
"pullToRefresh": "Potiahnuť pre aktualizáciu"
|
||||
},
|
||||
"security": {
|
||||
"about": "Môžete nastaviť $t(lockRoomPassword) pre konferenciu. Účastníci budú musieť zadať $t(lockRoomPassword), aby mohli vstúpiť.",
|
||||
"aboutReadOnly": "Moderátor može nastaviť $t(lockRoomPassword) pre konferenciu. Účastníci budú musieť zadať $t(lockRoomPassword), aby mohli vstúpiť.",
|
||||
"insecureRoomNameWarning": "Názov konferencie nie je bezpečný. Môžu do nej vstúpiť neželaní účastníci. Zvážte zabezpečenie konferencie tlačidlom.",
|
||||
"securityOptions": "Nastavenie zabezpečenia"
|
||||
},
|
||||
"settings": {
|
||||
"calendar": {
|
||||
"about": "Používa sa kalendárová integrácia {{appName}} pre zabezpečený prístup ku vašemu kalendáru.",
|
||||
@@ -526,6 +602,7 @@
|
||||
"followMe": "Všetci sledujú mňa",
|
||||
"language": "Jazyk",
|
||||
"loggedIn": "Prihlásený ako {{name}}",
|
||||
"microphones": "Mikrofóny",
|
||||
"moderator": "Moderátor",
|
||||
"more": "Viac",
|
||||
"name": "Meno",
|
||||
@@ -533,6 +610,7 @@
|
||||
"selectAudioOutput": "Zvukový výstup",
|
||||
"selectCamera": "Kamera",
|
||||
"selectMic": "Mikrofón",
|
||||
"speakers": "Reproduktory",
|
||||
"startAudioMuted": "Pri pripojení všetkým stlmiť zvuk",
|
||||
"startVideoMuted": "Pri pripojení všetkým vypnúť video",
|
||||
"title": "Nastavenia"
|
||||
@@ -540,12 +618,15 @@
|
||||
"settingsView": {
|
||||
"advanced": "Rozšírené",
|
||||
"alertOk": "OK",
|
||||
"alertCancel": "Zrušiť",
|
||||
"alertTitle": "Upozornenie",
|
||||
"alertURLText": "Zadaná serverový URL je neplatná",
|
||||
"alertURLText": "Zadaná serverová URL je neplatná",
|
||||
"buildInfoSection": "informácie o kompilácií",
|
||||
"conferenceSection": "Konferencia",
|
||||
"disableCallIntegration": "Deaktivovať integráciu s natívnymi volaniami",
|
||||
"disableP2P": "Deaktivovať mód s koncovými zariadeniami",
|
||||
"disableCrashReporting": "Vypnúť oznamovanie pádov",
|
||||
"disableCrashReportingWarning": "Naozak chcete vypnúť oznamovanie pádov? Nastavenie bude aktívne po reštartovaní aplikácie.",
|
||||
"displayName": "Ukázať",
|
||||
"email": "E-mail",
|
||||
"header": "Nastavenia",
|
||||
@@ -562,10 +643,10 @@
|
||||
},
|
||||
"speaker": "Rečník",
|
||||
"speakerStats": {
|
||||
"hours": "",
|
||||
"minutes": "",
|
||||
"hours": "{{count}}h",
|
||||
"minutes": "{{count}}m",
|
||||
"name": "Meno",
|
||||
"seconds": "",
|
||||
"seconds": "{{count}}s",
|
||||
"speakerStats": "Štatistiky rečníka",
|
||||
"speakerTime": "Čas rečníka"
|
||||
},
|
||||
@@ -576,7 +657,7 @@
|
||||
"suspendedoverlay": {
|
||||
"rejoinKeyTitle": "Znovu pripojiť",
|
||||
"text": "Stlačte tlačidlo <i>Znovu pripojiť</i> na opätovné spojenie.",
|
||||
"title": "Konferencia sa prerušila lebo váš počítač bol uspaní."
|
||||
"title": "Konferencia sa prerušila lebo váš počítač bol uspaný."
|
||||
},
|
||||
"toolbar": {
|
||||
"accessibilityLabel": {
|
||||
@@ -587,14 +668,17 @@
|
||||
"chat": "Zapnúť/vypnúť textovú diskusiu",
|
||||
"document": "Zatvoriť zdielaný dokument",
|
||||
"download": "Stiahnuť našu aplikáciu",
|
||||
"e2ee": "Koncové šifrovanie",
|
||||
"feedback": "Zanechať spätnú väzbu",
|
||||
"fullScreen": "Zapnúť/vypnúť zobrazenie na celú obrazovku",
|
||||
"grantModerator": "Urobiť moderátorom",
|
||||
"hangup": "Ukončiť volanie",
|
||||
"help": "Pomoc",
|
||||
"invite": "Pozvať účastníka",
|
||||
"kick": "Odstrániť účastníka",
|
||||
"lobbyButton": "Zapnúť/vypnúť čakáreň",
|
||||
"localRecording": "Zapnúť/vypnúť ovládanie lokálneho nahrávania",
|
||||
"lockRoom": "Zapnúť/vypnúť heslo pre stretnutie",
|
||||
"lockRoom": "Zapnúť/vypnúť heslo",
|
||||
"moreActions": "Menu „Ďalšie akcie“ zapnúť/vypnúť",
|
||||
"moreActionsMenu": "Menu „Ďalšie akcie“",
|
||||
"moreOptions": "Zobraz viac možností",
|
||||
@@ -606,6 +690,7 @@
|
||||
"raiseHand": "„Ohlásiť sa“ zapnúť/vypnúť",
|
||||
"recording": "Nahrávanie zapnúť/vypnúť",
|
||||
"remoteMute": "Účastníka stlmiť",
|
||||
"security": "Nastavenie zabezpečenia",
|
||||
"Settings": "Nastavenia zapnúť/vypnúť",
|
||||
"sharedvideo": "Zdieľanie YouTube videa zapnúť/vypnúť",
|
||||
"shareRoom": "Pozvať osobu",
|
||||
@@ -615,6 +700,7 @@
|
||||
"speakerStats": "Štatistiky rečníka zobraziť/skryť",
|
||||
"tileView": "Prepnúť dlaždicové zobrazenie",
|
||||
"toggleCamera": "Zmeniť kameru",
|
||||
"toggleFilmstrip": "Zapnúť/vypnúť video náhľady",
|
||||
"videomute": "„Video odpojiť“ zapnúť/vypnúť",
|
||||
"videoblur": "Rozmazanie pozadia zapnúť/vypnúť"
|
||||
},
|
||||
@@ -622,21 +708,24 @@
|
||||
"audioOnlyOff": "Mód „Iba zvuk“ deaktivovať",
|
||||
"audioOnlyOn": "Mód „Iba zvuk“ aktivovať",
|
||||
"audioRoute": "Vybrať zvukové zariadenie",
|
||||
"authenticate": "Overiť",
|
||||
"authenticate": "Autentifikácia",
|
||||
"callQuality": "Spravovať kvalitu videa",
|
||||
"chat": "Otvoriť / Zatvoriť chat",
|
||||
"closeChat": "Chat zatvoriť",
|
||||
"documentClose": "Zdielaný dokument zatvoriť",
|
||||
"documentOpen": "Zdielaný dokument otvoriť",
|
||||
"documentClose": "Zatvoriť zdieľaný dokument",
|
||||
"documentOpen": "Otvoriť zdieľaný dokument",
|
||||
"download": "Stiahnuť našu aplikáciu",
|
||||
"e2ee": "Koncové šifrovanie",
|
||||
"enterFullScreen": "Zobraziť na celú obrazovku",
|
||||
"enterTileView": "Kachličkové zobrazenie",
|
||||
"enterTileView": "Dlaždicové zobrazenie",
|
||||
"exitFullScreen": "Opustiť celú obrazovku",
|
||||
"exitTileView": "Kachličkové zobrazenie vypnúť",
|
||||
"exitTileView": "Zrušiť dlaždicové zobrazenie",
|
||||
"feedback": "Nechať spätnú väzbu",
|
||||
"hangup": "Odísť",
|
||||
"help": "Pomoc",
|
||||
"invite": "Pozvať účastníkov",
|
||||
"invite": "Pozvať ľudí",
|
||||
"lobbyButtonDisable": "Vypnúť čakáreň",
|
||||
"lobbyButtonEnable": "Zapnúť čakáreň",
|
||||
"login": "Prihlásiť",
|
||||
"logout": "Odhlásiť",
|
||||
"lowerYourHand": "Dať dole ruku",
|
||||
@@ -645,10 +734,10 @@
|
||||
"mute": "Vypnúť / Zapnúť mikrofón",
|
||||
"muteEveryone": "Všetkých stlmiť",
|
||||
"noAudioSignalTitle": "Neprichádza žiaden vstup z vašeho mikrofónu!",
|
||||
"noAudioSignalDesc": "Pokiaľ ste zámerne nestlmili váš mikrofón v systémových nastavenia alebo hardvery, pouvažujte nad prepnutím zariadenia.",
|
||||
"noAudioSignalDescSuggestion": "Pokiaľ ste zámerne nestlmili váš mikrofón v systémových nastavenia alebo hardvery, pouvažujte nad prepnutím na odporúčané zariadenie.",
|
||||
"noAudioSignalDesc": "Pokiaľ ste zámerne nestlmili váš mikrofón v systémových nastaveniach alebo hardvéri, pouvažujte nad prepnutím zariadenia.",
|
||||
"noAudioSignalDescSuggestion": "Pokiaľ ste zámerne nestlmili váš mikrofón v systémových nastaveniach alebo hardvéri, pouvažujte nad prepnutím na odporúčané zariadenie.",
|
||||
"noAudioSignalDialInDesc": "Môže zavolať pomocou:",
|
||||
"noAudioSignalDialInLinkDesc" : "Pripojovacie telefónne čísla",
|
||||
"noAudioSignalDialInLinkDesc": "Pripojovacie telefónne čísla",
|
||||
"noisyAudioInputTitle": "Váš mikrofón vyzerá byť zašumený!",
|
||||
"noisyAudioInputDesc": "Vyzerá, že váš mikrofón je zašumený, skúste ho vypnuť, alebo zmeňte zariadenie.",
|
||||
"openChat": "Otvoriť chat",
|
||||
@@ -657,6 +746,7 @@
|
||||
"profile": "Úprava profilu",
|
||||
"raiseHand": "Prihlásiť / Odhlásiť sa o slovo",
|
||||
"raiseYourHand": "Prihlásiť sa o slovo",
|
||||
"security": "Nastavenie zabezpečenia",
|
||||
"Settings": "Nastavenia",
|
||||
"sharedvideo": "Zdielať YouTube video",
|
||||
"shareRoom": "Pozvať niekoho",
|
||||
@@ -684,7 +774,7 @@
|
||||
"pending": "Pripravuje sa prepisovanie stretnutia...",
|
||||
"start": "Začni zobrazovať titulky",
|
||||
"stop": "Skonči zobrazovať titulky",
|
||||
"tr": ""
|
||||
"tr": "TR"
|
||||
},
|
||||
"userMedia": {
|
||||
"androidGrantPermissions": "Vyberte <b><i>Povoliť</i></b> keď sa prehliadač bude pýtať na povolenie.",
|
||||
@@ -699,14 +789,14 @@
|
||||
"safariGrantPermissions": "Vyberte <b><i>OK</i></b> keď sa prehliadač bude pýtať na povolenie."
|
||||
},
|
||||
"videoSIPGW": {
|
||||
"busy": "",
|
||||
"busyTitle": "",
|
||||
"errorAlreadyInvited": "",
|
||||
"errorInvite": "",
|
||||
"errorInviteFailed": "",
|
||||
"errorInviteFailedTitle": "",
|
||||
"errorInviteTitle": "",
|
||||
"pending": ""
|
||||
"busy": "Všetky zdroje sú obsadené, skúste znovu o pár minút.",
|
||||
"busyTitle": "Služba je obsadená",
|
||||
"errorAlreadyInvited": "{{displayName}} už bol pozvaný",
|
||||
"errorInvite": "Konferencia sa ešte nezačala, skúste neskôr.",
|
||||
"errorInviteFailed": "Skúste znovu neskôr.",
|
||||
"errorInviteFailedTitle": "Pozývanie {{displayName}} zlyhalo",
|
||||
"errorInviteTitle": "Chyba pozývania",
|
||||
"pending": "{{displayName}} bol pozvaný"
|
||||
},
|
||||
"videoStatus": {
|
||||
"audioOnly": "AUD",
|
||||
@@ -728,8 +818,10 @@
|
||||
},
|
||||
"videothumbnail": {
|
||||
"domute": "Vypnúť mikrofón",
|
||||
"domuteOthers": "Vypnúť mikrofóny ostatným",
|
||||
"flip": "Prevrátiť",
|
||||
"kick": "Vyhodiť",
|
||||
"grantModerator": "Urobiť moderátorom",
|
||||
"kick": "Odstrániť",
|
||||
"moderator": "Moderátor",
|
||||
"mute": "Účastník s vypnutým mikrofónom",
|
||||
"muted": "Vypnutý mikrofón",
|
||||
@@ -751,20 +843,62 @@
|
||||
"connectCalendarButton": "Pripojte váš kalendár",
|
||||
"connectCalendarText": "",
|
||||
"enterRoomTitle": "Začať nové stretnutie",
|
||||
"roomNameAllowedChars": "Meno stretnutia by nemalo obsahovať žiaden z týchto znakov: ?, &, :, ', \", %, #.",
|
||||
"getHelp": "Získať pomoc",
|
||||
"go": "Začať",
|
||||
"goSmall": "Začať",
|
||||
"join": "Pripojiť",
|
||||
"info": "Info",
|
||||
"join": "Pripojiť",
|
||||
"moderatedMessage": "Alebo si <a href=\"{{url}}\" rel=\"noopener noreferrer\" target=\"_blank\">rezervujte vopred URL</a> pre konferenciu, kde budete jediný moderátor.",
|
||||
"privacy": "Súkromie",
|
||||
"recentList": "Posledné",
|
||||
"recentListDelete": "Vymazať",
|
||||
"recentListEmpty": "Váš zoznam posledných hovorov je prázdny. Spojte sa s kolegami z Vášho tímu a potom tu nájdete všetky vaše stretnutia.",
|
||||
"reducedUIText": "Vítajte v {{app}}!",
|
||||
"reducedUIText": "Vitajte v {{app}}!",
|
||||
"roomNameAllowedChars": "Názov miestnosti by nemal obsahovať žiaden z týchto znakov: ?, &, :, ', \", %, #.",
|
||||
"roomname": "Zadajte názov miestnosti",
|
||||
"roomnameHint": "Zadajte názov alebo URL odkaz miestnosti ku ktorej sa chcete pripojiť. Pokial ste miestnosť vytvorili, uistite sa, že ostatný účastníci schôdzky zadajú rovnaké meno ako vy.",
|
||||
"roomnameHint": "Zadajte názov alebo URL odkaz miestnosti ku ktorej sa chcete pripojiť. Názov si môžete vymyslieť - dajte ho vedieť ostatným účastníkom konferencie, ktorí ho sem zadajú.",
|
||||
"sendFeedback": "Odoslať spätnú väzbu",
|
||||
"terms": "Podmienky používania",
|
||||
"title": "Zabezpečené, plnohodnotné a úplne bezplatné videokonferencie"
|
||||
},
|
||||
"lonelyMeetingExperience": {
|
||||
"button": "Pozvať ďalších",
|
||||
"youAreAlone": "Ste sám v tejto konferencii"
|
||||
},
|
||||
"helpView": {
|
||||
"header": "Centrum pomoci"
|
||||
},
|
||||
"lobby": {
|
||||
"knockingParticipantList": "Zoznam čakajúcich účastníkov",
|
||||
"allow": "Povoliť",
|
||||
"backToKnockModeButton": "Žiadne heslo, požiadať o vstup",
|
||||
"dialogTitle": "Čakáreň",
|
||||
"disableDialogContent": "Čakáreň je zapnutá. Táto funkcia zabezpečuje, že do konferencie nemôžu vstúpiť neželaní účastníci. Chcete ju vypnúť?",
|
||||
"disableDialogSubmit": "Vypnúť",
|
||||
"emailField": "Zadajte vašu e-mailovú adresu",
|
||||
"enableDialogPasswordField": "Nastaviť heslo (voliteľné)",
|
||||
"enableDialogSubmit": "Zapnúť",
|
||||
"enableDialogText": "Čakáreň umožňuje zabezpečiť konferenciu tým, že účastníci môžu do konferencie vstúpiť len po schválení moderátorom.",
|
||||
"enterPasswordButton": "Zadať heslo do konferencie",
|
||||
"enterPasswordTitle": "Zadajte heslo pre vstup do konferencie",
|
||||
"invalidPassword": "Nesprávne heslo",
|
||||
"joiningMessage": "Vstúpite do konferencie, keď niekto schváli vašu žiadosť",
|
||||
"joinWithPasswordMessage": "Vstupujem s heslom...",
|
||||
"joinRejectedMessage": "Vaša žiadosť bola zamietnutá moderátorom.",
|
||||
"joinTitle": "Vstup do konferencie",
|
||||
"joiningTitle": "Žiadam o vstup do konferencie...",
|
||||
"joiningWithPasswordTitle": "Vstupujem s heslom...",
|
||||
"knockButton": "Požiadať o vstup",
|
||||
"knockTitle": "Niekto žiada o vstup do konferencie",
|
||||
"nameField": "Zadajte vaše meno",
|
||||
"notificationLobbyAccessDenied": "Žiadosť {{targetParticipantName}} o vstup bola zamietnutá účastníkom {{originParticipantName}}",
|
||||
"notificationLobbyAccessGranted": "Žiadosť {{targetParticipantName}} o vstup bola povolená účastníkom {{originParticipantName}}",
|
||||
"notificationLobbyDisabled": "Účastník {{originParticipantName}} vypol čakáreň",
|
||||
"notificationLobbyEnabled": "Účastník {{originParticipantName}} zapol čakáreň",
|
||||
"notificationTitle": "Čakáreň",
|
||||
"passwordField": "Zadajte heslo do konferencie",
|
||||
"passwordJoinButton": "Vstúpiť",
|
||||
"reject": "Odmietnuť",
|
||||
"toggleLabel": "Zapnúť čakáreň"
|
||||
}
|
||||
}
|
||||
|
||||
1520
lang/main-sr.json
1520
lang/main-sr.json
File diff suppressed because it is too large
Load Diff
@@ -579,7 +579,7 @@
|
||||
},
|
||||
|
||||
"security": {
|
||||
"about": "Toplantınıza bir şifre ekleyebilirsiniz. Katılımcıların toplantıya katılmasına izin verilmeden önce şifreyi girmeleri gerekecektir.",
|
||||
"about": "Toplantınıza bir parola ekleyebilirsiniz. Katılımcıların toplantıya katılmasına izin verilmeden önce parolayı girmeleri gerekecektir.",
|
||||
"insecureRoomNameWarning": "Toplantı odası güvenli değil. Konferansınıza istenmeyen katılımcılar katılabilir.",
|
||||
"securityOptions": "Güvenlik Seçenekleri"
|
||||
},
|
||||
@@ -819,7 +819,7 @@
|
||||
"join": "Katılmak için dokunun",
|
||||
"roomname": "Oda adı girin"
|
||||
},
|
||||
"appDescription": "Durma ve tüm ekiple görüntülü sohbet et. Hatta tanıdığın herkesi davet et. {{app}} tüm gün, her gün ücretsiz olarak kullanabileceğiniz, hesap gerektirmeden kullanbilieceğiniz tamamen şifrelenmiş, % 100 özgür bir video konferans çözümüdür.",
|
||||
"appDescription": "Durma ve tüm ekiple görüntülü sohbet et. Hatta tanıdığın herkesi davet et. {{app}} tüm gün, her gün ücretsiz olarak ve hesap gerektirmeden kullanabileceğiniz tamamen şifrelenmiş, % 100 özgür bir video konferans çözümüdür.",
|
||||
"audioVideoSwitch": {
|
||||
"audio": "Ses",
|
||||
"video": "Görüntü"
|
||||
@@ -865,27 +865,27 @@
|
||||
|
||||
"lobby": {
|
||||
"allow": "İzin ver",
|
||||
"backToKnockModeButton": "Şifre yok, bunun yerine katılmayı isteyin",
|
||||
"backToKnockModeButton": "Parola yok, bunun yerine katılmayı isteyin",
|
||||
"dialogTitle": "Lobi modu",
|
||||
"disableDialogContent": "Lobi modu şu anda etkin. Bu özellik, istenmeyen katılımcıların toplantınıza katılamamasını sağlar. Devre dışı bırakmak istiyor musunuz?",
|
||||
"disableDialogSubmit": "Devre Dışı",
|
||||
"emailField": "E-posta adresinizi giriniz",
|
||||
"enableDialogPasswordField": "Şifre belirleyin (isteğe bağlı)",
|
||||
"enableDialogPasswordField": "Parola belirleyin (isteğe bağlı)",
|
||||
"enableDialogSubmit": "Etkin",
|
||||
"enableDialogText": "Lobi modu, toplantınızı yalnızca kişilerin bir moderatör tarafından resmi olarak onaylandıktan sonra girmelerine izin vererek korumanıza izin verir.",
|
||||
"enterPasswordButton": "Toplantı şifresini girin",
|
||||
"enterPasswordTitle": "Toplantıya katılmak için şifre girin",
|
||||
"invalidPassword": "Geçersiz şifre",
|
||||
"enterPasswordButton": "Toplantı parolasını girin",
|
||||
"enterPasswordTitle": "Toplantıya katılmak için parola girin",
|
||||
"invalidPassword": "Geçersiz parola",
|
||||
"joiningMessage": "Birisi isteğinizi kabul eder etmez toplantıya katılacaksınız",
|
||||
"joinWithPasswordMessage": "Şifre ile katılmaya çalışıyorsunuz lütfen bekleyin...",
|
||||
"joinWithPasswordMessage": "Parola ile katılmaya çalışıyorsunuz lütfen bekleyin...",
|
||||
"joinRejectedMessage": "Katılma isteğiniz bir moderatör tarafından reddedildi.",
|
||||
"joinTitle": "Toplantıya katıl",
|
||||
"joiningTitle": "Toplantıya katılma isteniyor...",
|
||||
"joiningWithPasswordTitle": "Şifre ile katılıyor...",
|
||||
"joiningWithPasswordTitle": "Parola ile katılıyor...",
|
||||
"knockButton": "Katılmak için sor",
|
||||
"knockTitle": "Birisi toplantıya katılmak istiyor",
|
||||
"nameField": "Adınızı giriniz",
|
||||
"passwordField": "Toplantı şifresini giriniz",
|
||||
"passwordField": "Toplantı parolasını giriniz",
|
||||
"passwordJoinButton": "Katıl",
|
||||
"reject": "Reddet",
|
||||
"toggleLabel": "Lobiyi etkinleştir"
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
},
|
||||
"connectionindicator": {
|
||||
"address": "Address:",
|
||||
"audio_ssrc": "Audio SSRC:",
|
||||
"bandwidth": "Estimated bandwidth:",
|
||||
"bitrate": "Bitrate:",
|
||||
"bridgeCount": "Server count: ",
|
||||
@@ -126,9 +127,12 @@
|
||||
"remoteport": "Remote port:",
|
||||
"remoteport_plural": "Remote ports:",
|
||||
"resolution": "Resolution:",
|
||||
"savelogs": "Save logs",
|
||||
"participant_id": "Participant id:",
|
||||
"status": "Connection:",
|
||||
"transport": "Transport:",
|
||||
"transport_plural": "Transports:"
|
||||
"transport_plural": "Transports:",
|
||||
"video_ssrc": "Video SSRC:"
|
||||
},
|
||||
"dateUtils": {
|
||||
"earlier": "Earlier",
|
||||
@@ -197,10 +201,7 @@
|
||||
"displayNameRequired": "Hi! What’s your name?",
|
||||
"done": "Done",
|
||||
"e2eeDescription": "End-to-End Encryption is currently EXPERIMENTAL. Please keep in mind that turning on end-to-end encryption will effectively disable server-side provided services such as: recording, live streaming and phone participation. Also keep in mind that the meeting will only work for people joining from browsers with support for insertable streams.",
|
||||
"e2eeLabel": "E2EE key",
|
||||
"e2eeNoKey": "None",
|
||||
"e2eeToggleSet": "Set key",
|
||||
"e2eeSet": "Set",
|
||||
"e2eeLabel": "Enable End-to-End Encryption",
|
||||
"e2eeWarning": "WARNING: Not all participants in this meeting seem to have support for End-to-End encryption. If you enable it they won't be able to see nor hear you.",
|
||||
"enterDisplayName": "Please enter your name here",
|
||||
"error": "Error",
|
||||
@@ -365,7 +366,7 @@
|
||||
"password": "$t(lockRoomPasswordUppercase):",
|
||||
"title": "Share",
|
||||
"tooltip": "Share link and dial-in info for this meeting",
|
||||
"label": "Meeting info"
|
||||
"label": "Dial-in info"
|
||||
},
|
||||
"inviteDialog": {
|
||||
"alertText": "Failed to invite some participants.",
|
||||
@@ -504,6 +505,7 @@
|
||||
"poweredby": "powered by",
|
||||
"prejoin": {
|
||||
"audioAndVideoError": "Audio and video error:",
|
||||
"audioDeviceProblem": "There is a problem with your audio device",
|
||||
"audioOnlyError": "Audio error:",
|
||||
"audioTrackError": "Could not create audio track.",
|
||||
"calling": "Calling",
|
||||
@@ -511,15 +513,35 @@
|
||||
"callMeAtNumber": "Call me at this number:",
|
||||
"configuringDevices": "Configuring devices...",
|
||||
"connectedWithAudioQ": "You’re connected with audio?",
|
||||
"connection": {
|
||||
"good": "Your internet connection looks good!",
|
||||
"nonOptimal": "Your internet connection is not optimal",
|
||||
"poor": "You have a poor internet connection"
|
||||
},
|
||||
"connectionDetails": {
|
||||
"audioClipping": "We expect your audio to be clipped.",
|
||||
"audioHighQuality": "We expect your audio to have excellent quality.",
|
||||
"audioLowNoVideo": "We expect your audio quality to be low and no video.",
|
||||
"goodQuality": "Awesome! Your media quality is going to be great.",
|
||||
"noMediaConnectivity": "We could not find a way to establish media connectivity for this test. This is typically caused by a firewall or NAT.",
|
||||
"noVideo": "We expect that your video will be terrible.",
|
||||
"undetectable": "If you still can not make calls in browser, we recommend that you make sure your speakers, microphone and camera are properly set up, that you have granted your browser rights to use your microphone and camera, and that your browser version is up-to-date. If you still have trouble calling, you should contact the web application developer.",
|
||||
"veryPoorConnection": "We expect your call quality to be really terrible.",
|
||||
"videoFreezing": "We expect your video to freeze, turn black, and be pixelated.",
|
||||
"videoHighQuality": "We expect your video to have good quality.",
|
||||
"videoLowQuality": "We expect your video to have low quality in terms of frame rate and resolution.",
|
||||
"videoTearing": "We expect your video to be pixelated or have visual artefacts."
|
||||
},
|
||||
"copyAndShare": "Copy & share meeting link",
|
||||
"dialInMeeting": "Dial into the meeting",
|
||||
"dialInPin": "Dial into the meeting and enter PIN code:",
|
||||
"dialing": "Dialing",
|
||||
"doNotShow": "Don't show this again",
|
||||
"doNotShow": "Don't show this screen again",
|
||||
"errorDialOut": "Could not dial out",
|
||||
"errorDialOutDisconnected": "Could not dial out. Disconnected",
|
||||
"errorDialOutFailed": "Could not dial out. Call failed",
|
||||
"errorDialOutStatus": "Error getting dial out status",
|
||||
"errorMissingName": "Please enter your name to join the meeting",
|
||||
"errorStatusCode": "Error dialing out, status code: {{status}}",
|
||||
"errorValidation": "Number validation failed",
|
||||
"iWantToDialIn": "I want to dial in",
|
||||
@@ -676,7 +698,6 @@
|
||||
"document": "Toggle shared document",
|
||||
"download": "Download our apps",
|
||||
"embedMeeting": "Embed meeting",
|
||||
"e2ee": "End-to-End Encryption",
|
||||
"feedback": "Leave feedback",
|
||||
"fullScreen": "Toggle full screen",
|
||||
"grantModerator": "Grant Moderator",
|
||||
@@ -855,12 +876,12 @@
|
||||
"getHelp": "Get help",
|
||||
"go": "GO",
|
||||
"goSmall": "GO",
|
||||
"info": "Info",
|
||||
"info": "Dial-in info",
|
||||
"join": "CREATE / JOIN",
|
||||
"moderatedMessage": "Or <a href=\"{{url}}\" rel=\"noopener noreferrer\" target=\"_blank\">book a meeting URL</a> in advance where you are the only moderator.",
|
||||
"privacy": "Privacy",
|
||||
"recentList": "Recent",
|
||||
"recentListDelete": "Delete",
|
||||
"recentListDelete": "Delete entry",
|
||||
"recentListEmpty": "Your recent list is currently empty. Chat with your team and you will find all your recent meetings here.",
|
||||
"reducedUIText": "Welcome to {{app}}!",
|
||||
"roomNameAllowedChars": "Meeting name should not contain any of these characters: ?, &, :, ', \", %, #.",
|
||||
|
||||
36
manifest.json
Normal file
36
manifest.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"android_package_name": "org.jitsi.meet",
|
||||
"prefer_related_applications": true,
|
||||
"related_applications": [
|
||||
{
|
||||
"id": "org.jitsi.meet",
|
||||
"platform": "chromeos_play"
|
||||
}
|
||||
],
|
||||
"short_name": "Jitsi Meet",
|
||||
"name": "Jitsi Meet",
|
||||
"icons": [
|
||||
{
|
||||
"src": "static/pwa/icons/icon192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "static/pwa/icons/icon512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
},
|
||||
{
|
||||
"src": "static/pwa/icons/iconMask.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
],
|
||||
"start_url": "/",
|
||||
"background_color": "#17A0DB",
|
||||
"display": "standalone",
|
||||
"scope": "/",
|
||||
"theme_color": "#17A0DB"
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import Logger from 'jitsi-meet-logger';
|
||||
|
||||
import * as JitsiMeetConferenceEvents from '../../ConferenceEvents';
|
||||
import {
|
||||
createApiEvent,
|
||||
sendAnalytics
|
||||
@@ -14,13 +13,19 @@ import {
|
||||
setSubject
|
||||
} from '../../react/features/base/conference';
|
||||
import { parseJWTFromURLParams } from '../../react/features/base/jwt';
|
||||
import { JitsiRecordingConstants } from '../../react/features/base/lib-jitsi-meet';
|
||||
import JitsiMeetJS, { JitsiRecordingConstants } from '../../react/features/base/lib-jitsi-meet';
|
||||
import { pinParticipant } from '../../react/features/base/participants';
|
||||
import {
|
||||
processExternalDeviceRequest
|
||||
} from '../../react/features/device-selection/functions';
|
||||
import { isEnabled as isDropboxEnabled } from '../../react/features/dropbox';
|
||||
import { setE2EEKey } from '../../react/features/e2ee';
|
||||
import { toggleE2EE } from '../../react/features/e2ee/actions';
|
||||
import { invite } from '../../react/features/invite';
|
||||
import {
|
||||
captureLargeVideoScreenshot,
|
||||
resizeLargeVideo,
|
||||
selectParticipantInLargeVideo
|
||||
} from '../../react/features/large-video/actions';
|
||||
import { toggleLobbyMode } from '../../react/features/lobby/actions.web';
|
||||
import { RECORDING_TYPES } from '../../react/features/recording/constants';
|
||||
import { getActiveSession } from '../../react/features/recording/functions';
|
||||
@@ -40,14 +45,6 @@ declare var APP: Object;
|
||||
*/
|
||||
let commands = {};
|
||||
|
||||
/**
|
||||
* The state of screen sharing(started/stopped) before the screen sharing is
|
||||
* enabled and initialized.
|
||||
* NOTE: This flag help us to cache the state and use it if toggle-share-screen
|
||||
* was received before the initialization.
|
||||
*/
|
||||
let initialScreenSharingState = false;
|
||||
|
||||
/**
|
||||
* The transport instance used for communication with external apps.
|
||||
*
|
||||
@@ -115,14 +112,29 @@ function initCommands() {
|
||||
));
|
||||
}
|
||||
},
|
||||
'pin-participant': id => {
|
||||
logger.debug('Pin participant command received');
|
||||
sendAnalytics(createApiEvent('participant.pinned'));
|
||||
APP.store.dispatch(pinParticipant(id));
|
||||
},
|
||||
'proxy-connection-event': event => {
|
||||
APP.conference.onProxyConnectionEvent(event);
|
||||
},
|
||||
'resize-large-video': (width, height) => {
|
||||
logger.debug('Resize large video command received');
|
||||
sendAnalytics(createApiEvent('largevideo.resized'));
|
||||
APP.store.dispatch(resizeLargeVideo(width, height));
|
||||
},
|
||||
'send-tones': (options = {}) => {
|
||||
const { duration, tones, pause } = options;
|
||||
|
||||
APP.store.dispatch(sendTones(tones, duration, pause));
|
||||
},
|
||||
'set-large-video-participant': participantId => {
|
||||
logger.debug('Set large video participant command received');
|
||||
sendAnalytics(createApiEvent('largevideo.participant.set'));
|
||||
APP.store.dispatch(selectParticipantInLargeVideo(participantId));
|
||||
},
|
||||
'subject': subject => {
|
||||
sendAnalytics(createApiEvent('subject.changed'));
|
||||
APP.store.dispatch(setSubject(subject));
|
||||
@@ -191,9 +203,9 @@ function initCommands() {
|
||||
logger.error('Failed sending endpoint text message', err);
|
||||
}
|
||||
},
|
||||
'e2ee-key': key => {
|
||||
logger.debug('Set E2EE key command received');
|
||||
APP.store.dispatch(setE2EEKey(key));
|
||||
'toggle-e2ee': enabled => {
|
||||
logger.debug('Toggle E2EE key command received');
|
||||
APP.store.dispatch(toggleE2EE(enabled));
|
||||
},
|
||||
'set-video-quality': frameHeight => {
|
||||
logger.debug('Set video quality command received');
|
||||
@@ -202,7 +214,8 @@ function initCommands() {
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts a file recording or streaming depending on the passed on params.
|
||||
* Starts a file recording or streaming session depending on the passed on params.
|
||||
* For RTMP streams, `rtmpStreamKey` must be passed on. `rtmpBroadcastID` is optional.
|
||||
* For youtube streams, `youtubeStreamKey` must be passed on. `youtubeBroadcastID` is optional.
|
||||
* For dropbox recording, recording `mode` should be `file` and a dropbox oauth2 token must be provided.
|
||||
* For file recording, recording `mode` should be `file` and optionally `shouldShare` could be passed on.
|
||||
@@ -210,13 +223,23 @@ function initCommands() {
|
||||
*
|
||||
* @param { string } arg.mode - Recording mode, either `file` or `stream`.
|
||||
* @param { string } arg.dropboxToken - Dropbox oauth2 token.
|
||||
* @param { string } arg.rtmpStreamKey - The RTMP stream key.
|
||||
* @param { string } arg.rtmpBroadcastID - The RTMP braodcast ID.
|
||||
* @param { boolean } arg.shouldShare - Whether the recording should be shared with the participants or not.
|
||||
* Only applies to certain jitsi meet deploys.
|
||||
* @param { string } arg.youtubeStreamKey - The youtube stream key.
|
||||
* @param { string } arg.youtubeBroadcastID - The youtube broacast ID.
|
||||
* @returns {void}
|
||||
*/
|
||||
'start-recording': ({ mode, dropboxToken, shouldShare, youtubeStreamKey, youtubeBroadcastID }) => {
|
||||
'start-recording': ({
|
||||
mode,
|
||||
dropboxToken,
|
||||
shouldShare,
|
||||
rtmpStreamKey,
|
||||
rtmpBroadcastID,
|
||||
youtubeStreamKey,
|
||||
youtubeBroadcastID
|
||||
}) => {
|
||||
const state = APP.store.getState();
|
||||
const conference = getCurrentConference(state);
|
||||
|
||||
@@ -232,8 +255,8 @@ function initCommands() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode === JitsiRecordingConstants.mode.STREAM && !youtubeStreamKey) {
|
||||
logger.error('Failed starting recording: missing youtube stream key');
|
||||
if (mode === JitsiRecordingConstants.mode.STREAM && !(youtubeStreamKey || rtmpStreamKey)) {
|
||||
logger.error('Failed starting recording: missing youtube or RTMP stream key');
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -265,9 +288,9 @@ function initCommands() {
|
||||
}
|
||||
} else if (mode === JitsiRecordingConstants.mode.STREAM) {
|
||||
recordingConfig = {
|
||||
broadcastId: youtubeBroadcastID,
|
||||
broadcastId: youtubeBroadcastID || rtmpBroadcastID,
|
||||
mode: JitsiRecordingConstants.mode.STREAM,
|
||||
streamId: youtubeStreamKey
|
||||
streamId: youtubeStreamKey || rtmpStreamKey
|
||||
};
|
||||
} else {
|
||||
logger.error('Invalid recording mode provided');
|
||||
@@ -328,6 +351,21 @@ function initCommands() {
|
||||
const { name } = request;
|
||||
|
||||
switch (name) {
|
||||
case 'capture-largevideo-screenshot' :
|
||||
APP.store.dispatch(captureLargeVideoScreenshot())
|
||||
.then(dataURL => {
|
||||
let error;
|
||||
|
||||
if (!dataURL) {
|
||||
error = new Error('No large video found!');
|
||||
}
|
||||
|
||||
callback({
|
||||
error,
|
||||
dataURL
|
||||
});
|
||||
});
|
||||
break;
|
||||
case 'invite': {
|
||||
const { invitees } = request;
|
||||
|
||||
@@ -383,19 +421,6 @@ function initCommands() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for desktop/screen sharing enabled events and toggles the screen
|
||||
* sharing if needed.
|
||||
*
|
||||
* @param {boolean} enabled - Current screen sharing enabled status.
|
||||
* @returns {void}
|
||||
*/
|
||||
function onDesktopSharingEnabledChanged(enabled = false) {
|
||||
if (enabled && initialScreenSharingState) {
|
||||
toggleScreenSharing();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the API should be enabled or not.
|
||||
*
|
||||
@@ -423,12 +448,10 @@ function shouldBeEnabled() {
|
||||
* @returns {void}
|
||||
*/
|
||||
function toggleScreenSharing(enable) {
|
||||
if (APP.conference.isDesktopSharingEnabled) {
|
||||
|
||||
// eslint-disable-next-line no-empty-function
|
||||
APP.conference.toggleScreenSharing(enable).catch(() => {});
|
||||
} else {
|
||||
initialScreenSharingState = !initialScreenSharingState;
|
||||
if (JitsiMeetJS.isDesktopSharingEnabled()) {
|
||||
APP.conference.toggleScreenSharing(enable).catch(() => {
|
||||
logger.warn('Failed to toggle screen-sharing');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,10 +484,6 @@ class API {
|
||||
*/
|
||||
this._enabled = true;
|
||||
|
||||
APP.conference.addListener(
|
||||
JitsiMeetConferenceEvents.DESKTOP_SHARING_ENABLED_CHANGED,
|
||||
onDesktopSharingEnabledChanged);
|
||||
|
||||
initCommands();
|
||||
}
|
||||
|
||||
@@ -524,6 +543,19 @@ class API {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify external application that the video quality setting has changed.
|
||||
*
|
||||
* @param {number} videoQuality - The video quality. The number represents the maximum height of the video streams.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyVideoQualityChanged(videoQuality: number) {
|
||||
this._sendEvent({
|
||||
name: 'video-quality-changed',
|
||||
videoQuality
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify external application (if API is enabled) that message was
|
||||
* received.
|
||||
@@ -677,6 +709,21 @@ class API {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify external application (if API is enabled) that the an error has been logged.
|
||||
*
|
||||
* @param {string} logLevel - The message log level.
|
||||
* @param {Array} args - Array of strings composing the log message.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyLog(logLevel: string, args: Array<string>) {
|
||||
this._sendEvent({
|
||||
name: 'log',
|
||||
logLevel,
|
||||
args
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify external application (if API is enabled) that the conference has
|
||||
* been joined.
|
||||
@@ -697,8 +744,7 @@ class API {
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify external application (if API is enabled) that user changed their
|
||||
* nickname.
|
||||
* Notify external application (if API is enabled) that local user has left the conference.
|
||||
*
|
||||
* @param {string} roomName - User id.
|
||||
* @returns {void}
|
||||
@@ -963,6 +1009,19 @@ class API {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify external application (if API is enabled) that the localStorage has changed.
|
||||
*
|
||||
* @param {string} localStorageContent - The new localStorageContent.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyLocalStorageChanged(localStorageContent: string) {
|
||||
this._sendEvent({
|
||||
name: 'local-storage-changed',
|
||||
localStorageContent
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes the allocated resources.
|
||||
*
|
||||
@@ -971,9 +1030,6 @@ class API {
|
||||
dispose() {
|
||||
if (this._enabled) {
|
||||
this._enabled = false;
|
||||
APP.conference.removeListener(
|
||||
JitsiMeetConferenceEvents.DESKTOP_SHARING_ENABLED_CHANGED,
|
||||
onDesktopSharingEnabledChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
162
modules/API/external/external_api.js
vendored
162
modules/API/external/external_api.js
vendored
@@ -1,3 +1,4 @@
|
||||
import { jitsiLocalStorage } from '@jitsi/js-utils/jitsi-local-storage';
|
||||
import EventEmitter from 'events';
|
||||
|
||||
import { urlObjectToString } from '../../../react/features/base/util/uri';
|
||||
@@ -35,8 +36,11 @@ const commands = {
|
||||
hangup: 'video-hangup',
|
||||
muteEveryone: 'mute-everyone',
|
||||
password: 'password',
|
||||
pinParticipant: 'pin-participant',
|
||||
resizeLargeVideo: 'resize-large-video',
|
||||
sendEndpointTextMessage: 'send-endpoint-text-message',
|
||||
sendTones: 'send-tones',
|
||||
setLargeVideoParticipant: 'set-large-video-participant',
|
||||
setVideoQuality: 'set-video-quality',
|
||||
startRecording: 'start-recording',
|
||||
stopRecording: 'stop-recording',
|
||||
@@ -67,6 +71,7 @@ const events = {
|
||||
'feedback-prompt-displayed': 'feedbackPromptDisplayed',
|
||||
'filmstrip-display-changed': 'filmstripDisplayChanged',
|
||||
'incoming-message': 'incomingMessage',
|
||||
'log': 'log',
|
||||
'mic-error': 'micError',
|
||||
'outgoing-message': 'outgoingMessage',
|
||||
'participant-joined': 'participantJoined',
|
||||
@@ -80,6 +85,7 @@ const events = {
|
||||
'video-conference-left': 'videoConferenceLeft',
|
||||
'video-availability-changed': 'videoAvailabilityChanged',
|
||||
'video-mute-status-changed': 'videoMuteStatusChanged',
|
||||
'video-quality-changed': 'videoQualityChanged',
|
||||
'screen-sharing-status-changed': 'screenSharingStatusChanged',
|
||||
'dominant-speaker-changed': 'dominantSpeakerChanged',
|
||||
'subject-change': 'subjectChange',
|
||||
@@ -263,6 +269,7 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
userInfo,
|
||||
e2eeKey
|
||||
} = parseArguments(args);
|
||||
const localStorageContent = jitsiLocalStorage.getItem('jitsiLocalStorage');
|
||||
|
||||
this._parentNode = parentNode;
|
||||
this._url = generateURL(domain, {
|
||||
@@ -272,7 +279,10 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
noSSL,
|
||||
roomName,
|
||||
devices,
|
||||
userInfo
|
||||
userInfo,
|
||||
appData: {
|
||||
localStorageContent
|
||||
}
|
||||
});
|
||||
this._createIFrame(height, width, onload);
|
||||
this._transport = new Transport({
|
||||
@@ -355,6 +365,19 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the formatted display name of a participant.
|
||||
*
|
||||
* @param {string} participantId - The id of the participant.
|
||||
* @returns {string} The formatted display name.
|
||||
*/
|
||||
_getFormattedDisplayName(participantId) {
|
||||
const { formattedDisplayName }
|
||||
= this._participants[participantId] || {};
|
||||
|
||||
return formattedDisplayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id of the on stage participant.
|
||||
*
|
||||
@@ -421,10 +444,12 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
const parsedWidth = parseSizeParam(width);
|
||||
|
||||
if (parsedHeight !== undefined) {
|
||||
this._height = height;
|
||||
this._frame.style.height = parsedHeight;
|
||||
}
|
||||
|
||||
if (parsedWidth !== undefined) {
|
||||
this._width = width;
|
||||
this._frame.style.width = parsedWidth;
|
||||
}
|
||||
}
|
||||
@@ -503,6 +528,14 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
changeParticipantNumber(this, -1);
|
||||
delete this._participants[this._myUserID];
|
||||
break;
|
||||
case 'video-quality-changed':
|
||||
this._videoQuality = data.videoQuality;
|
||||
break;
|
||||
case 'local-storage-changed':
|
||||
jitsiLocalStorage.setItem('jitsiLocalStorage', data.localStorageContent);
|
||||
|
||||
// Since this is internal event we don't need to emit it to the consumer of the API.
|
||||
return true;
|
||||
}
|
||||
|
||||
const eventName = events[name];
|
||||
@@ -538,6 +571,13 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
* the event and value - the listener.
|
||||
* Currently we support the following
|
||||
* events:
|
||||
* {@code log} - receives event notifications whenever information has
|
||||
* been logged and has a log level specified within {@code config.apiLogLevels}.
|
||||
* The listener will receive object with the following structure:
|
||||
* {{
|
||||
* logLevel: the message log level
|
||||
* arguments: an array of strings that compose the actual log message
|
||||
* }}
|
||||
* {@code incomingMessage} - receives event notifications about incoming
|
||||
* messages. The listener will receive object with the following structure:
|
||||
* {{
|
||||
@@ -607,6 +647,18 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures the screenshot of the large video.
|
||||
*
|
||||
* @returns {Promise<string>} - Resolves with a base64 encoded image data of the screenshot
|
||||
* if large video is detected, an error otherwise.
|
||||
*/
|
||||
captureLargeVideoScreenshot() {
|
||||
return this._transport.sendRequest({
|
||||
name: 'capture-largevideo-screenshot'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the listeners and removes the Jitsi Meet frame.
|
||||
*
|
||||
@@ -689,6 +741,32 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
return getCurrentDevices(this._transport);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the conference participants information.
|
||||
*
|
||||
* @returns {Array<Object>} - Returns an array containing participants
|
||||
* information like participant id, display name, avatar URL and email.
|
||||
*/
|
||||
getParticipantsInfo() {
|
||||
const participantIds = Object.keys(this._participants);
|
||||
const participantsInfo = Object.values(this._participants);
|
||||
|
||||
participantsInfo.forEach((participant, idx) => {
|
||||
participant.participantId = participantIds[idx];
|
||||
});
|
||||
|
||||
return participantsInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current video quality setting.
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
getVideoQuality() {
|
||||
return this._videoQuality;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the audio is available.
|
||||
*
|
||||
@@ -809,19 +887,6 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
return email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the formatted display name of a participant.
|
||||
*
|
||||
* @param {string} participantId - The id of the participant.
|
||||
* @returns {string} The formatted display name.
|
||||
*/
|
||||
_getFormattedDisplayName(participantId) {
|
||||
const { formattedDisplayName }
|
||||
= this._participants[participantId] || {};
|
||||
|
||||
return formattedDisplayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the iframe that loads Jitsi Meet.
|
||||
*
|
||||
@@ -865,6 +930,17 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Pins a participant's video on to the stage view.
|
||||
*
|
||||
* @param {string} participantId - Participant id (JID) of the participant
|
||||
* that needs to be pinned on the stage view.
|
||||
* @returns {void}
|
||||
*/
|
||||
pinParticipant(participantId) {
|
||||
this.executeCommand('pinParticipant', participantId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes event listener.
|
||||
*
|
||||
@@ -891,6 +967,19 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
eventList.forEach(event => this.removeEventListener(event));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes the large video container as per the dimensions provided.
|
||||
*
|
||||
* @param {number} width - Width that needs to be applied on the large video container.
|
||||
* @param {number} height - Height that needs to be applied on the large video container.
|
||||
* @returns {void}
|
||||
*/
|
||||
resizeLargeVideo(width, height) {
|
||||
if (width <= this._width && height <= this._height) {
|
||||
this.executeCommand('resizeLargeVideo', width, height);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes an event along to the local conference participant to establish
|
||||
* or update a direct peer connection. This is currently used for developing
|
||||
@@ -934,6 +1023,18 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
return setAudioOutputDevice(this._transport, label, deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the given participant on the large video. If no participant id is specified,
|
||||
* dominant and pinned speakers will be taken into consideration while selecting the
|
||||
* the large video participant.
|
||||
*
|
||||
* @param {string} participantId - Jid of the participant to be displayed on the large video.
|
||||
* @returns {void}
|
||||
*/
|
||||
setLargeVideoParticipant(participantId) {
|
||||
this.executeCommand('setLargeVideoParticipant', participantId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the video input device to the one with the label or id that is
|
||||
* passed.
|
||||
@@ -946,6 +1047,39 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
return setVideoInputDevice(this._transport, label, deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a file recording or streaming session depending on the passed on params.
|
||||
* For RTMP streams, `rtmpStreamKey` must be passed on. `rtmpBroadcastID` is optional.
|
||||
* For youtube streams, `youtubeStreamKey` must be passed on. `youtubeBroadcastID` is optional.
|
||||
* For dropbox recording, recording `mode` should be `file` and a dropbox oauth2 token must be provided.
|
||||
* For file recording, recording `mode` should be `file` and optionally `shouldShare` could be passed on.
|
||||
* No other params should be passed.
|
||||
*
|
||||
* @param {Object} options - An object with config options to pass along.
|
||||
* @param { string } options.mode - Recording mode, either `file` or `stream`.
|
||||
* @param { string } options.dropboxToken - Dropbox oauth2 token.
|
||||
* @param { boolean } options.shouldShare - Whether the recording should be shared with the participants or not.
|
||||
* Only applies to certain jitsi meet deploys.
|
||||
* @param { string } options.rtmpStreamKey - The RTMP stream key.
|
||||
* @param { string } options.rtmpBroadcastID - The RTMP broacast ID.
|
||||
* @param { string } options.youtubeStreamKey - The youtube stream key.
|
||||
* @param { string } options.youtubeBroadcastID - The youtube broacast ID.
|
||||
* @returns {void}
|
||||
*/
|
||||
startRecording(options) {
|
||||
this.executeCommand('startRecording', options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops a recording or streaming session that is in progress.
|
||||
*
|
||||
* @param {string} mode - `file` or `stream`.
|
||||
* @returns {void}
|
||||
*/
|
||||
stopRecording(mode) {
|
||||
this.executeCommand('startRecording', mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configuration for electron for the windows that are open
|
||||
* from Jitsi Meet.
|
||||
|
||||
@@ -7,7 +7,6 @@ import EventEmitter from 'events';
|
||||
import Logger from 'jitsi-meet-logger';
|
||||
|
||||
import { isMobileBrowser } from '../../react/features/base/environment/utils';
|
||||
import { getLocalParticipant } from '../../react/features/base/participants';
|
||||
import { toggleChat } from '../../react/features/chat';
|
||||
import { setDocumentUrl } from '../../react/features/etherpad';
|
||||
import { setFilmstripVisible } from '../../react/features/filmstrip';
|
||||
@@ -99,29 +98,11 @@ UI.notifyReservationError = function(code, msg) {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Change nickname for the user.
|
||||
* @param {string} id user id
|
||||
* @param {string} displayName new nickname
|
||||
*/
|
||||
UI.changeDisplayName = function(id, displayName) {
|
||||
VideoLayout.onDisplayNameChanged(id, displayName);
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize conference UI.
|
||||
*/
|
||||
UI.initConference = function() {
|
||||
const { getState } = APP.store;
|
||||
const { id, name } = getLocalParticipant(getState);
|
||||
|
||||
UI.showToolbar();
|
||||
|
||||
const displayName = config.displayJids ? id : name;
|
||||
|
||||
if (displayName) {
|
||||
UI.changeDisplayName('localVideoContainer', displayName);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -247,19 +228,12 @@ UI.getSharedDocumentManager = () => etherpadManager;
|
||||
* @param {JitsiParticipant} user
|
||||
*/
|
||||
UI.addUser = function(user) {
|
||||
const id = user.getId();
|
||||
const displayName = user.getDisplayName();
|
||||
const status = user.getStatus();
|
||||
|
||||
if (status) {
|
||||
// FIXME: move updateUserStatus in participantPresenceChanged action
|
||||
UI.updateUserStatus(user, status);
|
||||
}
|
||||
|
||||
// set initial display name
|
||||
if (displayName) {
|
||||
UI.changeDisplayName(id, displayName);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -356,8 +330,8 @@ UI.askForNickname = function() {
|
||||
/**
|
||||
* Sets muted audio state for participant
|
||||
*/
|
||||
UI.setAudioMuted = function(id, muted) {
|
||||
VideoLayout.onAudioMute(id, muted);
|
||||
UI.setAudioMuted = function(id) {
|
||||
// FIXME: Maybe this can be removed!
|
||||
if (APP.conference.isLocalId(id)) {
|
||||
APP.conference.updateAudioIconEnabled();
|
||||
}
|
||||
@@ -366,8 +340,8 @@ UI.setAudioMuted = function(id, muted) {
|
||||
/**
|
||||
* Sets muted video state for participant
|
||||
*/
|
||||
UI.setVideoMuted = function(id, muted) {
|
||||
VideoLayout.onVideoMute(id, muted);
|
||||
UI.setVideoMuted = function(id) {
|
||||
VideoLayout.onVideoMute(id);
|
||||
if (APP.conference.isLocalId(id)) {
|
||||
APP.conference.updateVideoIconEnabled();
|
||||
}
|
||||
@@ -494,14 +468,6 @@ UI.handleLastNEndpoints = function(leavingIds, enteringIds) {
|
||||
*/
|
||||
UI.setAudioLevel = (id, lvl) => VideoLayout.setAudioLevel(id, lvl);
|
||||
|
||||
/**
|
||||
* Hide connection quality statistics from UI.
|
||||
*/
|
||||
UI.hideStats = function() {
|
||||
VideoLayout.hideStats();
|
||||
};
|
||||
|
||||
|
||||
UI.notifyTokenAuthFailed = function() {
|
||||
messageHandler.showError({
|
||||
descriptionKey: 'dialog.tokenAuthFailed',
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
/* global $ */
|
||||
/* global $, APP */
|
||||
|
||||
import Logger from 'jitsi-meet-logger';
|
||||
/* eslint-disable no-unused-vars */
|
||||
import React, { Component } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { I18nextProvider } from 'react-i18next';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
import { i18next } from '../../../react/features/base/i18n';
|
||||
import Thumbnail from '../../../react/features/filmstrip/components/web/Thumbnail';
|
||||
import SmallVideo from '../videolayout/SmallVideo';
|
||||
|
||||
const logger = Logger.getLogger(__filename);
|
||||
/* eslint-enable no-unused-vars */
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -24,18 +29,12 @@ export default class SharedVideoThumb extends SmallVideo {
|
||||
this.videoSpanId = 'sharedVideoContainer';
|
||||
this.container = this.createContainer(this.videoSpanId);
|
||||
this.$container = $(this.container);
|
||||
this.renderThumbnail();
|
||||
this._setThumbnailSize();
|
||||
this.bindHoverHandler();
|
||||
this.isVideoMuted = true;
|
||||
this.updateDisplayName();
|
||||
this.container.onclick = this._onContainerClick;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
initializeAvatar() {} // eslint-disable-line no-empty-function
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} spanId
|
||||
@@ -46,18 +45,6 @@ export default class SharedVideoThumb extends SmallVideo {
|
||||
container.id = spanId;
|
||||
container.className = 'videocontainer';
|
||||
|
||||
// add the avatar
|
||||
const avatar = document.createElement('img');
|
||||
|
||||
avatar.className = 'sharedVideoAvatar';
|
||||
avatar.src = `https://img.youtube.com/vi/${this.url}/0.jpg`;
|
||||
container.appendChild(avatar);
|
||||
|
||||
const displayNameContainer = document.createElement('div');
|
||||
|
||||
displayNameContainer.className = 'displayNameContainer';
|
||||
container.appendChild(displayNameContainer);
|
||||
|
||||
const remoteVideosContainer
|
||||
= document.getElementById('filmstripRemoteVideosContainer');
|
||||
const localVideoContainer
|
||||
@@ -69,21 +56,14 @@ export default class SharedVideoThumb extends SmallVideo {
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers re-rendering of the display name using current instance state.
|
||||
*
|
||||
* @returns {void}
|
||||
* Renders the thumbnail.
|
||||
*/
|
||||
updateDisplayName() {
|
||||
if (!this.container) {
|
||||
logger.warn(`Unable to set displayName - ${this.videoSpanId
|
||||
} does not exist`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this._renderDisplayName({
|
||||
elementID: `${this.videoSpanId}_name`,
|
||||
participantID: this.id
|
||||
});
|
||||
renderThumbnail(isHovered = false) {
|
||||
ReactDOM.render(
|
||||
<Provider store = { APP.store }>
|
||||
<I18nextProvider i18n = { i18next }>
|
||||
<Thumbnail participantID = { this.id } isHovered = { isHovered } />
|
||||
</I18nextProvider>
|
||||
</Provider>, this.container);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,6 @@
|
||||
*/
|
||||
const UIUtil = {
|
||||
|
||||
/**
|
||||
* Returns the available video width.
|
||||
*/
|
||||
getAvailableVideoWidth() {
|
||||
return window.innerWidth;
|
||||
},
|
||||
|
||||
/**
|
||||
* Escapes the given text.
|
||||
*/
|
||||
|
||||
@@ -37,7 +37,6 @@ const Filmstrip = {
|
||||
*/
|
||||
resizeThumbnailsForTileView(width, height, forceUpdate = false) {
|
||||
const thumbs = this._getThumbs(!forceUpdate);
|
||||
const avatarSize = height / 2;
|
||||
|
||||
if (thumbs.localThumb) {
|
||||
thumbs.localThumb.css({
|
||||
@@ -58,11 +57,6 @@ const Filmstrip = {
|
||||
width: `${width}px`
|
||||
});
|
||||
}
|
||||
|
||||
$('.avatar-container').css({
|
||||
height: `${avatarSize}px`,
|
||||
width: `${avatarSize}px`
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -77,7 +71,6 @@ const Filmstrip = {
|
||||
|
||||
if (thumbs.localThumb) {
|
||||
const { height, width } = local;
|
||||
const avatarSize = height / 2;
|
||||
|
||||
thumbs.localThumb.css({
|
||||
height: `${height}px`,
|
||||
@@ -85,15 +78,10 @@ const Filmstrip = {
|
||||
'min-width': `${width}px`,
|
||||
width: `${width}px`
|
||||
});
|
||||
$('#localVideoContainer > .avatar-container').css({
|
||||
height: `${avatarSize}px`,
|
||||
width: `${avatarSize}px`
|
||||
});
|
||||
}
|
||||
|
||||
if (thumbs.remoteThumbs) {
|
||||
const { height, width } = remote;
|
||||
const avatarSize = height / 2;
|
||||
|
||||
thumbs.remoteThumbs.css({
|
||||
height: `${height}px`,
|
||||
@@ -101,10 +89,6 @@ const Filmstrip = {
|
||||
'min-width': `${width}px`,
|
||||
width: `${width}px`
|
||||
});
|
||||
$('#filmstripRemoteVideosContainer > span > .avatar-container').css({
|
||||
height: `${avatarSize}px`,
|
||||
width: `${avatarSize}px`
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -126,10 +110,6 @@ const Filmstrip = {
|
||||
'min-width': '',
|
||||
'min-height': ''
|
||||
});
|
||||
$('#localVideoContainer > .avatar-container').css({
|
||||
height: '50%',
|
||||
width: `${heightToWidthPercent / 2}%`
|
||||
});
|
||||
}
|
||||
|
||||
if (thumbs.remoteThumbs) {
|
||||
@@ -142,10 +122,6 @@ const Filmstrip = {
|
||||
'min-width': '',
|
||||
'min-height': ''
|
||||
});
|
||||
$('#filmstripRemoteVideosContainer > span > .avatar-container').css({
|
||||
height: '50%',
|
||||
width: `${heightToWidthPercent / 2}%`
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -12,16 +12,16 @@ import {
|
||||
JitsiParticipantConnectionStatus
|
||||
} from '../../../react/features/base/lib-jitsi-meet';
|
||||
import { VIDEO_TYPE } from '../../../react/features/base/media';
|
||||
import { getParticipantById } from '../../../react/features/base/participants';
|
||||
import { CHAT_SIZE } from '../../../react/features/chat';
|
||||
import {
|
||||
updateKnownLargeVideoResolution
|
||||
} from '../../../react/features/large-video';
|
||||
} from '../../../react/features/large-video/actions';
|
||||
import { PresenceLabel } from '../../../react/features/presence-status';
|
||||
/* eslint-enable no-unused-vars */
|
||||
import UIEvents from '../../../service/UI/UIEvents';
|
||||
import { createDeferred } from '../../util/helpers';
|
||||
import AudioLevels from '../audio_levels/AudioLevels';
|
||||
import UIUtil from '../util/UIUtil';
|
||||
|
||||
import { VideoContainer, VIDEO_CONTAINER_TYPE } from './VideoContainer';
|
||||
|
||||
@@ -68,7 +68,30 @@ export default class LargeVideoManager {
|
||||
// use the same video container to handle desktop tracks
|
||||
this.addContainer(DESKTOP_CONTAINER_TYPE, this.videoContainer);
|
||||
|
||||
/**
|
||||
* The preferred width passed as an argument to {@link updateContainerSize}.
|
||||
*
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.preferredWidth = undefined;
|
||||
|
||||
/**
|
||||
* The preferred height passed as an argument to {@link updateContainerSize}.
|
||||
*
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.preferredHeight = undefined;
|
||||
|
||||
/**
|
||||
* The calculated width that will be used for the large video.
|
||||
* @type {number}
|
||||
*/
|
||||
this.width = 0;
|
||||
|
||||
/**
|
||||
* The calculated height that will be used for the large video.
|
||||
* @type {number}
|
||||
*/
|
||||
this.height = 0;
|
||||
|
||||
/**
|
||||
@@ -202,9 +225,8 @@ export default class LargeVideoManager {
|
||||
const wasUsersImageCached
|
||||
= !isUserSwitch && container.wasVideoRendered;
|
||||
const isVideoMuted = !stream || stream.isMuted();
|
||||
|
||||
const connectionStatus
|
||||
= APP.conference.getParticipantConnectionStatus(id);
|
||||
const participant = getParticipantById(APP.store.getState(), id);
|
||||
const connectionStatus = participant?.connectionStatus;
|
||||
const isVideoRenderable
|
||||
= !isVideoMuted
|
||||
&& (APP.conference.isLocalId(id)
|
||||
@@ -323,8 +345,15 @@ export default class LargeVideoManager {
|
||||
/**
|
||||
* Update container size.
|
||||
*/
|
||||
updateContainerSize() {
|
||||
let widthToUse = UIUtil.getAvailableVideoWidth();
|
||||
updateContainerSize(width, height) {
|
||||
if (typeof width === 'number') {
|
||||
this.preferredWidth = width;
|
||||
}
|
||||
if (typeof height === 'number') {
|
||||
this.preferredHeight = height;
|
||||
}
|
||||
|
||||
let widthToUse = this.preferredWidth || window.innerWidth;
|
||||
const { isOpen } = APP.store.getState()['features/chat'];
|
||||
|
||||
if (isOpen) {
|
||||
@@ -336,7 +365,7 @@ export default class LargeVideoManager {
|
||||
}
|
||||
|
||||
this.width = widthToUse;
|
||||
this.height = window.innerHeight;
|
||||
this.height = this.preferredHeight || window.innerHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -450,8 +479,8 @@ export default class LargeVideoManager {
|
||||
*/
|
||||
showRemoteConnectionMessage(show) {
|
||||
if (typeof show !== 'boolean') {
|
||||
const connStatus
|
||||
= APP.conference.getParticipantConnectionStatus(this.id);
|
||||
const participant = getParticipantById(APP.store.getState(), this.id);
|
||||
const connStatus = participant?.connectionStatus;
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
show = !APP.conference.isLocalId(this.id)
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/* global $, config, interfaceConfig, APP */
|
||||
/* global $, config, APP */
|
||||
|
||||
import Logger from 'jitsi-meet-logger';
|
||||
/* eslint-disable no-unused-vars */
|
||||
import React, { Component } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { I18nextProvider } from 'react-i18next';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
import { i18next } from '../../../react/features/base/i18n';
|
||||
import { JitsiTrackEvents } from '../../../react/features/base/lib-jitsi-meet';
|
||||
import { VideoTrack } from '../../../react/features/base/media';
|
||||
import { updateSettings } from '../../../react/features/base/settings';
|
||||
import { getLocalVideoTrack } from '../../../react/features/base/tracks';
|
||||
import Thumbnail from '../../../react/features/filmstrip/components/web/Thumbnail';
|
||||
import { shouldDisplayTileView } from '../../../react/features/video-layout';
|
||||
/* eslint-enable no-unused-vars */
|
||||
import UIEvents from '../../../service/UI/UIEvents';
|
||||
|
||||
import SmallVideo from './SmallVideo';
|
||||
|
||||
const logger = Logger.getLogger(__filename);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@@ -37,6 +37,7 @@ export default class LocalVideo extends SmallVideo {
|
||||
this.isLocal = true;
|
||||
this._setThumbnailSize();
|
||||
this.updateDOMLocation();
|
||||
this.renderThumbnail();
|
||||
|
||||
this.localVideoId = null;
|
||||
this.bindHoverHandler();
|
||||
@@ -44,7 +45,6 @@ export default class LocalVideo extends SmallVideo {
|
||||
this._buildContextMenu();
|
||||
}
|
||||
this.emitter = emitter;
|
||||
this.statsPopoverLocation = interfaceConfig.VERTICAL_FILMSTRIP ? 'left top' : 'top center';
|
||||
|
||||
Object.defineProperty(this, 'id', {
|
||||
get() {
|
||||
@@ -53,17 +53,6 @@ export default class LocalVideo extends SmallVideo {
|
||||
});
|
||||
this.initBrowserSpecificProperties();
|
||||
|
||||
// Set default display name.
|
||||
this.updateDisplayName();
|
||||
|
||||
// Initialize the avatar display with an avatar url selected from the redux
|
||||
// state. Redux stores the local user with a hardcoded participant id of
|
||||
// 'local' if no id has been assigned yet.
|
||||
this.initializeAvatar();
|
||||
|
||||
this.addAudioLevelIndicator();
|
||||
this.updateIndicators();
|
||||
|
||||
this.container.onclick = this._onContainerClick;
|
||||
}
|
||||
|
||||
@@ -76,38 +65,19 @@ export default class LocalVideo extends SmallVideo {
|
||||
containerSpan.classList.add('videocontainer');
|
||||
containerSpan.id = this.videoSpanId;
|
||||
|
||||
containerSpan.innerHTML = `
|
||||
<div class = 'videocontainer__background'></div>
|
||||
<span id = 'localVideoWrapper'></span>
|
||||
<div class = 'videocontainer__toolbar'></div>
|
||||
<div class = 'videocontainer__toptoolbar'></div>
|
||||
<div class = 'videocontainer__hoverOverlay'></div>
|
||||
<div class = 'displayNameContainer'></div>
|
||||
<div class = 'avatar-container'></div>`;
|
||||
|
||||
return containerSpan;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers re-rendering of the display name using current instance state.
|
||||
*
|
||||
* @returns {void}
|
||||
* Renders the thumbnail.
|
||||
*/
|
||||
updateDisplayName() {
|
||||
if (!this.container) {
|
||||
logger.warn(
|
||||
`Unable to set displayName - ${this.videoSpanId
|
||||
} does not exist`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this._renderDisplayName({
|
||||
allowEditing: APP.store.getState()['features/base/jwt'].isGuest,
|
||||
displayNameSuffix: interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME,
|
||||
elementID: 'localDisplayName',
|
||||
participantID: this.id
|
||||
});
|
||||
renderThumbnail(isHovered = false) {
|
||||
ReactDOM.render(
|
||||
<Provider store = { APP.store }>
|
||||
<I18nextProvider i18n = { i18next }>
|
||||
<Thumbnail participantID = { this.id } isHovered = { isHovered } />
|
||||
</I18nextProvider>
|
||||
</Provider>, this.container);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,7 +87,6 @@ export default class LocalVideo extends SmallVideo {
|
||||
changeVideo(stream) {
|
||||
this.videoStream = stream;
|
||||
this.localVideoId = `localVideo_${stream.getId()}`;
|
||||
this._updateVideoElement();
|
||||
|
||||
// eslint-disable-next-line eqeqeq
|
||||
const isVideo = stream.videoType != 'desktop';
|
||||
@@ -127,17 +96,6 @@ export default class LocalVideo extends SmallVideo {
|
||||
this.setFlipX(isVideo ? settings.localFlipX : false);
|
||||
|
||||
const endedHandler = () => {
|
||||
const localVideoContainer
|
||||
= document.getElementById('localVideoWrapper');
|
||||
|
||||
// Only remove if there is no video and not a transition state.
|
||||
// Previous non-react logic created a new video element with each track
|
||||
// removal whereas react reuses the video component so it could be the
|
||||
// stream ended but a new one is being used.
|
||||
if (localVideoContainer && this.videoStream.isEnded()) {
|
||||
ReactDOM.unmountComponentAtNode(localVideoContainer);
|
||||
}
|
||||
|
||||
this._notifyOfStreamEnded();
|
||||
stream.off(JitsiTrackEvents.LOCAL_TRACK_STOPPED, endedHandler);
|
||||
};
|
||||
@@ -253,35 +211,5 @@ export default class LocalVideo extends SmallVideo {
|
||||
: document.getElementById('filmstripLocalVideoThumbnail');
|
||||
|
||||
appendTarget && appendTarget.appendChild(this.container);
|
||||
this._updateVideoElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the React Element for displaying video in {@code LocalVideo}.
|
||||
*
|
||||
*/
|
||||
_updateVideoElement() {
|
||||
const localVideoContainer = document.getElementById('localVideoWrapper');
|
||||
const videoTrack
|
||||
= getLocalVideoTrack(APP.store.getState()['features/base/tracks']);
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store = { APP.store }>
|
||||
<VideoTrack
|
||||
id = 'localVideo_container'
|
||||
videoTrack = { videoTrack } />
|
||||
</Provider>,
|
||||
localVideoContainer
|
||||
);
|
||||
|
||||
// Ensure the video gets play() called on it. This may be necessary in the
|
||||
// case where the local video container was moved and re-attached, in which
|
||||
// case video does not autoplay. Also, set the playsinline attribute on the
|
||||
// video element so that local video doesn't open in full screen by default
|
||||
// in Safari browser on iOS.
|
||||
const video = this.container.querySelector('video');
|
||||
|
||||
video && video.setAttribute('playsinline', 'true');
|
||||
video && !config.testing?.noAutoPlayVideo && video.play();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,10 +12,14 @@ import { i18next } from '../../../react/features/base/i18n';
|
||||
import {
|
||||
JitsiParticipantConnectionStatus
|
||||
} from '../../../react/features/base/lib-jitsi-meet';
|
||||
import { MEDIA_TYPE } from '../../../react/features/base/media';
|
||||
import {
|
||||
getParticipantById,
|
||||
getPinnedParticipant,
|
||||
pinParticipant
|
||||
} from '../../../react/features/base/participants';
|
||||
import { isRemoteTrackMuted } from '../../../react/features/base/tracks';
|
||||
import Thumbnail from '../../../react/features/filmstrip/components/web/Thumbnail';
|
||||
import { PresenceLabel } from '../../../react/features/presence-status';
|
||||
import {
|
||||
REMOTE_CONTROL_MENU_STATES,
|
||||
@@ -39,16 +43,6 @@ function createContainer(spanId) {
|
||||
container.id = spanId;
|
||||
container.className = 'videocontainer';
|
||||
|
||||
container.innerHTML = `
|
||||
<div class = 'videocontainer__background'></div>
|
||||
<div class = 'videocontainer__toptoolbar'></div>
|
||||
<div class = 'videocontainer__toolbar'></div>
|
||||
<div class = 'videocontainer__hoverOverlay'></div>
|
||||
<div class = 'displayNameContainer'></div>
|
||||
<div class = 'avatar-container'></div>
|
||||
<div class ='presence-label-container'></div>
|
||||
<span class = 'remotevideomenu'></span>`;
|
||||
|
||||
const remoteVideosContainer
|
||||
= document.getElementById('filmstripRemoteVideosContainer');
|
||||
const localVideoContainer
|
||||
@@ -79,14 +73,10 @@ export default class RemoteVideo extends SmallVideo {
|
||||
|
||||
this._audioStreamElement = null;
|
||||
this._supportsRemoteControl = false;
|
||||
this.statsPopoverLocation = interfaceConfig.VERTICAL_FILMSTRIP ? 'left bottom' : 'top center';
|
||||
this.addRemoteVideoContainer();
|
||||
this.updateIndicators();
|
||||
this.updateDisplayName();
|
||||
this.bindHoverHandler();
|
||||
this.flipX = false;
|
||||
this.isLocal = false;
|
||||
this.popupMenuIsHovered = false;
|
||||
this._isRemoteControlSessionActive = false;
|
||||
|
||||
/**
|
||||
@@ -98,17 +88,6 @@ export default class RemoteVideo extends SmallVideo {
|
||||
*/
|
||||
this._canPlayEventReceived = false;
|
||||
|
||||
/**
|
||||
* The flag is set to <tt>true</tt> if remote participant's video gets muted
|
||||
* during his media connection disruption. This is to prevent black video
|
||||
* being render on the thumbnail, because even though once the video has
|
||||
* been played the image usually remains on the video element it seems that
|
||||
* after longer period of the video element being hidden this image can be
|
||||
* lost.
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.mutedWhileDisconnected = false;
|
||||
|
||||
// Bind event handlers so they are only bound once for every instance.
|
||||
// TODO The event handlers should be turned into actions so changes can be
|
||||
// handled through reducers and middleware.
|
||||
@@ -126,26 +105,24 @@ export default class RemoteVideo extends SmallVideo {
|
||||
addRemoteVideoContainer() {
|
||||
this.container = createContainer(this.videoSpanId);
|
||||
this.$container = $(this.container);
|
||||
this.initializeAvatar();
|
||||
this.renderThumbnail();
|
||||
this._setThumbnailSize();
|
||||
this.initBrowserSpecificProperties();
|
||||
this.updateRemoteVideoMenu();
|
||||
this.updateStatusBar();
|
||||
this.addAudioLevelIndicator();
|
||||
this.addPresenceLabel();
|
||||
|
||||
return this.container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether current video is considered hovered. Currently it is hovered
|
||||
* if the mouse is over the video, or if the connection indicator or the popup
|
||||
* menu is shown(hovered).
|
||||
* @private
|
||||
* NOTE: extends SmallVideo's method
|
||||
* Renders the thumbnail.
|
||||
*/
|
||||
_isHovered() {
|
||||
return super._isHovered() || this.popupMenuIsHovered;
|
||||
renderThumbnail(isHovered = false) {
|
||||
ReactDOM.render(
|
||||
<Provider store = { APP.store }>
|
||||
<I18nextProvider i18n = { i18next }>
|
||||
<Thumbnail participantID = { this.id } isHovered = { isHovered } />
|
||||
</I18nextProvider>
|
||||
</Provider>, this.container);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -207,7 +184,6 @@ export default class RemoteVideo extends SmallVideo {
|
||||
<AtlasKitThemeProvider mode = 'dark'>
|
||||
<RemoteVideoMenuTriggerButton
|
||||
initialVolumeValue = { initialVolumeValue }
|
||||
isAudioMuted = { this.isAudioMuted }
|
||||
menuPosition = { remoteMenuPosition }
|
||||
onMenuDisplay
|
||||
= {this._onRemoteVideoMenuDisplay.bind(this)}
|
||||
@@ -311,43 +287,11 @@ export default class RemoteVideo extends SmallVideo {
|
||||
|
||||
/**
|
||||
* Updates the remote video menu.
|
||||
*
|
||||
* @param isMuted the new muted state to update to
|
||||
*/
|
||||
updateRemoteVideoMenu(isMuted) {
|
||||
if (typeof isMuted !== 'undefined') {
|
||||
this.isAudioMuted = isMuted;
|
||||
}
|
||||
updateRemoteVideoMenu() {
|
||||
this._generatePopupContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @override
|
||||
*/
|
||||
setVideoMutedView(isMuted) {
|
||||
super.setVideoMutedView(isMuted);
|
||||
|
||||
// Update 'mutedWhileDisconnected' flag
|
||||
this._figureOutMutedWhileDisconnected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Figures out the value of {@link #mutedWhileDisconnected} flag by taking into
|
||||
* account remote participant's network connectivity and video muted status.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_figureOutMutedWhileDisconnected() {
|
||||
const isActive = this.isConnectionActive();
|
||||
|
||||
if (!isActive && this.isVideoMuted) {
|
||||
this.mutedWhileDisconnected = true;
|
||||
} else if (isActive && !this.isVideoMuted) {
|
||||
this.mutedWhileDisconnected = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the remote stream element corresponding to the given stream and
|
||||
* parent container.
|
||||
@@ -378,17 +322,6 @@ export default class RemoteVideo extends SmallVideo {
|
||||
this.updateView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the remote user associated with this <tt>RemoteVideo</tt>
|
||||
* has connectivity issues.
|
||||
*
|
||||
* @return {boolean} <tt>true</tt> if the user's connection is fine or
|
||||
* <tt>false</tt> otherwise.
|
||||
*/
|
||||
isConnectionActive() {
|
||||
return this.user.getConnectionStatus() === JitsiParticipantConnectionStatus.ACTIVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* The remote video is considered "playable" once the can play event has been received. It will be allowed to
|
||||
* display video also in {@link JitsiParticipantConnectionStatus.INTERRUPTED} if the video has received the canplay
|
||||
@@ -400,12 +333,13 @@ export default class RemoteVideo extends SmallVideo {
|
||||
* @override
|
||||
*/
|
||||
isVideoPlayable() {
|
||||
const connectionState = APP.conference.getParticipantConnectionStatus(this.id);
|
||||
const participant = getParticipantById(APP.store.getState(), this.id);
|
||||
const { connectionStatus, mutedWhileDisconnected } = participant || {};
|
||||
|
||||
return super.isVideoPlayable()
|
||||
&& this._canPlayEventReceived
|
||||
&& (connectionState === JitsiParticipantConnectionStatus.ACTIVE
|
||||
|| (connectionState === JitsiParticipantConnectionStatus.INTERRUPTED && !this.mutedWhileDisconnected));
|
||||
&& (connectionStatus === JitsiParticipantConnectionStatus.ACTIVE
|
||||
|| (connectionStatus === JitsiParticipantConnectionStatus.INTERRUPTED && !mutedWhileDisconnected));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -413,34 +347,16 @@ export default class RemoteVideo extends SmallVideo {
|
||||
*/
|
||||
updateView() {
|
||||
this.$container.toggleClass('audio-only', APP.conference.isAudioOnly());
|
||||
this.updateConnectionStatusIndicator();
|
||||
|
||||
// This must be called after 'updateConnectionStatusIndicator' because it
|
||||
// affects the display mode by modifying 'mutedWhileDisconnected' flag
|
||||
super.updateView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the UI to reflect user's connectivity status.
|
||||
*/
|
||||
updateConnectionStatusIndicator() {
|
||||
const connectionStatus = this.user.getConnectionStatus();
|
||||
|
||||
logger.debug(`${this.id} thumbnail connection status: ${connectionStatus}`);
|
||||
|
||||
// FIXME rename 'mutedWhileDisconnected' to 'mutedWhileNotRendering'
|
||||
// Update 'mutedWhileDisconnected' flag
|
||||
this._figureOutMutedWhileDisconnected();
|
||||
this.updateConnectionStatus(connectionStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes RemoteVideo from the page.
|
||||
*/
|
||||
remove() {
|
||||
super.remove();
|
||||
this.removePresenceLabel();
|
||||
this.removeRemoteVideoMenu();
|
||||
ReactDOM.unmountComponentAtNode(this.container);
|
||||
super.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -481,7 +397,11 @@ export default class RemoteVideo extends SmallVideo {
|
||||
|
||||
const isVideo = stream.isVideoTrack();
|
||||
|
||||
isVideo ? this.videoStream = stream : this.audioStream = stream;
|
||||
if (isVideo) {
|
||||
this.videoStream = stream;
|
||||
} else {
|
||||
this.audioStream = stream;
|
||||
}
|
||||
|
||||
if (!stream.getOriginalStream()) {
|
||||
logger.debug('Remote video stream has no original stream');
|
||||
@@ -509,24 +429,6 @@ export default class RemoteVideo extends SmallVideo {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers re-rendering of the display name using current instance state.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
updateDisplayName() {
|
||||
if (!this.container) {
|
||||
logger.warn(`Unable to set displayName - ${this.videoSpanId} does not exist`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this._renderDisplayName({
|
||||
elementID: `${this.videoSpanId}_name`,
|
||||
participantID: this.id
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes remote video menu element from video element identified by
|
||||
* given <tt>videoElementId</tt>.
|
||||
@@ -541,39 +443,4 @@ export default class RemoteVideo extends SmallVideo {
|
||||
menuSpan.remove();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mounts the {@code PresenceLabel} for displaying the participant's current
|
||||
* presence status.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
addPresenceLabel() {
|
||||
const presenceLabelContainer = this.container.querySelector('.presence-label-container');
|
||||
|
||||
if (presenceLabelContainer) {
|
||||
ReactDOM.render(
|
||||
<Provider store = { APP.store }>
|
||||
<I18nextProvider i18n = { i18next }>
|
||||
<PresenceLabel
|
||||
participantID = { this.id }
|
||||
className = 'presence-label' />
|
||||
</I18nextProvider>
|
||||
</Provider>,
|
||||
presenceLabelContainer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmounts the {@code PresenceLabel} component.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
removePresenceLabel() {
|
||||
const presenceLabelContainer = this.container.querySelector('.presence-label-container');
|
||||
|
||||
if (presenceLabelContainer) {
|
||||
ReactDOM.unmountComponentAtNode(presenceLabelContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,11 +11,19 @@ import { Provider } from 'react-redux';
|
||||
import { AudioLevelIndicator } from '../../../react/features/audio-level-indicator';
|
||||
import { Avatar as AvatarDisplay } from '../../../react/features/base/avatar';
|
||||
import { i18next } from '../../../react/features/base/i18n';
|
||||
import { MEDIA_TYPE } from '../../../react/features/base/media';
|
||||
import {
|
||||
getLocalParticipant,
|
||||
getParticipantById,
|
||||
getParticipantCount,
|
||||
getPinnedParticipant,
|
||||
pinParticipant
|
||||
} from '../../../react/features/base/participants';
|
||||
import {
|
||||
getTrackByMediaTypeAndParticipant,
|
||||
isLocalTrackMuted,
|
||||
isRemoteTrackMuted
|
||||
} from '../../../react/features/base/tracks';
|
||||
import { ConnectionIndicator } from '../../../react/features/connection-indicator';
|
||||
import { DisplayName } from '../../../react/features/display-name';
|
||||
import {
|
||||
@@ -81,58 +89,13 @@ export default class SmallVideo {
|
||||
* Constructor.
|
||||
*/
|
||||
constructor(VideoLayout) {
|
||||
this.isAudioMuted = false;
|
||||
this.isVideoMuted = false;
|
||||
this.videoStream = null;
|
||||
this.audioStream = null;
|
||||
this.VideoLayout = VideoLayout;
|
||||
this.videoIsHovered = false;
|
||||
|
||||
/**
|
||||
* The current state of the user's bridge connection. The value should be
|
||||
* a string as enumerated in the library's participantConnectionStatus
|
||||
* constants.
|
||||
*
|
||||
* @private
|
||||
* @type {string|null}
|
||||
*/
|
||||
this._connectionStatus = null;
|
||||
|
||||
/**
|
||||
* Whether or not the ConnectionIndicator's popover is hovered. Modifies
|
||||
* how the video overlays display based on hover state.
|
||||
*
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this._popoverIsHovered = false;
|
||||
|
||||
/**
|
||||
* Whether or not the connection indicator should be displayed.
|
||||
*
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this._showConnectionIndicator = !interfaceConfig.CONNECTION_INDICATOR_DISABLED;
|
||||
|
||||
/**
|
||||
* Whether or not the dominant speaker indicator should be displayed.
|
||||
*
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this._showDominantSpeaker = false;
|
||||
|
||||
/**
|
||||
* Whether or not the raised hand indicator should be displayed.
|
||||
*
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this._showRaisedHand = false;
|
||||
this.videoType = undefined;
|
||||
|
||||
// Bind event handlers so they are only bound once for every instance.
|
||||
this._onPopoverHover = this._onPopoverHover.bind(this);
|
||||
this.updateView = this.updateView.bind(this);
|
||||
|
||||
this._onContainerClick = this._onContainerClick.bind(this);
|
||||
@@ -192,139 +155,22 @@ export default class SmallVideo {
|
||||
this.$container.hover(
|
||||
() => {
|
||||
this.videoIsHovered = true;
|
||||
this.renderThumbnail(true);
|
||||
this.updateView();
|
||||
this.updateIndicators();
|
||||
},
|
||||
() => {
|
||||
this.videoIsHovered = false;
|
||||
this.renderThumbnail(false);
|
||||
this.updateView();
|
||||
this.updateIndicators();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmounts the ConnectionIndicator component.
|
||||
|
||||
* @returns {void}
|
||||
*/
|
||||
removeConnectionIndicator() {
|
||||
this._showConnectionIndicator = false;
|
||||
this.updateIndicators();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the connectionStatus stat which displays in the ConnectionIndicator.
|
||||
|
||||
* @returns {void}
|
||||
*/
|
||||
updateConnectionStatus(connectionStatus) {
|
||||
this._connectionStatus = connectionStatus;
|
||||
this.updateIndicators();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows / hides the audio muted indicator over small videos.
|
||||
*
|
||||
* @param {boolean} isMuted indicates if the muted element should be shown
|
||||
* or hidden
|
||||
* Renders the thumbnail.
|
||||
*/
|
||||
showAudioIndicator(isMuted) {
|
||||
this.isAudioMuted = isMuted;
|
||||
this.updateStatusBar();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows video muted indicator over small videos and disables/enables avatar
|
||||
* if video muted.
|
||||
*
|
||||
* @param {boolean} isMuted indicates if we should set the view to muted view
|
||||
* or not
|
||||
*/
|
||||
setVideoMutedView(isMuted) {
|
||||
this.isVideoMuted = isMuted;
|
||||
this.updateView();
|
||||
this.updateStatusBar();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create or updates the ReactElement for displaying status indicators about
|
||||
* audio mute, video mute, and moderator status.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
updateStatusBar() {
|
||||
const statusBarContainer = this.container.querySelector('.videocontainer__toolbar');
|
||||
|
||||
if (!statusBarContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store = { APP.store }>
|
||||
<I18nextProvider i18n = { i18next }>
|
||||
<StatusIndicators
|
||||
showAudioMutedIndicator = { this.isAudioMuted }
|
||||
showVideoMutedIndicator = { this.isVideoMuted }
|
||||
participantID = { this.id } />
|
||||
</I18nextProvider>
|
||||
</Provider>,
|
||||
statusBarContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the element indicating the audio level of the participant.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
addAudioLevelIndicator() {
|
||||
let audioLevelContainer = this._getAudioLevelContainer();
|
||||
|
||||
if (audioLevelContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
audioLevelContainer = document.createElement('span');
|
||||
audioLevelContainer.className = 'audioindicator-container';
|
||||
this.container.appendChild(audioLevelContainer);
|
||||
this.updateAudioLevelIndicator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the element indicating the audio level of the participant.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
removeAudioLevelIndicator() {
|
||||
const audioLevelContainer = this._getAudioLevelContainer();
|
||||
|
||||
if (audioLevelContainer) {
|
||||
ReactDOM.unmountComponentAtNode(audioLevelContainer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the audio level for this small video.
|
||||
*
|
||||
* @param lvl the new audio level to set
|
||||
* @returns {void}
|
||||
*/
|
||||
updateAudioLevelIndicator(lvl = 0) {
|
||||
const audioLevelContainer = this._getAudioLevelContainer();
|
||||
|
||||
if (audioLevelContainer) {
|
||||
ReactDOM.render(<AudioLevelIndicator audioLevel = { lvl }/>, audioLevelContainer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the component's DOM for the element that should be the parent to the
|
||||
* AudioLevelIndicator.
|
||||
*
|
||||
* @returns {HTMLElement} The DOM element that holds the AudioLevelIndicator.
|
||||
*/
|
||||
_getAudioLevelContainer() {
|
||||
return this.container.querySelector('.audioindicator-container');
|
||||
renderThumbnail() {
|
||||
// Should be implemented by in subclasses.
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -341,62 +187,6 @@ export default class SmallVideo {
|
||||
return $($(this.container).find('video')[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the HTML image element which displays user's avatar.
|
||||
*
|
||||
* @return {jQuery|HTMLElement} a jQuery selector pointing to the HTML image
|
||||
* element which displays the user's avatar.
|
||||
*/
|
||||
$avatar() {
|
||||
return this.$container.find('.avatar-container');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the display name element, which appears on the video thumbnail.
|
||||
*
|
||||
* @return {jQuery} a jQuery selector pointing to the display name element of
|
||||
* the video thumbnail
|
||||
*/
|
||||
$displayName() {
|
||||
return this.$container.find('.displayNameContainer');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates or updates the participant's display name that is shown over the
|
||||
* video preview.
|
||||
*
|
||||
* @param {Object} props - The React {@code Component} props to pass into the
|
||||
* {@code DisplayName} component.
|
||||
* @returns {void}
|
||||
*/
|
||||
_renderDisplayName(props) {
|
||||
const displayNameContainer = this.container.querySelector('.displayNameContainer');
|
||||
|
||||
if (displayNameContainer) {
|
||||
ReactDOM.render(
|
||||
<Provider store = { APP.store }>
|
||||
<I18nextProvider i18n = { i18next }>
|
||||
<DisplayName { ...props } />
|
||||
</I18nextProvider>
|
||||
</Provider>,
|
||||
displayNameContainer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the component responsible for showing the participant's display name,
|
||||
* if its container is present.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
removeDisplayName() {
|
||||
const displayNameContainer = this.container.querySelector('.displayNameContainer');
|
||||
|
||||
if (displayNameContainer) {
|
||||
ReactDOM.unmountComponentAtNode(displayNameContainer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables / disables the css responsible for focusing/pinning a video
|
||||
* thumbnail.
|
||||
@@ -440,7 +230,18 @@ export default class SmallVideo {
|
||||
* or <tt>false</tt> otherwise.
|
||||
*/
|
||||
isVideoPlayable() {
|
||||
return this.videoStream && !this.isVideoMuted && !APP.conference.isAudioOnly();
|
||||
const state = APP.store.getState();
|
||||
const tracks = state['features/base/tracks'];
|
||||
const participant = this.id ? getParticipantById(state, this.id) : getLocalParticipant(state);
|
||||
let isVideoMuted = true;
|
||||
|
||||
if (participant?.local) {
|
||||
isVideoMuted = isLocalTrackMuted(tracks, MEDIA_TYPE.VIDEO);
|
||||
} else if (!participant?.isFakeParticipant) { // remote participants excluding shared video
|
||||
isVideoMuted = isRemoteTrackMuted(tracks, MEDIA_TYPE.VIDEO, this.id);
|
||||
}
|
||||
|
||||
return this.videoStream && !isVideoMuted && !APP.conference.isAudioOnly();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -450,8 +251,10 @@ export default class SmallVideo {
|
||||
* or <tt>DISPLAY_BLACKNESS_WITH_NAME</tt>.
|
||||
*/
|
||||
selectDisplayMode(input) {
|
||||
// Display name is always and only displayed when user is on the stage
|
||||
if (input.isCurrentlyOnLargeVideo && !input.tileViewActive) {
|
||||
if (!input.tileViewActive && input.isScreenSharing) {
|
||||
return input.isHovered ? DISPLAY_AVATAR_WITH_NAME : DISPLAY_AVATAR;
|
||||
} else if (input.isCurrentlyOnLargeVideo && !input.tileViewActive) {
|
||||
// Display name is always and only displayed when user is on the stage
|
||||
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
|
||||
@@ -468,18 +271,32 @@ export default class SmallVideo {
|
||||
* @returns {Object}
|
||||
*/
|
||||
computeDisplayModeInput() {
|
||||
let isScreenSharing = false;
|
||||
let connectionStatus, mutedWhileDisconnected;
|
||||
const state = APP.store.getState();
|
||||
const participant = getParticipantById(state, this.id);
|
||||
|
||||
if (typeof participant !== 'undefined' && !participant.isFakeParticipant && !participant.local) {
|
||||
const tracks = state['features/base/tracks'];
|
||||
const track = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, this.id);
|
||||
|
||||
isScreenSharing = typeof track !== 'undefined' && track.videoType === 'desktop';
|
||||
connectionStatus = participant.connectionStatus;
|
||||
mutedWhileDisconnected = participant.mutedWhileDisconnected;
|
||||
}
|
||||
|
||||
return {
|
||||
isCurrentlyOnLargeVideo: this.isCurrentlyOnLargeVideo(),
|
||||
isHovered: this._isHovered(),
|
||||
isAudioOnly: APP.conference.isAudioOnly(),
|
||||
tileViewActive: shouldDisplayTileView(APP.store.getState()),
|
||||
tileViewActive: shouldDisplayTileView(state),
|
||||
isVideoPlayable: this.isVideoPlayable(),
|
||||
hasVideo: Boolean(this.selectVideoElement().length),
|
||||
connectionStatus: APP.conference.getParticipantConnectionStatus(this.id),
|
||||
mutedWhileDisconnected: this.mutedWhileDisconnected,
|
||||
connectionStatus,
|
||||
mutedWhileDisconnected,
|
||||
canPlayEventReceived: this._canPlayEventReceived,
|
||||
videoStream: Boolean(this.videoStream),
|
||||
isVideoMuted: this.isVideoMuted,
|
||||
isScreenSharing,
|
||||
videoStreamMuted: this.videoStream ? this.videoStream.isMuted() : 'no stream'
|
||||
};
|
||||
}
|
||||
@@ -491,7 +308,7 @@ export default class SmallVideo {
|
||||
* @private
|
||||
*/
|
||||
_isHovered() {
|
||||
return this.videoIsHovered || this._popoverIsHovered;
|
||||
return this.videoIsHovered;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -538,43 +355,6 @@ export default class SmallVideo {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the react component displaying the avatar with the passed in avatar
|
||||
* url.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
initializeAvatar() {
|
||||
const thumbnail = this.$avatar().get(0);
|
||||
|
||||
if (thumbnail) {
|
||||
// Maybe add a special case for local participant, as on init of
|
||||
// LocalVideo.js the id is set to "local" but will get updated later.
|
||||
ReactDOM.render(
|
||||
<Provider store = { APP.store }>
|
||||
<AvatarDisplay
|
||||
className = 'userAvatar'
|
||||
participantId = { this.id } />
|
||||
</Provider>,
|
||||
thumbnail
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmounts any attached react components (particular the avatar image) from
|
||||
* the avatar container.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
removeAvatar() {
|
||||
const thumbnail = this.$avatar().get(0);
|
||||
|
||||
if (thumbnail) {
|
||||
ReactDOM.unmountComponentAtNode(thumbnail);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows or hides the dominant speaker indicator.
|
||||
* @param show whether to show or hide.
|
||||
@@ -591,30 +371,8 @@ export default class SmallVideo {
|
||||
|
||||
return;
|
||||
}
|
||||
if (this._showDominantSpeaker === show) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._showDominantSpeaker = show;
|
||||
this.$container.toggleClass('active-speaker', this._showDominantSpeaker);
|
||||
this.updateIndicators();
|
||||
this.updateView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows or hides the raised hand indicator.
|
||||
* @param show whether to show or hide.
|
||||
*/
|
||||
showRaisedHandIndicator(show) {
|
||||
if (!this.container) {
|
||||
logger.warn(`Unable to raised hand indication - ${
|
||||
this.videoSpanId} does not exist`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this._showRaisedHand = show;
|
||||
this.updateIndicators();
|
||||
this.$container.toggleClass('active-speaker', show);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -645,19 +403,7 @@ export default class SmallVideo {
|
||||
*/
|
||||
remove() {
|
||||
logger.log('Remove thumbnail', this.id);
|
||||
this.removeAudioLevelIndicator();
|
||||
|
||||
const toolbarContainer
|
||||
= this.container.querySelector('.videocontainer__toolbar');
|
||||
|
||||
if (toolbarContainer) {
|
||||
ReactDOM.unmountComponentAtNode(toolbarContainer);
|
||||
}
|
||||
|
||||
this.removeConnectionIndicator();
|
||||
this.removeDisplayName();
|
||||
this.removeAvatar();
|
||||
this._unmountIndicators();
|
||||
this._unmountThumbnail();
|
||||
|
||||
// Remove whole container
|
||||
if (this.container.parentNode) {
|
||||
@@ -672,77 +418,9 @@ export default class SmallVideo {
|
||||
* @returns {void}
|
||||
*/
|
||||
rerender() {
|
||||
this.updateIndicators();
|
||||
this.updateStatusBar();
|
||||
this.updateView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the React element responsible for showing connection status, dominant
|
||||
* speaker, and raised hand icons. Uses instance variables to get the necessary
|
||||
* state to display. Will create the React element if not already created.
|
||||
*
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
updateIndicators() {
|
||||
const indicatorToolbar = this.container.querySelector('.videocontainer__toptoolbar');
|
||||
|
||||
if (!indicatorToolbar) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { NORMAL = 8 } = interfaceConfig.INDICATOR_FONT_SIZES || {};
|
||||
const iconSize = NORMAL;
|
||||
const showConnectionIndicator = this.videoIsHovered || !interfaceConfig.CONNECTION_INDICATOR_AUTO_HIDE_ENABLED;
|
||||
const state = APP.store.getState();
|
||||
const currentLayout = getCurrentLayout(state);
|
||||
const participantCount = getParticipantCount(state);
|
||||
let statsPopoverPosition, tooltipPosition;
|
||||
|
||||
if (currentLayout === LAYOUTS.TILE_VIEW) {
|
||||
statsPopoverPosition = 'right top';
|
||||
tooltipPosition = 'right';
|
||||
} else if (currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW) {
|
||||
statsPopoverPosition = this.statsPopoverLocation;
|
||||
tooltipPosition = 'left';
|
||||
} else {
|
||||
statsPopoverPosition = this.statsPopoverLocation;
|
||||
tooltipPosition = 'top';
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store = { APP.store }>
|
||||
<I18nextProvider i18n = { i18next }>
|
||||
<div>
|
||||
<AtlasKitThemeProvider mode = 'dark'>
|
||||
{ this._showConnectionIndicator
|
||||
? <ConnectionIndicator
|
||||
alwaysVisible = { showConnectionIndicator }
|
||||
connectionStatus = { this._connectionStatus }
|
||||
iconSize = { iconSize }
|
||||
isLocalVideo = { this.isLocal }
|
||||
enableStatsDisplay = { !interfaceConfig.filmStripOnly }
|
||||
participantId = { this.id }
|
||||
statsPopoverPosition = { statsPopoverPosition } />
|
||||
: null }
|
||||
<RaisedHandIndicator
|
||||
iconSize = { iconSize }
|
||||
participantId = { this.id }
|
||||
tooltipPosition = { tooltipPosition } />
|
||||
{ this._showDominantSpeaker && participantCount > 2
|
||||
? <DominantSpeakerIndicator
|
||||
iconSize = { iconSize }
|
||||
tooltipPosition = { tooltipPosition } />
|
||||
: null }
|
||||
</AtlasKitThemeProvider>
|
||||
</div>
|
||||
</I18nextProvider>
|
||||
</Provider>,
|
||||
indicatorToolbar
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback invoked when the thumbnail is clicked and potentially trigger
|
||||
* pinning of the participant.
|
||||
@@ -800,31 +478,10 @@ export default class SmallVideo {
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the React element responsible for showing connection status, dominant
|
||||
* speaker, and raised hand icons.
|
||||
*
|
||||
* @private
|
||||
* @returns {void}
|
||||
* Unmounts the thumbnail.
|
||||
*/
|
||||
_unmountIndicators() {
|
||||
const indicatorToolbar = this.container.querySelector('.videocontainer__toptoolbar');
|
||||
|
||||
if (indicatorToolbar) {
|
||||
ReactDOM.unmountComponentAtNode(indicatorToolbar);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current state of the connection indicator popover being hovered.
|
||||
* If hovered, display the small video as if it is hovered.
|
||||
*
|
||||
* @param {boolean} popoverIsHovered - Whether or not the mouse cursor is
|
||||
* currently over the connection indicator popover.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onPopoverHover(popoverIsHovered) {
|
||||
this._popoverIsHovered = popoverIsHovered;
|
||||
this.updateView();
|
||||
_unmountThumbnail() {
|
||||
ReactDOM.unmountComponentAtNode(this.container);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -838,10 +495,6 @@ export default class SmallVideo {
|
||||
switch (layout) {
|
||||
case LAYOUTS.VERTICAL_FILMSTRIP_VIEW: {
|
||||
this.$container.css('padding-top', `${heightToWidthPercent}%`);
|
||||
this.$avatar().css({
|
||||
height: '50%',
|
||||
width: `${heightToWidthPercent / 2}%`
|
||||
});
|
||||
break;
|
||||
}
|
||||
case LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW: {
|
||||
@@ -851,7 +504,6 @@ export default class SmallVideo {
|
||||
|
||||
if (typeof size !== 'undefined') {
|
||||
const { height, width } = size;
|
||||
const avatarSize = height / 2;
|
||||
|
||||
this.$container.css({
|
||||
height: `${height}px`,
|
||||
@@ -859,10 +511,6 @@ export default class SmallVideo {
|
||||
'min-width': `${width}px`,
|
||||
width: `${width}px`
|
||||
});
|
||||
this.$avatar().css({
|
||||
height: `${avatarSize}px`,
|
||||
width: `${avatarSize}px`
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -872,7 +520,6 @@ export default class SmallVideo {
|
||||
|
||||
if (typeof thumbnailSize !== 'undefined') {
|
||||
const { height, width } = thumbnailSize;
|
||||
const avatarSize = height / 2;
|
||||
|
||||
this.$container.css({
|
||||
height: `${height}px`,
|
||||
@@ -880,10 +527,6 @@ export default class SmallVideo {
|
||||
'min-width': `${width}px`,
|
||||
width: `${width}px`
|
||||
});
|
||||
this.$avatar().css({
|
||||
height: `${avatarSize}px`,
|
||||
width: `${avatarSize}px`
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ function onLocalFlipXChanged(val) {
|
||||
*/
|
||||
function getAllThumbnails() {
|
||||
return [
|
||||
localVideoThumbnail,
|
||||
...localVideoThumbnail ? [ localVideoThumbnail ] : [],
|
||||
...Object.values(remoteVideos)
|
||||
];
|
||||
}
|
||||
@@ -116,12 +116,6 @@ const VideoLayout = {
|
||||
* @param lvl the new audio level to update to
|
||||
*/
|
||||
setAudioLevel(id, lvl) {
|
||||
const smallVideo = this.getSmallVideo(id);
|
||||
|
||||
if (smallVideo) {
|
||||
smallVideo.updateAudioLevelIndicator(lvl);
|
||||
}
|
||||
|
||||
if (largeVideo && id === largeVideo.id) {
|
||||
largeVideo.updateLargeVideoAudioLevel(lvl);
|
||||
}
|
||||
@@ -137,19 +131,6 @@ const VideoLayout = {
|
||||
this._updateLargeVideoIfDisplayed(localId);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get's the localID of the conference and set it to the local video
|
||||
* (small one). This needs to be called as early as possible, when muc is
|
||||
* actually joined. Otherwise events can come with information like email
|
||||
* and setting them assume the id is already set.
|
||||
*/
|
||||
mucJoined() {
|
||||
// FIXME: replace this call with a generic update call once SmallVideo
|
||||
// only contains a ReactElement. Then remove this call once the
|
||||
// Filmstrip is fully in React.
|
||||
localVideoThumbnail.updateIndicators();
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows/hides local video.
|
||||
* @param {boolean} true to make the local video visible, false - otherwise
|
||||
@@ -173,10 +154,9 @@ const VideoLayout = {
|
||||
remoteVideo.addRemoteStreamElement(stream);
|
||||
|
||||
// Make sure track's muted state is reflected
|
||||
if (stream.getType() === 'audio') {
|
||||
this.onAudioMute(id, stream.isMuted());
|
||||
} else {
|
||||
this.onVideoMute(id, stream.isMuted());
|
||||
if (stream.getType() !== 'audio') {
|
||||
this.onVideoMute(id);
|
||||
remoteVideo.updateView();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -188,6 +168,7 @@ const VideoLayout = {
|
||||
|
||||
if (remoteVideo) {
|
||||
remoteVideo.removeRemoteStreamElement(stream);
|
||||
remoteVideo.updateView();
|
||||
}
|
||||
|
||||
this.updateMutedForNoTracks(id, stream.getType());
|
||||
@@ -208,7 +189,7 @@ const VideoLayout = {
|
||||
if (mediaType === 'audio') {
|
||||
APP.UI.setAudioMuted(participantId, true);
|
||||
} else if (mediaType === 'video') {
|
||||
APP.UI.setVideoMuted(participantId, true);
|
||||
APP.UI.setVideoMuted(participantId);
|
||||
} else {
|
||||
logger.error(`Unsupported media type: ${mediaType}`);
|
||||
}
|
||||
@@ -327,35 +308,17 @@ const VideoLayout = {
|
||||
this._updateLargeVideoIfDisplayed(resourceJid, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* On audio muted event.
|
||||
*/
|
||||
onAudioMute(id, isMuted) {
|
||||
if (APP.conference.isLocalId(id)) {
|
||||
localVideoThumbnail.showAudioIndicator(isMuted);
|
||||
} else {
|
||||
const remoteVideo = remoteVideos[id];
|
||||
|
||||
if (!remoteVideo) {
|
||||
return;
|
||||
}
|
||||
|
||||
remoteVideo.showAudioIndicator(isMuted);
|
||||
remoteVideo.updateRemoteVideoMenu();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* On video muted event.
|
||||
*/
|
||||
onVideoMute(id, value) {
|
||||
onVideoMute(id) {
|
||||
if (APP.conference.isLocalId(id)) {
|
||||
localVideoThumbnail && localVideoThumbnail.setVideoMutedView(value);
|
||||
localVideoThumbnail && localVideoThumbnail.updateView();
|
||||
} else {
|
||||
const remoteVideo = remoteVideos[id];
|
||||
|
||||
if (remoteVideo) {
|
||||
remoteVideo.setVideoMutedView(value);
|
||||
remoteVideo.updateView();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,22 +326,6 @@ const VideoLayout = {
|
||||
this._updateLargeVideoIfDisplayed(id, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Display name changed.
|
||||
*/
|
||||
onDisplayNameChanged(id) {
|
||||
if (id === 'localVideoContainer'
|
||||
|| APP.conference.isLocalId(id)) {
|
||||
localVideoThumbnail.updateDisplayName();
|
||||
} else {
|
||||
const remoteVideo = remoteVideos[id];
|
||||
|
||||
if (remoteVideo) {
|
||||
remoteVideo.updateDisplayName();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* On dominant speaker changed event.
|
||||
*
|
||||
@@ -409,12 +356,6 @@ const VideoLayout = {
|
||||
const remoteVideo = remoteVideos[id];
|
||||
|
||||
if (remoteVideo) {
|
||||
// Updating only connection status indicator is not enough, because
|
||||
// when we the connection is restored while the avatar was displayed
|
||||
// (due to 'muted while disconnected' condition) we may want to show
|
||||
// the video stream again and in order to do that the display mode
|
||||
// must be updated.
|
||||
// remoteVideo.updateConnectionStatusIndicator(isActive);
|
||||
remoteVideo.updateView();
|
||||
}
|
||||
},
|
||||
@@ -451,20 +392,6 @@ const VideoLayout = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Hides all the indicators
|
||||
*/
|
||||
hideStats() {
|
||||
for (const video in remoteVideos) { // eslint-disable-line guard-for-in
|
||||
const remoteVideo = remoteVideos[video];
|
||||
|
||||
if (remoteVideo) {
|
||||
remoteVideo.removeConnectionIndicator();
|
||||
}
|
||||
}
|
||||
localVideoThumbnail.removeConnectionIndicator();
|
||||
},
|
||||
|
||||
removeParticipantContainer(id) {
|
||||
// Unlock large video
|
||||
if (this.getPinnedId() === id) {
|
||||
@@ -485,13 +412,14 @@ const VideoLayout = {
|
||||
},
|
||||
|
||||
onVideoTypeChanged(id, newVideoType) {
|
||||
if (VideoLayout.getRemoteVideoType(id) === newVideoType) {
|
||||
const remoteVideo = remoteVideos[id];
|
||||
|
||||
if (!remoteVideo) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info('Peer video type changed: ', id, newVideoType);
|
||||
|
||||
this._updateLargeVideoIfDisplayed(id, true);
|
||||
remoteVideo.updateView();
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -514,15 +442,6 @@ const VideoLayout = {
|
||||
},
|
||||
|
||||
changeUserAvatar(id, avatarUrl) {
|
||||
const smallVideo = VideoLayout.getSmallVideo(id);
|
||||
|
||||
if (smallVideo) {
|
||||
smallVideo.initializeAvatar();
|
||||
} else {
|
||||
logger.warn(
|
||||
`Missed avatar update - no small video yet for ${id}`
|
||||
);
|
||||
}
|
||||
if (this.isCurrentlyOnLarge(id)) {
|
||||
largeVideo.updateAvatar(avatarUrl);
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ export default {
|
||||
})
|
||||
.catch(err => {
|
||||
audioTrackError = err;
|
||||
showError && APP.store.disptach(notifyMicError(err));
|
||||
showError && APP.store.dispatch(notifyMicError(err));
|
||||
|
||||
return [];
|
||||
}));
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import EventEmitter from 'events';
|
||||
import { getLogger } from 'jitsi-meet-logger';
|
||||
|
||||
import JitsiMeetJS from '../../react/features/base/lib-jitsi-meet';
|
||||
import { DISCO_REMOTE_CONTROL_FEATURE }
|
||||
from '../../service/remotecontrol/Constants';
|
||||
import * as RemoteControlEvents
|
||||
@@ -68,9 +69,7 @@ class RemoteControl extends EventEmitter {
|
||||
* @returns {void}
|
||||
*/
|
||||
init() {
|
||||
if (config.disableRemoteControl
|
||||
|| this._initialized
|
||||
|| !APP.conference.isDesktopSharingEnabled) {
|
||||
if (config.disableRemoteControl || this._initialized || !JitsiMeetJS.isDesktopSharingEnabled()) {
|
||||
return;
|
||||
}
|
||||
logger.log('Initializing remote control.');
|
||||
|
||||
9634
package-lock.json
generated
9634
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
36
package.json
36
package.json
@@ -32,7 +32,7 @@
|
||||
"@atlaskit/theme": "7.0.2",
|
||||
"@atlaskit/toggle": "5.0.14",
|
||||
"@atlaskit/tooltip": "12.1.13",
|
||||
"@jitsi/js-utils": "1.0.1",
|
||||
"@jitsi/js-utils": "1.0.2",
|
||||
"@microsoft/microsoft-graph-client": "1.1.0",
|
||||
"@react-native-community/async-storage": "1.3.4",
|
||||
"@react-native-community/google-signin": "3.0.1",
|
||||
@@ -40,11 +40,11 @@
|
||||
"@svgr/webpack": "4.3.2",
|
||||
"@tensorflow-models/body-pix": "2.0.4",
|
||||
"@tensorflow/tfjs": "1.5.1",
|
||||
"@webcomponents/url": "0.7.1",
|
||||
"amplitude-js": "4.5.2",
|
||||
"amplitude-js": "7.3.1",
|
||||
"base64-js": "1.3.1",
|
||||
"bc-css-flags": "3.0.0",
|
||||
"dropbox": "4.0.9",
|
||||
"focus-visible": "5.1.0",
|
||||
"i18n-iso-countries": "3.7.8",
|
||||
"i18next": "17.0.6",
|
||||
"i18next-browser-languagedetector": "3.0.1",
|
||||
@@ -56,20 +56,22 @@
|
||||
"jquery-i18next": "1.2.1",
|
||||
"js-md5": "0.6.1",
|
||||
"jwt-decode": "2.2.0",
|
||||
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#3ac82faa2d6a0e09428b89409b1c89cce08904bf",
|
||||
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#6bb0b86c0a7dd22bb5798236d9b80ca578b28d21",
|
||||
"libflacjs": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d",
|
||||
"lodash": "4.17.19",
|
||||
"moment": "2.19.4",
|
||||
"moment-duration-format": "2.2.2",
|
||||
"olm": "https://packages.matrix.org/npm/olm/olm-3.2.1.tgz",
|
||||
"pixelmatch": "5.1.0",
|
||||
"punycode": "2.1.1",
|
||||
"react": "16.9",
|
||||
"react-dom": "16.9",
|
||||
"react-emoji-render": "1.2.4",
|
||||
"react-i18next": "10.11.4",
|
||||
"react-linkify": "1.0.0-alpha",
|
||||
"react-native": "github:jitsi/react-native#efd2aff5661d75a230e36406b698cfe0ee545be2",
|
||||
"react-native-background-timer": "2.1.1",
|
||||
"react-native-calendar-events": "github:jitsi/react-native-calendar-events#928a80e2ffef0d7e84936d7e7e0acc4f53ee8470",
|
||||
"react-native": "github:jitsi/react-native#891986ec5ecaef65d1c8a7fe472f86cf84fe7551",
|
||||
"react-native-background-timer": "2.4.0",
|
||||
"react-native-calendar-events": "github:jitsi/react-native-calendar-events#df48ecdc4e1e90c5352f803ddbab1fa7269b74a7",
|
||||
"react-native-callstats": "3.61.0",
|
||||
"react-native-collapsible": "1.5.1",
|
||||
"react-native-default-preference": "1.4.2",
|
||||
@@ -77,20 +79,22 @@
|
||||
"react-native-keep-awake": "4.0.0",
|
||||
"react-native-linear-gradient": "2.5.6",
|
||||
"react-native-sound": "github:jitsi/react-native-sound#3fe5480fce935e888d5089d94a191c7c7e3aa190",
|
||||
"react-native-svg": "9.7.1",
|
||||
"react-native-svg-transformer": "0.13.0",
|
||||
"react-native-swipeout": "2.3.6",
|
||||
"react-native-splash-screen": "3.2.0",
|
||||
"react-native-svg": "10.1.0",
|
||||
"react-native-svg-transformer": "0.14.3",
|
||||
"react-native-url-polyfill": "1.2.0",
|
||||
"react-native-watch-connectivity": "0.4.3",
|
||||
"react-native-webrtc": "1.84.0",
|
||||
"react-native-webview": "7.4.1",
|
||||
"react-native-webrtc": "1.84.1",
|
||||
"react-native-webview": "10.9.0",
|
||||
"react-native-youtube-iframe": "1.2.3",
|
||||
"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#566a16885897704d6e6d67a1d5ac5d39781db2af",
|
||||
"rtcstats": "github:jitsi/rtcstats#v6.1.3",
|
||||
"rnnoise-wasm": "github:jitsi/rnnoise-wasm#566a16885897704d6e6d67a1d5ac5d39781db2af",
|
||||
"rtcstats": "github:jitsi/rtcstats#v6.2.0",
|
||||
"stackblur-canvas": "2.3.0",
|
||||
"styled-components": "3.4.9",
|
||||
"util": "0.12.1",
|
||||
"uuid": "3.1.0",
|
||||
@@ -125,10 +129,9 @@
|
||||
"expose-loader": "0.7.5",
|
||||
"flow-bin": "0.104.0",
|
||||
"imports-loader": "0.7.1",
|
||||
"jest": "26.1.0",
|
||||
"jetifier": "1.6.4",
|
||||
"metro-react-native-babel-preset": "0.56.0",
|
||||
"node-sass": "4.14.1",
|
||||
"sass": "1.26.8",
|
||||
"string-replace-loader": "2.1.1",
|
||||
"style-loader": "0.19.0",
|
||||
"unorm": "1.6.0",
|
||||
@@ -145,7 +148,6 @@
|
||||
"scripts": {
|
||||
"lint": "eslint . && flow",
|
||||
"postinstall": "jetify",
|
||||
"test": "jest",
|
||||
"validate": "npm ls"
|
||||
},
|
||||
"browser": {
|
||||
|
||||
88
pwa-worker.js
Normal file
88
pwa-worker.js
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
Copyright 2015, 2019, 2020 Google LLC. All Rights Reserved.
|
||||
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.
|
||||
*/
|
||||
|
||||
const CACHE_NAME = 'offline';
|
||||
|
||||
// Customize this with a different URL if needed.
|
||||
const OFFLINE_URL = 'static/offline.html';
|
||||
|
||||
self.addEventListener('install', event => {
|
||||
event.waitUntil(
|
||||
(async () => {
|
||||
const cache = await caches.open(CACHE_NAME);
|
||||
|
||||
|
||||
// Setting {cache: 'reload'} in the new request will ensure that the
|
||||
// response isn't fulfilled from the HTTP cache; i.e., it will be from
|
||||
// the network.
|
||||
await cache.add(new Request(OFFLINE_URL, { cache: 'reload' }));
|
||||
})()
|
||||
);
|
||||
|
||||
// Force the waiting service worker to become the active service worker.
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
self.addEventListener('activate', event => {
|
||||
event.waitUntil(
|
||||
(async () => {
|
||||
// Enable navigation preload if it's supported.
|
||||
// See https://developers.google.com/web/updates/2017/02/navigation-preload
|
||||
if ('navigationPreload' in self.registration) {
|
||||
await self.registration.navigationPreload.enable();
|
||||
}
|
||||
})()
|
||||
);
|
||||
|
||||
// Tell the active service worker to take control of the page immediately.
|
||||
self.clients.claim();
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', event => {
|
||||
// We only want to call event.respondWith() if this is a navigation request
|
||||
// for an HTML page.
|
||||
if (event.request.mode === 'navigate') {
|
||||
event.respondWith((async () => {
|
||||
try {
|
||||
// First, try to use the navigation preload response if it's supported.
|
||||
const preloadResponse = await event.preloadResponse;
|
||||
|
||||
if (preloadResponse) {
|
||||
return preloadResponse;
|
||||
}
|
||||
|
||||
// Always try the network first.
|
||||
const networkResponse = await fetch(event.request);
|
||||
|
||||
return networkResponse;
|
||||
} catch (error) {
|
||||
// catch is only triggered if an exception is thrown, which is likely
|
||||
// due to a network error.
|
||||
// If fetch() returns a valid HTTP response with a response code in
|
||||
// the 4xx or 5xx range, the catch() will NOT be called.
|
||||
console.log('Fetch failed; returning offline page instead.', error);
|
||||
|
||||
const cache = await caches.open(CACHE_NAME);
|
||||
const cachedResponse = await cache.match(OFFLINE_URL);
|
||||
|
||||
return cachedResponse;
|
||||
}
|
||||
})());
|
||||
}
|
||||
|
||||
// If our if() condition is false, then this fetch handler won't intercept the
|
||||
// request. If there are any other fetch handlers registered, they will get a
|
||||
// chance to call event.respondWith(). If no fetch handlers call
|
||||
// event.respondWith(), the request will be handled by the browser as if there
|
||||
// were no service worker involvement.
|
||||
});
|
||||
@@ -772,6 +772,22 @@ export function createTrackMutedEvent(mediaType, reason, muted = true) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an event for joining a vpaas conference.
|
||||
*
|
||||
* @param {string} tenant - The conference tenant.
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createVpaasConferenceJoinedEvent(tenant) {
|
||||
return {
|
||||
action: 'vpaas.conference.joined',
|
||||
attributes: {
|
||||
tenant
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an event for an action on the welcome page.
|
||||
*
|
||||
|
||||
@@ -57,12 +57,15 @@ export function resetAnalytics() {
|
||||
* @param {Store} store - The redux store in which the specified {@code action} is being dispatched.
|
||||
* @returns {Promise} Resolves with the handlers that have been successfully loaded.
|
||||
*/
|
||||
export function createHandlers({ getState }: { getState: Function }) {
|
||||
export async function createHandlers({ getState }: { getState: Function }) {
|
||||
getJitsiMeetGlobalNS().analyticsHandlers = [];
|
||||
window.analyticsHandlers = []; // Legacy support.
|
||||
|
||||
if (!isAnalyticsEnabled(getState)) {
|
||||
return Promise.resolve([]);
|
||||
// Avoid all analytics processing if there are no handlers, since no event would be sent.
|
||||
analytics.dispose();
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
const state = getState();
|
||||
@@ -100,43 +103,47 @@ export function createHandlers({ getState }: { getState: Function }) {
|
||||
};
|
||||
const handlers = [];
|
||||
|
||||
try {
|
||||
const amplitude = new AmplitudeHandler(handlerConstructorOptions);
|
||||
if (amplitudeAPPKey) {
|
||||
try {
|
||||
const amplitude = new AmplitudeHandler(handlerConstructorOptions);
|
||||
|
||||
analytics.amplitudeIdentityProps = amplitude.getIdentityProps();
|
||||
analytics.amplitudeIdentityProps = amplitude.getIdentityProps();
|
||||
|
||||
handlers.push(amplitude);
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (e) {}
|
||||
handlers.push(amplitude);
|
||||
} catch (e) {
|
||||
logger.error('Failed to initialize Amplitude handler', e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const matomo = new MatomoHandler(handlerConstructorOptions);
|
||||
if (matomoEndpoint && matomoSiteID) {
|
||||
try {
|
||||
const matomo = new MatomoHandler(handlerConstructorOptions);
|
||||
|
||||
handlers.push(matomo);
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (e) {}
|
||||
handlers.push(matomo);
|
||||
} catch (e) {
|
||||
logger.error('Failed to initialize Matomo handler', e);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
_loadHandlers(scriptURLs, handlerConstructorOptions)
|
||||
.then(externalHandlers => {
|
||||
handlers.push(...externalHandlers);
|
||||
if (handlers.length === 0) {
|
||||
// Throwing an error in order to dispose the analytics in the catch clause due to the lack of any
|
||||
// analytics handlers.
|
||||
throw new Error('No analytics handlers created!');
|
||||
}
|
||||
if (Array.isArray(scriptURLs) && scriptURLs.length > 0) {
|
||||
let externalHandlers;
|
||||
|
||||
return handlers;
|
||||
})
|
||||
.catch(e => {
|
||||
analytics.dispose();
|
||||
if (handlers.length !== 0) {
|
||||
logger.error(e);
|
||||
}
|
||||
try {
|
||||
externalHandlers = await _loadHandlers(scriptURLs, handlerConstructorOptions);
|
||||
handlers.push(...externalHandlers);
|
||||
} catch (e) {
|
||||
logger.error('Failed to initialize external analytics handlers', e);
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}));
|
||||
// Avoid all analytics processing if there are no handlers, since no event would be sent.
|
||||
if (handlers.length === 0) {
|
||||
analytics.dispose();
|
||||
}
|
||||
|
||||
logger.info(`Initialized ${handlers.length} analytics handlers`);
|
||||
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,7 +235,7 @@ function _inIframe() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to load the scripts for the analytics handlers and creates them.
|
||||
* Tries to load the scripts for the external analytics handlers and creates them.
|
||||
*
|
||||
* @param {Array} scriptURLs - The array of script urls to load.
|
||||
* @param {Object} handlerConstructorOptions - The default options to pass when creating handlers.
|
||||
@@ -279,7 +286,7 @@ function _loadHandlers(scriptURLs = [], handlerConstructorOptions) {
|
||||
logger.warn(`Error creating analytics handler: ${error}`);
|
||||
}
|
||||
}
|
||||
logger.debug(`Loaded ${handlers.length} analytics handlers`);
|
||||
logger.debug(`Loaded ${handlers.length} external analytics handlers`);
|
||||
|
||||
return handlers;
|
||||
});
|
||||
|
||||
@@ -72,6 +72,11 @@ export default class AmplitudeHandler extends AbstractHandler {
|
||||
* @returns {Object}
|
||||
*/
|
||||
getIdentityProps() {
|
||||
// TODO: Remove when web and native Aplitude implementations are unified.
|
||||
if (navigator.product === 'ReactNative') {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
sessionId: amplitude.getInstance(this._amplitudeOptions).getSessionId(),
|
||||
deviceId: amplitude.getInstance(this._amplitudeOptions).options.deviceId,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import type { Dispatch } from 'redux';
|
||||
|
||||
import { API_ID } from '../../../modules/API/constants';
|
||||
import { setRoom } from '../base/conference';
|
||||
import {
|
||||
configWillLoad,
|
||||
@@ -15,7 +16,7 @@ import { connect, disconnect, setLocationURL } from '../base/connection';
|
||||
import { loadConfig } from '../base/lib-jitsi-meet';
|
||||
import { MEDIA_TYPE } from '../base/media';
|
||||
import { toState } from '../base/redux';
|
||||
import { createDesiredLocalTracks, isLocalVideoTrackMuted, isLocalTrackMuted } from '../base/tracks';
|
||||
import { createDesiredLocalTracks, isLocalCameraTrackMuted, isLocalTrackMuted } from '../base/tracks';
|
||||
import {
|
||||
addHashParamsToURL,
|
||||
getBackendSafeRoomName,
|
||||
@@ -23,6 +24,7 @@ import {
|
||||
parseURIString,
|
||||
toURLString
|
||||
} from '../base/util';
|
||||
import { isVpaasMeeting } from '../billing-counter/functions';
|
||||
import { clearNotifications, showNotification } from '../notifications';
|
||||
import { setFatalError } from '../overlay';
|
||||
|
||||
@@ -168,9 +170,11 @@ export function redirectWithStoredParams(pathname: string) {
|
||||
* window.location.pathname. If the specified pathname is relative, the context
|
||||
* root of the Web app will be prepended to the specified pathname before
|
||||
* assigning it to window.location.pathname.
|
||||
* @param {string} hashParam - Optional hash param to assign to
|
||||
* window.location.hash.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function redirectToStaticPage(pathname: string) {
|
||||
export function redirectToStaticPage(pathname: string, hashParam: ?string) {
|
||||
return () => {
|
||||
const windowLocation = window.location;
|
||||
let newPathname = pathname;
|
||||
@@ -184,6 +188,10 @@ export function redirectToStaticPage(pathname: string) {
|
||||
newPathname = getLocationContextRoot(windowLocation) + newPathname;
|
||||
}
|
||||
|
||||
if (hashParam) {
|
||||
windowLocation.hash = hashParam;
|
||||
}
|
||||
|
||||
windowLocation.pathname = newPathname;
|
||||
};
|
||||
}
|
||||
@@ -224,7 +232,7 @@ export function reloadNow() {
|
||||
function addTrackStateToURL(url, stateful) {
|
||||
const state = toState(stateful);
|
||||
const tracks = state['features/base/tracks'];
|
||||
const isVideoMuted = isLocalVideoTrackMuted(tracks);
|
||||
const isVideoMuted = isLocalCameraTrackMuted(tracks);
|
||||
const isAudioMuted = isLocalTrackMuted(tracks, MEDIA_TYPE.AUDIO);
|
||||
|
||||
return addHashParamsToURL(new URL(url), { // use new URL object in order to not pollute the passed parameter.
|
||||
@@ -284,8 +292,16 @@ export function maybeRedirectToWelcomePage(options: Object = {}) {
|
||||
|
||||
// if close page is enabled redirect to it, without further action
|
||||
if (enableClosePage) {
|
||||
if (isVpaasMeeting(getState())) {
|
||||
redirectToStaticPage('/');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const { isGuest, jwt } = getState()['features/base/jwt'];
|
||||
|
||||
let hashParam;
|
||||
|
||||
// save whether current user is guest or not, and pass auth token,
|
||||
// before navigating to close page
|
||||
window.sessionStorage.setItem('guest', isGuest);
|
||||
@@ -294,12 +310,15 @@ export function maybeRedirectToWelcomePage(options: Object = {}) {
|
||||
let path = 'close.html';
|
||||
|
||||
if (interfaceConfig.SHOW_PROMOTIONAL_CLOSE_PAGE) {
|
||||
if (Number(API_ID) === API_ID) {
|
||||
hashParam = `#jitsi_meet_external_api_id=${API_ID}`;
|
||||
}
|
||||
path = 'close3.html';
|
||||
} else if (!options.feedbackSubmitted) {
|
||||
path = 'close2.html';
|
||||
}
|
||||
|
||||
dispatch(redirectToStaticPage(`static/${path}`));
|
||||
dispatch(redirectToStaticPage(`static/${path}`, hashParam));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
import SplashScreen from 'react-native-splash-screen';
|
||||
|
||||
import { setColorScheme } from '../../base/color-scheme';
|
||||
import { DialogContainer } from '../../base/dialog';
|
||||
@@ -84,6 +85,8 @@ export class App extends AbstractApp {
|
||||
componentDidMount() {
|
||||
super.componentDidMount();
|
||||
|
||||
SplashScreen.hide();
|
||||
|
||||
this._init.then(() => {
|
||||
const { dispatch, getState } = this.state.store;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import '../base/sounds/middleware';
|
||||
import '../base/testing/middleware';
|
||||
import '../base/tracks/middleware';
|
||||
import '../base/user-interaction/middleware';
|
||||
import '../billing-counter/middleware';
|
||||
import '../calendar-sync/middleware';
|
||||
import '../chat/middleware';
|
||||
import '../conference/middleware';
|
||||
|
||||
@@ -24,12 +24,14 @@ import '../base/sounds/reducer';
|
||||
import '../base/testing/reducer';
|
||||
import '../base/tracks/reducer';
|
||||
import '../base/user-interaction/reducer';
|
||||
import '../billing-counter/reducer';
|
||||
import '../blur/reducer';
|
||||
import '../calendar-sync/reducer';
|
||||
import '../chat/reducer';
|
||||
import '../deep-linking/reducer';
|
||||
import '../device-selection/reducer';
|
||||
import '../dropbox/reducer';
|
||||
import '../dynamic-branding/reducer';
|
||||
import '../etherpad/reducer';
|
||||
import '../filmstrip/reducer';
|
||||
import '../follow-me/reducer';
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user