Compare commits
137 Commits
7184
...
jitsi-meet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7831ad809 | ||
|
|
80cfb80397 | ||
|
|
ae281e9935 | ||
|
|
b800ad8427 | ||
|
|
051cf67ce9 | ||
|
|
85e1333ad9 | ||
|
|
f02c7557af | ||
|
|
e82a5cf150 | ||
|
|
c92ce56110 | ||
|
|
4cae954eba | ||
|
|
b9d5838398 | ||
|
|
fcf723c679 | ||
|
|
06b67dcf44 | ||
|
|
61e9cacceb | ||
|
|
475c2f4606 | ||
|
|
20f2bfa449 | ||
|
|
4c0c36d233 | ||
|
|
59f1ee1e1e | ||
|
|
1af90a208e | ||
|
|
22c6b72a75 | ||
|
|
d8c7f8de81 | ||
|
|
f76122f0b0 | ||
|
|
63927db9e4 | ||
|
|
6b28af8329 | ||
|
|
ccebccf8e6 | ||
|
|
279a4efb83 | ||
|
|
ceac1ab25f | ||
|
|
2ba6bcf172 | ||
|
|
ae0669fa07 | ||
|
|
71627f97f7 | ||
|
|
e35338b73d | ||
|
|
a112d38943 | ||
|
|
b705c63a65 | ||
|
|
b4c8f7d097 | ||
|
|
74bac9806f | ||
|
|
65248d7d29 | ||
|
|
dc037bc8dd | ||
|
|
a22db037c7 | ||
|
|
44cc0f7e9a | ||
|
|
eafb337cd1 | ||
|
|
9b3be66287 | ||
|
|
1a10a00f74 | ||
|
|
a196bc27b8 | ||
|
|
ac8e4d9828 | ||
|
|
a6ade336b7 | ||
|
|
350443ad34 | ||
|
|
4c37ef7a2c | ||
|
|
3eedc2a49d | ||
|
|
aaeb1a90e5 | ||
|
|
ed89f9af20 | ||
|
|
863ad0b0e6 | ||
|
|
e2d701a8cc | ||
|
|
2710273069 | ||
|
|
07af18e284 | ||
|
|
519e37f567 | ||
|
|
7cf61eb776 | ||
|
|
f81446909c | ||
|
|
b4115593c0 | ||
|
|
f8bd8b616e | ||
|
|
be55ccd6f4 | ||
|
|
e7db18bd80 | ||
|
|
dff41e0fcb | ||
|
|
43be4324af | ||
|
|
c33baf4c96 | ||
|
|
f95a356025 | ||
|
|
1ba7765898 | ||
|
|
0346fca434 | ||
|
|
d267b2499d | ||
|
|
e3e5f1fbfa | ||
|
|
4697192b43 | ||
|
|
38a293f8f6 | ||
|
|
13e8f992b5 | ||
|
|
c384d0d3a9 | ||
|
|
2b71fa512b | ||
|
|
d381ceb040 | ||
|
|
e18c428f52 | ||
|
|
9fc32dc59b | ||
|
|
6f45622ef1 | ||
|
|
e56c7070c2 | ||
|
|
0aef7a36aa | ||
|
|
c030cf941e | ||
|
|
f6760e4ac7 | ||
|
|
9060c77307 | ||
|
|
a1d018eef4 | ||
|
|
3f724d8fb7 | ||
|
|
49d69a5a02 | ||
|
|
6db9e42876 | ||
|
|
ad3e8f9f53 | ||
|
|
9f39caa247 | ||
|
|
1402a63324 | ||
|
|
a9863e65c3 | ||
|
|
646c58f7d1 | ||
|
|
a78ea7ca9c | ||
|
|
8b8565bf60 | ||
|
|
b9e30f3c1b | ||
|
|
96b6edccf8 | ||
|
|
2af9dc88e6 | ||
|
|
eda25ca3c9 | ||
|
|
c99da17973 | ||
|
|
9e147d7842 | ||
|
|
d7afaf871f | ||
|
|
c4f6d37aa1 | ||
|
|
a5663872d9 | ||
|
|
007283aab3 | ||
|
|
3b612376f2 | ||
|
|
1a312e2140 | ||
|
|
6f5d0400b8 | ||
|
|
aec86cecc0 | ||
|
|
bf1dde7cd1 | ||
|
|
91e9005f08 | ||
|
|
57f9ea2865 | ||
|
|
1f6425fbfd | ||
|
|
e169979bab | ||
|
|
6e9e9c9a6a | ||
|
|
102a369bca | ||
|
|
b318b987a7 | ||
|
|
78ce68160a | ||
|
|
6aff616af4 | ||
|
|
0140a49641 | ||
|
|
732754c566 | ||
|
|
b360a9e572 | ||
|
|
f88fa81616 | ||
|
|
e0e66119f5 | ||
|
|
ba4784f149 | ||
|
|
7fb7c3de9c | ||
|
|
3d2d449d31 | ||
|
|
ca60c33dda | ||
|
|
162512496a | ||
|
|
7819c97839 | ||
|
|
e9c8603c3c | ||
|
|
9e165c337a | ||
|
|
58af1b98c0 | ||
|
|
6a077333c6 | ||
|
|
cb234e6b1b | ||
|
|
67a9f35176 | ||
|
|
9396e8b0c0 | ||
|
|
200d857012 |
@@ -1,6 +1,8 @@
|
||||
# The build artifacts of the jitsi-meet project.
|
||||
build/*
|
||||
|
||||
doc/*
|
||||
|
||||
# Third-party source code which we (1) do not want to modify or (2) try to
|
||||
# modify as little as possible.
|
||||
libs/*
|
||||
|
||||
16
.github/stale.yml
vendored
16
.github/stale.yml
vendored
@@ -1,16 +0,0 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 90
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- confirmed
|
||||
staleLabel: wontfix
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
|
||||
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@@ -12,14 +12,24 @@ jobs:
|
||||
with:
|
||||
node-version: 16
|
||||
cache: 'npm'
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v35
|
||||
- name: Get changed lang files
|
||||
id: lang-files
|
||||
run: echo "all=$(echo "${{ steps.changed-files.outputs.all_changed_files }}" | grep -oE 'lang\/\S+' | tr '\n' ' ')" >> "$GITHUB_OUTPUT"
|
||||
- run: npm install
|
||||
- name: Check git status
|
||||
run: git status
|
||||
- name: Normalize lang files to ensure sorted
|
||||
if: steps.lang-files.outputs.all
|
||||
run: npm run lang-sort
|
||||
- name: Check lang files are formatted correctly
|
||||
if: steps.lang-files.outputs.all
|
||||
run: npm run lint:lang
|
||||
- name: Check if the git repository is clean
|
||||
run: $(exit $(git status --porcelain --untracked-files=no | head -255 | wc -l)) || (echo "Dirty git tree"; git diff; exit 1)
|
||||
- run: npm run lint:ci
|
||||
- run: npm run lint:ci && npm run tsc:ci
|
||||
linux-build:
|
||||
name: Build Frontend (Linux)
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
21
.github/workflows/stale.yml
vendored
Normal file
21
.github/workflows/stale.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
name: 'Close stale issues and PRs'
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 1 * * *'
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v8
|
||||
with:
|
||||
stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.'
|
||||
stale-pr-message: 'This PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.'
|
||||
stale-issue-label: 'stale'
|
||||
stale-pr-label: 'stale'
|
||||
exempt-issue-labels: 'confirmed,help-needed'
|
||||
exempt-pr-labels: 'confirmed'
|
||||
days-before-issue-stale: 60
|
||||
days-before-pr-stale: 90
|
||||
days-before-issue-close: 10
|
||||
days-before-pr-close: 10
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -61,8 +61,9 @@ buck-out/
|
||||
|
||||
# fastlane
|
||||
#
|
||||
*/fastlane/report.xml
|
||||
*/fastlane/Preview.html
|
||||
**/fastlane/report.xml
|
||||
**/fastlane/Preview.html
|
||||
**/fastlane/test_output
|
||||
|
||||
# Build artifacts
|
||||
*.jsbundle
|
||||
|
||||
5
Makefile
5
Makefile
@@ -63,10 +63,7 @@ deploy-appbundle:
|
||||
|
||||
deploy-lib-jitsi-meet:
|
||||
cp \
|
||||
$(LIBJITSIMEET_DIR)/dist/umd/lib-jitsi-meet.min.js \
|
||||
$(LIBJITSIMEET_DIR)/dist/umd/lib-jitsi-meet.min.map \
|
||||
$(LIBJITSIMEET_DIR)/dist/umd/lib-jitsi-meet.e2ee-worker.js \
|
||||
$(LIBJITSIMEET_DIR)/modules/browser/capabilities.json \
|
||||
$(LIBJITSIMEET_DIR)/dist/umd/lib-jitsi-meet.* \
|
||||
$(DEPLOY_DIR)
|
||||
|
||||
deploy-olm:
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
android:extractNativeLibs="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:name=".MainApplication"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:theme="@style/AppTheme">
|
||||
<meta-data
|
||||
@@ -17,7 +16,8 @@
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask"
|
||||
android:launchMode="singleInstance"
|
||||
android:taskAffinity=""
|
||||
android:name=".MainActivity"
|
||||
android:resizeableActivity="true"
|
||||
android:supportsPictureInPicture="true"
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright @ 2022-present 8x8, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jitsi.meet;
|
||||
|
||||
import android.app.Application;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.react.ReactApplication;
|
||||
import com.facebook.react.ReactNativeHost;
|
||||
|
||||
import org.jitsi.meet.sdk.JitsiReactNativeHost;
|
||||
|
||||
/**
|
||||
* Application class for Jitsi Meet. The only reason why this exists is for Detox
|
||||
* to believe our app is a "greenfield" app. SDK users need not use this.
|
||||
*/
|
||||
public class MainApplication extends Application implements ReactApplication {
|
||||
private final ReactNativeHost mReactNativeHost = new JitsiReactNativeHost(this);
|
||||
|
||||
@Override
|
||||
public ReactNativeHost getReactNativeHost() {
|
||||
return mReactNativeHost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
// Initialize RN
|
||||
Log.d(this.getClass().getCanonicalName(), "app onCreate");
|
||||
getReactNativeHost().getReactInstanceManager();
|
||||
}
|
||||
}
|
||||
@@ -10,16 +10,17 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.0.4'
|
||||
classpath 'com.android.tools.build:gradle:7.1.1'
|
||||
classpath 'com.google.gms:google-services:4.3.14'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.2'
|
||||
}
|
||||
}
|
||||
|
||||
ext {
|
||||
kotlinVersion = "1.5.32"
|
||||
buildToolsVersion = "31.0.0"
|
||||
compileSdkVersion = 32
|
||||
minSdkVersion = 23
|
||||
minSdkVersion = 24
|
||||
targetSdkVersion = 32
|
||||
supportLibVersion = "28.0.0"
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ if [[ $MVN_HTTP == 1 ]]; then
|
||||
deploy:deploy-file \
|
||||
-Durl=${MVN_REPO} \
|
||||
-DrepositoryId=${MVN_REPO_ID} \
|
||||
-Dfile=react-native-${RN_VERSION}.aar \
|
||||
-Dfile=react-native-${RN_VERSION}-release.aar \
|
||||
-Dpackaging=aar \
|
||||
-DgeneratePom=false \
|
||||
-DpomFile=react-native-${RN_VERSION}.pom || true
|
||||
@@ -58,7 +58,7 @@ else
|
||||
mvn \
|
||||
deploy:deploy-file \
|
||||
-Durl=${MVN_REPO} \
|
||||
-Dfile=react-native-${RN_VERSION}.aar \
|
||||
-Dfile=react-native-${RN_VERSION}-release.aar \
|
||||
-Dpackaging=aar \
|
||||
-DgeneratePom=false \
|
||||
-DpomFile=react-native-${RN_VERSION}.pom
|
||||
|
||||
@@ -45,6 +45,12 @@ class AudioDeviceHandlerGeneric implements
|
||||
*/
|
||||
private AudioModeModule module;
|
||||
|
||||
/**
|
||||
* Constant defining a Hearing Aid. Only available on API level >= 28.
|
||||
* The value of: AudioDeviceInfo.TYPE_HEARING_AID
|
||||
*/
|
||||
private static final int TYPE_HEARING_AID = 23;
|
||||
|
||||
/**
|
||||
* Constant defining a USB headset. Only available on API level >= 26.
|
||||
* The value of: AudioDeviceInfo.TYPE_USB_HEADSET
|
||||
@@ -85,6 +91,7 @@ class AudioDeviceHandlerGeneric implements
|
||||
break;
|
||||
case AudioDeviceInfo.TYPE_WIRED_HEADPHONES:
|
||||
case AudioDeviceInfo.TYPE_WIRED_HEADSET:
|
||||
case TYPE_HEARING_AID:
|
||||
case TYPE_USB_HEADSET:
|
||||
devices.add(AudioModeModule.DEVICE_HEADPHONES);
|
||||
break;
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import org.webrtc.VideoCodecInfo;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
/** Container for static helper functions related to dealing with H264 codecs. */
|
||||
class H264Utils {
|
||||
public static final String H264_FMTP_PROFILE_LEVEL_ID = "profile-level-id";
|
||||
public static final String H264_FMTP_LEVEL_ASYMMETRY_ALLOWED = "level-asymmetry-allowed";
|
||||
public static final String H264_FMTP_PACKETIZATION_MODE = "packetization-mode";
|
||||
|
||||
public static final String H264_PROFILE_CONSTRAINED_BASELINE = "42e0";
|
||||
public static final String H264_PROFILE_CONSTRAINED_HIGH = "640c";
|
||||
public static final String H264_LEVEL_3_1 = "1f"; // 31 in hex.
|
||||
public static final String H264_CONSTRAINED_HIGH_3_1 =
|
||||
H264_PROFILE_CONSTRAINED_HIGH + H264_LEVEL_3_1;
|
||||
public static final String H264_CONSTRAINED_BASELINE_3_1 =
|
||||
H264_PROFILE_CONSTRAINED_BASELINE + H264_LEVEL_3_1;
|
||||
|
||||
public static Map<String, String> getDefaultH264Params(boolean isHighProfile) {
|
||||
final Map<String, String> params = new HashMap<>();
|
||||
params.put(VideoCodecInfo.H264_FMTP_LEVEL_ASYMMETRY_ALLOWED, "1");
|
||||
params.put(VideoCodecInfo.H264_FMTP_PACKETIZATION_MODE, "1");
|
||||
params.put(VideoCodecInfo.H264_FMTP_PROFILE_LEVEL_ID,
|
||||
isHighProfile ? VideoCodecInfo.H264_CONSTRAINED_HIGH_3_1
|
||||
: VideoCodecInfo.H264_CONSTRAINED_BASELINE_3_1);
|
||||
return params;
|
||||
}
|
||||
|
||||
public static VideoCodecInfo DEFAULT_H264_BASELINE_PROFILE_CODEC =
|
||||
new VideoCodecInfo("H264", getDefaultH264Params(/* isHighProfile= */ false));
|
||||
public static VideoCodecInfo DEFAULT_H264_HIGH_PROFILE_CODEC =
|
||||
new VideoCodecInfo("H264", getDefaultH264Params(/* isHighProfile= */ true));
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
@@ -177,8 +178,11 @@ public class JitsiMeetActivity extends AppCompatActivity
|
||||
}
|
||||
|
||||
protected void leave() {
|
||||
Intent hangupBroadcastIntent = BroadcastIntentHelper.buildHangUpIntent();
|
||||
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(hangupBroadcastIntent);
|
||||
if (this.jitsiView != null) {
|
||||
this.jitsiView.abort();
|
||||
} else {
|
||||
JitsiMeetLogger.w("Cannot leave, view is null");
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable
|
||||
@@ -295,6 +299,7 @@ public class JitsiMeetActivity extends AppCompatActivity
|
||||
JitsiMeetActivityDelegate.requestPermissions(this, permissions, requestCode, listener);
|
||||
}
|
||||
|
||||
@SuppressLint("MissingSuperCall")
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
JitsiMeetActivityDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
|
||||
@@ -157,6 +157,14 @@ public class JitsiMeetView extends FrameLayout {
|
||||
setProps(options != null ? options.asProps() : new Bundle());
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method which aborts running RN by passing empty props.
|
||||
* This is only meant to be used from the enclosing Activity's onDestroy.
|
||||
*/
|
||||
public void abort() {
|
||||
setProps(new Bundle());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the {@code ReactRootView} for the given app name with the given
|
||||
* props. Once created it's set as the view of this {@code FrameLayout}.
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
import com.facebook.react.ReactNativeHost;
|
||||
import com.facebook.react.ReactPackage;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This is the minimal implementation of ReactNativeHost that will make things like the
|
||||
* Detox testing framework believe we are a "greenfield" app.
|
||||
*
|
||||
* Generally speaking, apps using the SDK (other than the Jitsi Meet app itself) should not
|
||||
* need to use this because the
|
||||
*/
|
||||
public class JitsiReactNativeHost extends ReactNativeHost {
|
||||
public JitsiReactNativeHost(Application application) {
|
||||
super(application);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getUseDeveloperSupport() {
|
||||
// Unused since we override `createReactInstanceManager`.
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
// Unused since we override `createReactInstanceManager`.
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ReactInstanceManager createReactInstanceManager() {
|
||||
ReactInstanceManagerHolder.initReactInstanceManager(this.getApplication());
|
||||
|
||||
return ReactInstanceManagerHolder.getReactInstanceManager();
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -32,17 +31,17 @@ import com.facebook.react.jscexecutor.JSCExecutorFactory;
|
||||
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
import com.oney.WebRTCModule.EglUtils;
|
||||
import com.oney.WebRTCModule.RTCVideoViewManager;
|
||||
import com.oney.WebRTCModule.WebRTCModule;
|
||||
import com.oney.WebRTCModule.WebRTCModuleOptions;
|
||||
import com.oney.WebRTCModule.webrtcutils.H264AndSoftwareVideoDecoderFactory;
|
||||
import com.oney.WebRTCModule.webrtcutils.H264AndSoftwareVideoEncoderFactory;
|
||||
|
||||
import org.devio.rn.splashscreen.SplashScreenModule;
|
||||
import org.webrtc.EglBase;
|
||||
import org.webrtc.audio.AudioDeviceModule;
|
||||
import org.webrtc.audio.JavaAudioDeviceModule;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
class ReactInstanceManagerHolder {
|
||||
@@ -79,30 +78,11 @@ class ReactInstanceManagerHolder {
|
||||
nativeModules.add(new RNConnectionService(reactContext));
|
||||
}
|
||||
|
||||
// Initialize the WebRTC module by hand, since we want to override some
|
||||
// initialization options.
|
||||
WebRTCModule.Options options = new WebRTCModule.Options();
|
||||
|
||||
AudioDeviceModule adm = JavaAudioDeviceModule.builder(reactContext)
|
||||
.setEnableVolumeLogger(false)
|
||||
.createAudioDeviceModule();
|
||||
options.setAudioDeviceModule(adm);
|
||||
|
||||
EglBase.Context eglContext = EglUtils.getRootEglBaseContext();
|
||||
|
||||
options.setVideoDecoderFactory(new WebRTCVideoDecoderFactory(eglContext));
|
||||
options.setVideoEncoderFactory(new WebRTCVideoEncoderFactory(eglContext));
|
||||
|
||||
nativeModules.add(new WebRTCModule(reactContext, options));
|
||||
|
||||
return nativeModules;
|
||||
}
|
||||
|
||||
private static List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
||||
return Arrays.<ViewManager>asList(
|
||||
// WebRTC, see createNativeModules for details.
|
||||
new RTCVideoViewManager()
|
||||
);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
static List<ReactPackage> getReactNativePackages() {
|
||||
@@ -122,6 +102,7 @@ class ReactInstanceManagerHolder {
|
||||
new com.reactnativecommunity.webview.RNCWebViewPackage(),
|
||||
new com.kevinresol.react_native_default_preference.RNDefaultPreferencePackage(),
|
||||
new com.learnium.RNDeviceInfo.RNDeviceInfo(),
|
||||
new com.oney.WebRTCModule.WebRTCModulePackage(),
|
||||
new com.swmansion.gesturehandler.RNGestureHandlerPackage(),
|
||||
new org.linusu.RNGetRandomValuesPackage(),
|
||||
new com.rnimmersive.RNImmersivePackage(),
|
||||
@@ -239,35 +220,6 @@ class ReactInstanceManagerHolder {
|
||||
return reactInstanceManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method to initialize the React Native instance manager. We
|
||||
* create a single instance in order to load the JavaScript bundle a single
|
||||
* time. All {@code ReactRootView} instances will be tied to the one and
|
||||
* only {@code ReactInstanceManager}.
|
||||
*
|
||||
* This method is only meant to be called when integrating with {@code JitsiReactNativeHost}.
|
||||
*
|
||||
* @param app {@code Application} current running Application.
|
||||
*/
|
||||
static void initReactInstanceManager(Application app) {
|
||||
if (reactInstanceManager != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(TAG, "initializing RN with Application");
|
||||
|
||||
reactInstanceManager
|
||||
= ReactInstanceManager.builder()
|
||||
.setApplication(app)
|
||||
.setBundleAssetName("index.android.bundle")
|
||||
.setJSMainModulePath("index.android")
|
||||
.setJavaScriptExecutorFactory(getReactNativeJSFactory())
|
||||
.addPackages(getReactNativePackages())
|
||||
.setUseDeveloperSupport(BuildConfig.DEBUG)
|
||||
.setInitialLifecycleState(LifecycleState.BEFORE_CREATE)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method to initialize the React Native instance manager. We
|
||||
* create a single instance in order to load the JavaScript bundle a single
|
||||
@@ -281,7 +233,15 @@ class ReactInstanceManagerHolder {
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(ReactInstanceManagerHolder.class.getCanonicalName(), "initializing RN with Activity");
|
||||
// Initialize the WebRTC module options.
|
||||
WebRTCModuleOptions options = WebRTCModuleOptions.getInstance();
|
||||
|
||||
EglBase.Context eglContext = EglUtils.getRootEglBaseContext();
|
||||
|
||||
options.videoDecoderFactory = new H264AndSoftwareVideoDecoderFactory(eglContext);
|
||||
options.videoEncoderFactory = new H264AndSoftwareVideoEncoderFactory(eglContext);
|
||||
|
||||
Log.d(TAG, "initializing RN with Activity");
|
||||
|
||||
reactInstanceManager
|
||||
= ReactInstanceManager.builder()
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
/** Enumeration of supported video codec types. */
|
||||
public enum VideoCodecMimeType {
|
||||
VP8("video/x-vnd.on2.vp8"),
|
||||
VP9("video/x-vnd.on2.vp9"),
|
||||
H264("video/avc"),
|
||||
AV1("video/av01");
|
||||
|
||||
private final String mimeType;
|
||||
|
||||
private VideoCodecMimeType(String mimeType) {
|
||||
this.mimeType = mimeType;
|
||||
}
|
||||
|
||||
String mimeType() {
|
||||
return mimeType;
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.webrtc.EglBase;
|
||||
import org.webrtc.HardwareVideoDecoderFactory;
|
||||
import org.webrtc.SoftwareVideoDecoderFactory;
|
||||
import org.webrtc.VideoCodecInfo;
|
||||
import org.webrtc.VideoDecoder;
|
||||
import org.webrtc.VideoDecoderFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This is a custom video decoder factory for WebRTC which behaves similarly
|
||||
* to the default one in iOS. It supports the following codecs:
|
||||
*
|
||||
* - In hardware: H.264 (baseline)
|
||||
* - In software: VP8, VP9, AV1
|
||||
*/
|
||||
public class WebRTCVideoDecoderFactory implements VideoDecoderFactory {
|
||||
private final VideoDecoderFactory hardwareVideoDecoderFactory;
|
||||
private final VideoDecoderFactory softwareVideoDecoderFactory = new SoftwareVideoDecoderFactory();
|
||||
|
||||
public WebRTCVideoDecoderFactory(@Nullable EglBase.Context eglContext) {
|
||||
this.hardwareVideoDecoderFactory = new HardwareVideoDecoderFactory(eglContext);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public VideoDecoder createDecoder(VideoCodecInfo codecInfo) {
|
||||
if (codecInfo.name.equalsIgnoreCase(VideoCodecMimeType.H264.name())) {
|
||||
return this.hardwareVideoDecoderFactory.createDecoder(codecInfo);
|
||||
}
|
||||
|
||||
return this.softwareVideoDecoderFactory.createDecoder(codecInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VideoCodecInfo[] getSupportedCodecs() {
|
||||
List<VideoCodecInfo> codecs = new ArrayList<>();
|
||||
|
||||
codecs.add(H264Utils.DEFAULT_H264_BASELINE_PROFILE_CODEC);
|
||||
codecs.add(new VideoCodecInfo(VideoCodecMimeType.VP8.name(), new HashMap<>()));
|
||||
codecs.add(new VideoCodecInfo(VideoCodecMimeType.VP9.name(), new HashMap<>()));
|
||||
codecs.add(new VideoCodecInfo(VideoCodecMimeType.AV1.name(), new HashMap<>()));
|
||||
|
||||
return codecs.toArray(new VideoCodecInfo[codecs.size()]);
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.webrtc.EglBase;
|
||||
import org.webrtc.HardwareVideoEncoderFactory;
|
||||
import org.webrtc.SoftwareVideoEncoderFactory;
|
||||
import org.webrtc.VideoCodecInfo;
|
||||
import org.webrtc.VideoEncoder;
|
||||
import org.webrtc.VideoEncoderFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This is a custom video encoder factory for WebRTC which behaves similarly
|
||||
* to the default one in iOS. It supports the following codecs:
|
||||
*
|
||||
* - In hardware: H.264 (baseline)
|
||||
* - In software: VP8, VP9, AV1
|
||||
*/
|
||||
public class WebRTCVideoEncoderFactory implements VideoEncoderFactory {
|
||||
private final VideoEncoderFactory hardwareVideoEncoderFactory;
|
||||
private final VideoEncoderFactory softwareVideoEncoderFactory = new SoftwareVideoEncoderFactory();
|
||||
|
||||
public WebRTCVideoEncoderFactory(@Nullable EglBase.Context eglContext) {
|
||||
this.hardwareVideoEncoderFactory =
|
||||
new HardwareVideoEncoderFactory(eglContext, false, false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public VideoEncoder createEncoder(VideoCodecInfo codecInfo) {
|
||||
if (codecInfo.name.equalsIgnoreCase(VideoCodecMimeType.H264.name())) {
|
||||
return this.hardwareVideoEncoderFactory.createEncoder(codecInfo);
|
||||
}
|
||||
|
||||
return this.softwareVideoEncoderFactory.createEncoder(codecInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VideoCodecInfo[] getSupportedCodecs() {
|
||||
List<VideoCodecInfo> codecs = new ArrayList<>();
|
||||
|
||||
codecs.add(H264Utils.DEFAULT_H264_BASELINE_PROFILE_CODEC);
|
||||
codecs.add(new VideoCodecInfo(VideoCodecMimeType.VP8.name(), new HashMap<>()));
|
||||
codecs.add(new VideoCodecInfo(VideoCodecMimeType.VP9.name(), new HashMap<>()));
|
||||
codecs.add(new VideoCodecInfo(VideoCodecMimeType.AV1.name(), new HashMap<>()));
|
||||
|
||||
return codecs.toArray(new VideoCodecInfo[codecs.size()]);
|
||||
}
|
||||
}
|
||||
2
app.js
2
app.js
@@ -18,7 +18,6 @@ import './react/features/base/jitsi-local-storage/setup';
|
||||
import conference from './conference';
|
||||
import API from './modules/API';
|
||||
import UI from './modules/UI/UI';
|
||||
import keyboardshortcut from './modules/keyboardshortcut/keyboardshortcut';
|
||||
import translation from './modules/translation/translation';
|
||||
|
||||
// Initialize Olm as early as possible.
|
||||
@@ -38,7 +37,6 @@ window.APP = {
|
||||
'index.loaded': window.indexLoadedTime
|
||||
},
|
||||
|
||||
keyboardshortcut,
|
||||
translation,
|
||||
UI
|
||||
};
|
||||
|
||||
217
conference.js
217
conference.js
@@ -140,6 +140,7 @@ import { downloadJSON } from './react/features/base/util/downloadJSON';
|
||||
import { showDesktopPicker } from './react/features/desktop-picker/actions';
|
||||
import { appendSuffix } from './react/features/display-name/functions';
|
||||
import { maybeOpenFeedbackDialog, submitFeedback } from './react/features/feedback/actions';
|
||||
import { initKeyboardShortcuts } from './react/features/keyboard-shortcuts/actions';
|
||||
import { maybeSetLobbyChatMessageListener } from './react/features/lobby/actions.any';
|
||||
import { setNoiseSuppressionEnabled } from './react/features/noise-suppression/actions';
|
||||
import { hideNotification, showNotification, showWarningNotification } from './react/features/notifications/actions';
|
||||
@@ -162,6 +163,7 @@ import { endpointMessageReceived } from './react/features/subtitles/actions.any'
|
||||
import { handleToggleVideoMuted } from './react/features/toolbox/actions.any';
|
||||
import { muteLocal } from './react/features/video-menu/actions.any';
|
||||
import { setIAmVisitor } from './react/features/visitors/actions';
|
||||
import { iAmVisitor } from './react/features/visitors/functions';
|
||||
import UIEvents from './service/UI/UIEvents';
|
||||
|
||||
const logger = Logger.getLogger(__filename);
|
||||
@@ -359,11 +361,11 @@ class ConferenceConnector {
|
||||
const [ vnode ] = params;
|
||||
|
||||
APP.store.dispatch(overwriteConfig(newConfig))
|
||||
.then(this._conference.leaveRoom())
|
||||
.then(APP.store.dispatch(setIAmVisitor(Boolean(vnode))))
|
||||
.then(() => this._conference.leaveRoom())
|
||||
.then(() => APP.store.dispatch(setIAmVisitor(Boolean(vnode))))
|
||||
|
||||
// we do not clear local tracks on error, so we need to manually clear them
|
||||
.then(APP.store.dispatch(destroyLocalTracks()))
|
||||
.then(() => APP.store.dispatch(destroyLocalTracks()))
|
||||
.then(() => {
|
||||
// Reset VideoLayout. It's destroyed in features/video-layout/middleware.web.js so re-initialize it.
|
||||
VideoLayout.initLargeVideo();
|
||||
@@ -416,7 +418,7 @@ class ConferenceConnector {
|
||||
|
||||
if (newConfig) {
|
||||
APP.store.dispatch(overwriteConfig(newConfig))
|
||||
.then(this._conference.leaveRoom())
|
||||
.then(() => this._conference.leaveRoom())
|
||||
.then(() => {
|
||||
_connectionPromise = connect(this._conference.roomName);
|
||||
|
||||
@@ -557,7 +559,7 @@ export default {
|
||||
);
|
||||
}
|
||||
|
||||
let tryCreateLocalTracks;
|
||||
let tryCreateLocalTracks = Promise.resolve([]);
|
||||
|
||||
// On Electron there is no permission prompt for granting permissions. That's why we don't need to
|
||||
// spend much time displaying the overlay screen. If GUM is not resolved within 15 seconds it will
|
||||
@@ -598,76 +600,65 @@ export default {
|
||||
|
||||
return [];
|
||||
});
|
||||
} else if (!requestedAudio && !requestedVideo) {
|
||||
// Resolve with no tracks
|
||||
tryCreateLocalTracks = Promise.resolve([]);
|
||||
} else {
|
||||
} else if (requestedAudio || requestedVideo) {
|
||||
tryCreateLocalTracks = createLocalTracksF({
|
||||
devices: initialDevices,
|
||||
timeout,
|
||||
firePermissionPromptIsShownEvent: true
|
||||
})
|
||||
.catch(err => {
|
||||
if (requestedAudio && requestedVideo) {
|
||||
|
||||
// Try audio only...
|
||||
errors.audioAndVideoError = err;
|
||||
|
||||
if (err.name === JitsiTrackErrors.TIMEOUT && !browser.isElectron()) {
|
||||
// In this case we expect that the permission prompt is still visible. There is no point of
|
||||
// executing GUM with different source. Also at the time of writing the following
|
||||
// inconsistency have been noticed in some browsers - if the permissions prompt is visible
|
||||
// and another GUM is executed the prompt does not change its content but if the user
|
||||
// clicks allow the user action isassociated with the latest GUM call.
|
||||
errors.audioOnlyError = err;
|
||||
errors.videoOnlyError = err;
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
return createLocalTracksF(audioOptions);
|
||||
} else if (requestedAudio && !requestedVideo) {
|
||||
errors.audioOnlyError = err;
|
||||
|
||||
return [];
|
||||
} else if (requestedVideo && !requestedAudio) {
|
||||
errors.videoOnlyError = err;
|
||||
|
||||
return [];
|
||||
}
|
||||
logger.error('Should never happen');
|
||||
})
|
||||
.catch(err => {
|
||||
// Log this just in case...
|
||||
if (!requestedAudio) {
|
||||
logger.error('The impossible just happened', err);
|
||||
}
|
||||
errors.audioOnlyError = err;
|
||||
|
||||
// Try video only...
|
||||
return requestedVideo
|
||||
? createLocalTracksF({
|
||||
devices: [ MEDIA_TYPE.VIDEO ],
|
||||
firePermissionPromptIsShownEvent: true
|
||||
})
|
||||
: [];
|
||||
})
|
||||
.catch(err => {
|
||||
// Log this just in case...
|
||||
if (!requestedVideo) {
|
||||
logger.error('The impossible just happened', err);
|
||||
}
|
||||
errors.videoOnlyError = err;
|
||||
.catch(async error => {
|
||||
if (error.name === JitsiTrackErrors.TIMEOUT && !browser.isElectron()) {
|
||||
errors.audioAndVideoError = error;
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
// Retry with separate gUM calls.
|
||||
const gUMPromises = [];
|
||||
const tracks = [];
|
||||
|
||||
if (requestedAudio) {
|
||||
gUMPromises.push(createLocalTracksF(audioOptions));
|
||||
}
|
||||
|
||||
if (requestedVideo) {
|
||||
gUMPromises.push(createLocalTracksF({
|
||||
devices: [ MEDIA_TYPE.VIDEO ],
|
||||
timeout,
|
||||
firePermissionPromptIsShownEvent: true
|
||||
}));
|
||||
}
|
||||
|
||||
const results = await Promise.allSettled(gUMPromises);
|
||||
let errorMsg;
|
||||
|
||||
results.forEach((result, idx) => {
|
||||
if (result.status === 'fulfilled') {
|
||||
tracks.push(result.value[0]);
|
||||
} else {
|
||||
errorMsg = result.reason;
|
||||
const isAudio = idx === 0;
|
||||
|
||||
logger.error(`${isAudio ? 'Audio' : 'Video'} track creation failed with error ${errorMsg}`);
|
||||
if (isAudio) {
|
||||
errors.audioOnlyError = errorMsg;
|
||||
} else {
|
||||
errors.videoOnlyError = errorMsg;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (errors.audioOnlyError && errors.videoOnlyError) {
|
||||
errors.audioAndVideoError = errorMsg;
|
||||
}
|
||||
|
||||
return tracks;
|
||||
});
|
||||
}
|
||||
|
||||
// Hide the permissions prompt/overlay as soon as the tracks are
|
||||
// created. Don't wait for the connection to be made, since in some
|
||||
// cases, when auth is required, for instance, that won't happen until
|
||||
// the user inputs their credentials, but the dialog would be
|
||||
// overshadowed by the overlay.
|
||||
// Hide the permissions prompt/overlay as soon as the tracks are created. Don't wait for the connection to
|
||||
// be established, as in some cases like when auth is required, connection won't be established until the user
|
||||
// inputs their credentials, but the dialog would be overshadowed by the overlay.
|
||||
tryCreateLocalTracks.then(tracks => {
|
||||
APP.store.dispatch(mediaPermissionPromptVisibilityChanged(false));
|
||||
|
||||
@@ -804,46 +795,55 @@ export default {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
async init({ roomName }) {
|
||||
const state = APP.store.getState();
|
||||
const initialOptions = {
|
||||
startAudioOnly: config.startAudioOnly,
|
||||
startScreenSharing: config.startScreenSharing,
|
||||
startWithAudioMuted: getStartWithAudioMuted(APP.store.getState())
|
||||
|| isUserInteractionRequiredForUnmute(APP.store.getState()),
|
||||
startWithVideoMuted: getStartWithVideoMuted(APP.store.getState())
|
||||
|| isUserInteractionRequiredForUnmute(APP.store.getState())
|
||||
startWithAudioMuted: getStartWithAudioMuted(state) || isUserInteractionRequiredForUnmute(state),
|
||||
startWithVideoMuted: getStartWithVideoMuted(state) || isUserInteractionRequiredForUnmute(state)
|
||||
};
|
||||
|
||||
this.roomName = roomName;
|
||||
|
||||
try {
|
||||
// Initialize the device list first. This way, when creating tracks
|
||||
// based on preferred devices, loose label matching can be done in
|
||||
// cases where the exact ID match is no longer available, such as
|
||||
// when the camera device has switched USB ports.
|
||||
// when in startSilent mode we want to start with audio muted
|
||||
// Initialize the device list first. This way, when creating tracks based on preferred devices, loose label
|
||||
// matching can be done in cases where the exact ID match is no longer available, such as -
|
||||
// 1. When the camera device has switched USB ports.
|
||||
// 2. When in startSilent mode we want to start with audio muted
|
||||
await this._initDeviceList();
|
||||
} catch (error) {
|
||||
logger.warn('initial device list initialization failed', error);
|
||||
}
|
||||
|
||||
const handleStartAudioMuted = (options, tracks) => {
|
||||
if (options.startWithAudioMuted) {
|
||||
// Filter out the local tracks based on various config options, i.e., when user joins muted or is muted by
|
||||
// focus. However, audio track will always be created even though it is not added to the conference since we
|
||||
// want audio related features (noisy mic, talk while muted, etc.) to work even if the mic is muted.
|
||||
const handleInitialTracks = (options, tracks) => {
|
||||
let localTracks = tracks;
|
||||
|
||||
// No local tracks are added when user joins as a visitor.
|
||||
if (iAmVisitor(state)) {
|
||||
return [];
|
||||
}
|
||||
if (options.startWithAudioMuted || room?.isStartAudioMuted()) {
|
||||
// Always add the track on Safari because of a known issue where audio playout doesn't happen
|
||||
// if the user joins audio and video muted, i.e., if there is no local media capture.
|
||||
if (browser.isWebKitBased()) {
|
||||
this.muteAudio(true, true);
|
||||
} else {
|
||||
return tracks.filter(track => track.getType() !== MEDIA_TYPE.AUDIO);
|
||||
localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.AUDIO);
|
||||
}
|
||||
}
|
||||
if (room?.isStartVideoMuted()) {
|
||||
localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.VIDEO);
|
||||
}
|
||||
|
||||
return tracks;
|
||||
return localTracks;
|
||||
};
|
||||
|
||||
if (isPrejoinPageVisible(APP.store.getState())) {
|
||||
if (isPrejoinPageVisible(state)) {
|
||||
_connectionPromise = connect(roomName).then(c => {
|
||||
// we want to initialize it early, in case of errors to be able
|
||||
// to gather logs
|
||||
// We want to initialize it early, in case of errors to be able to gather logs.
|
||||
APP.connection = c;
|
||||
|
||||
return c;
|
||||
@@ -856,43 +856,28 @@ export default {
|
||||
APP.store.dispatch(makePrecallTest(this._getConferenceOptions()));
|
||||
|
||||
const { tryCreateLocalTracks, errors } = this.createInitialLocalTracks(initialOptions);
|
||||
const tracks = await tryCreateLocalTracks;
|
||||
const localTracks = await tryCreateLocalTracks;
|
||||
|
||||
// Initialize device list a second time to ensure device labels
|
||||
// get populated in case of an initial gUM acceptance; otherwise
|
||||
// they may remain as empty strings.
|
||||
// Initialize device list a second time to ensure device labels get populated in case of an initial gUM
|
||||
// acceptance; otherwise they may remain as empty strings.
|
||||
this._initDeviceList(true);
|
||||
|
||||
if (isPrejoinPageVisible(APP.store.getState())) {
|
||||
return APP.store.dispatch(initPrejoin(tracks, errors));
|
||||
if (isPrejoinPageVisible(state)) {
|
||||
return APP.store.dispatch(initPrejoin(localTracks, errors));
|
||||
}
|
||||
|
||||
logger.debug('Prejoin screen no longer displayed at the time when tracks were created');
|
||||
|
||||
this._displayErrorsForCreateInitialLocalTracks(errors);
|
||||
|
||||
let localTracks = handleStartAudioMuted(initialOptions, tracks);
|
||||
|
||||
// in case where gum is slow and resolves after the startAudio/VideoMuted coming from jicofo, we can be
|
||||
// join unmuted even though jicofo had instruct us to mute, so let's respect that before passing the tracks
|
||||
if (!browser.isWebKitBased()) {
|
||||
if (room?.isStartAudioMuted()) {
|
||||
localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.AUDIO);
|
||||
}
|
||||
}
|
||||
|
||||
if (room?.isStartVideoMuted()) {
|
||||
localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.VIDEO);
|
||||
}
|
||||
|
||||
return this._setLocalAudioVideoStreams(localTracks);
|
||||
return this._setLocalAudioVideoStreams(handleInitialTracks(initialOptions, localTracks));
|
||||
}
|
||||
|
||||
const [ tracks, con ] = await this.createInitialLocalTracksAndConnect(roomName, initialOptions);
|
||||
|
||||
this._initDeviceList(true);
|
||||
|
||||
return this.startConference(con, handleStartAudioMuted(initialOptions, tracks));
|
||||
return this.startConference(con, handleInitialTracks(initialOptions, tracks));
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -1065,7 +1050,7 @@ export default {
|
||||
*/
|
||||
muteVideo(mute, showUI = true) {
|
||||
if (this.videoSwitchInProgress) {
|
||||
console.warn('muteVideo - unable to perform operations while video switch is in progress');
|
||||
logger.warn('muteVideo - unable to perform operations while video switch is in progress');
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -2301,10 +2286,7 @@ export default {
|
||||
|
||||
APP.UI.initConference();
|
||||
|
||||
if (!config.disableShortcuts) {
|
||||
APP.keyboardshortcut.init();
|
||||
}
|
||||
|
||||
dispatch(initKeyboardShortcuts());
|
||||
dispatch(conferenceJoined(room));
|
||||
|
||||
const jwt = APP.store.getState()['features/base/jwt'];
|
||||
@@ -2638,17 +2620,22 @@ export default {
|
||||
async leaveRoom(doDisconnect = true, reason = '') {
|
||||
APP.store.dispatch(conferenceWillLeave(room));
|
||||
|
||||
const maybeDisconnect = () => {
|
||||
if (doDisconnect) {
|
||||
return disconnect();
|
||||
}
|
||||
};
|
||||
|
||||
if (room && room.isJoined()) {
|
||||
return room.leave(reason).finally(() => {
|
||||
if (doDisconnect) {
|
||||
return disconnect();
|
||||
}
|
||||
return room.leave(reason).then(() => maybeDisconnect())
|
||||
.catch(e => {
|
||||
logger.error(e);
|
||||
|
||||
return maybeDisconnect();
|
||||
});
|
||||
}
|
||||
|
||||
if (doDisconnect) {
|
||||
return disconnect();
|
||||
}
|
||||
return maybeDisconnect();
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -1406,6 +1406,7 @@ var config = {
|
||||
disableAGC
|
||||
disableAP
|
||||
disableHPF
|
||||
disableLocalStats
|
||||
disableNS
|
||||
enableTalkWhileMuted
|
||||
forceJVB121Ratio
|
||||
|
||||
@@ -108,6 +108,10 @@
|
||||
#largeVideoContainer {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
#largeVideoWrapper {
|
||||
|
||||
@@ -60,7 +60,6 @@ $flagsImagePath: "../images/";
|
||||
@import 'filmstrip/vertical_filmstrip';
|
||||
@import 'filmstrip/vertical_filmstrip_overrides';
|
||||
@import 'unsupported-browser/main';
|
||||
@import 'modals/invite/add-people';
|
||||
@import 'deep-linking/main';
|
||||
@import 'transcription-subtitles';
|
||||
@import '_meetings_list.scss';
|
||||
|
||||
@@ -12,24 +12,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Styling inline dialog errors.
|
||||
*/
|
||||
.inline-dialog-error {
|
||||
margin-top: 16px;
|
||||
|
||||
&-text {
|
||||
color: $dialogErrorText;
|
||||
margin-bottom: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&-button {
|
||||
display: block;
|
||||
margin: 16px auto 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Styling shared video dialog errors.
|
||||
*/
|
||||
|
||||
@@ -41,10 +41,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Styles errors in the MultiSelectAutocomplete.
|
||||
*/
|
||||
.autocomplete-error {
|
||||
min-width: 260px;
|
||||
}
|
||||
|
||||
@@ -57,6 +57,10 @@
|
||||
line-height: 24px;
|
||||
border-collapse: collapse;
|
||||
|
||||
* {
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
thead {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
@@ -1,57 +1,4 @@
|
||||
.invite-more {
|
||||
&-container {
|
||||
margin-bottom: 8px;
|
||||
transition: margin-bottom 0.3s;
|
||||
|
||||
&.elevated {
|
||||
margin-bottom: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
&-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
border-radius: 8px;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&-header {
|
||||
max-width: 100%;
|
||||
margin-bottom: 16px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&-button {
|
||||
display: flex;
|
||||
max-width: 100%;
|
||||
height: 40px;
|
||||
box-sizing: border-box;
|
||||
padding: 8px 16px;
|
||||
background: #0376DA;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
|
||||
@media (hover: hover) and (pointer: fine) {
|
||||
&:hover {
|
||||
background: #278ADF;
|
||||
}
|
||||
}
|
||||
|
||||
&-text {
|
||||
margin-left: 8px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
&-dialog {
|
||||
color: #fff;
|
||||
font-size: 15px;
|
||||
@@ -65,59 +12,6 @@
|
||||
background: #5E6D7A;
|
||||
}
|
||||
|
||||
&.email-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 8px 8px 16px;
|
||||
margin-top: 24px;
|
||||
width: calc(100% - 26px);
|
||||
height: 22px;
|
||||
|
||||
background: #2A3A4B;
|
||||
border: 1px solid #5E6D7A;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
|
||||
&.active {
|
||||
border-radius: 3px 3px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.invite-buttons {
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
margin-top: 8px;
|
||||
|
||||
& > a {
|
||||
display: inline-block;
|
||||
height: 24px;
|
||||
min-width: 48px;
|
||||
border-radius: 3px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&-cancel {
|
||||
margin-right: 16px;
|
||||
padding: 7px 15px;
|
||||
background: #2A3A4B;
|
||||
border: 1px solid #5E6D7A;
|
||||
}
|
||||
|
||||
&-add {
|
||||
padding: 8px 16px;
|
||||
background: #0376DA;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
& > a {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.stream {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -158,14 +52,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-browser {
|
||||
.invite-more-content {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.invite-more-button {
|
||||
height: 48px;
|
||||
padding: 12px 16px;
|
||||
}
|
||||
}
|
||||
|
||||
3
debian/jitsi-meet-web-config.install
vendored
3
debian/jitsi-meet-web-config.install
vendored
@@ -1,3 +1,6 @@
|
||||
doc/debian/jitsi-meet/jitsi-meet.example /usr/share/jitsi-meet-web-config/
|
||||
doc/debian/jitsi-meet/jitsi-meet.example-apache /usr/share/jitsi-meet-web-config/
|
||||
config.js /usr/share/jitsi-meet-web-config/
|
||||
doc/jaas/nginx-jaas.conf /usr/share/jitsi-meet-web-config/
|
||||
doc/jaas/index-jaas.html /usr/share/jitsi-meet-web-config/
|
||||
doc/jaas/8x8.vc-config.js /usr/share/jitsi-meet-web-config/
|
||||
|
||||
2
debian/jitsi-meet-web.install
vendored
2
debian/jitsi-meet-web.install
vendored
@@ -12,3 +12,5 @@ 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/
|
||||
doc/jaas/move-to-jaas.sh /usr/share/jitsi-meet/scripts/
|
||||
doc/jaas/update-asap-daily.sh /usr/share/jitsi-meet/scripts/
|
||||
|
||||
@@ -78,13 +78,18 @@ Component "conference.jitmeet.example.com" "muc"
|
||||
restrict_room_creation = true
|
||||
storage = "memory"
|
||||
modules_enabled = {
|
||||
"muc_hide_all";
|
||||
"muc_meeting_id";
|
||||
"muc_domain_mapper";
|
||||
"polls";
|
||||
--"token_verification";
|
||||
"muc_rate_limit";
|
||||
"muc_password_whitelist";
|
||||
}
|
||||
admins = { "focusUser@auth.jitmeet.example.com" }
|
||||
muc_password_whitelist = {
|
||||
"focusUser@auth.jitmeet.example.com"
|
||||
}
|
||||
muc_room_locking = false
|
||||
muc_room_default_public_jids = true
|
||||
|
||||
@@ -92,6 +97,7 @@ Component "breakout.jitmeet.example.com" "muc"
|
||||
restrict_room_creation = true
|
||||
storage = "memory"
|
||||
modules_enabled = {
|
||||
"muc_hide_all";
|
||||
"muc_meeting_id";
|
||||
"muc_domain_mapper";
|
||||
"muc_rate_limit";
|
||||
@@ -105,6 +111,7 @@ Component "breakout.jitmeet.example.com" "muc"
|
||||
Component "internal.auth.jitmeet.example.com" "muc"
|
||||
storage = "memory"
|
||||
modules_enabled = {
|
||||
"muc_hide_all";
|
||||
"ping";
|
||||
}
|
||||
admins = { "focusUser@auth.jitmeet.example.com", "jvb@auth.jitmeet.example.com" }
|
||||
@@ -139,6 +146,7 @@ Component "lobby.jitmeet.example.com" "muc"
|
||||
muc_room_locking = false
|
||||
muc_room_default_public_jids = true
|
||||
modules_enabled = {
|
||||
"muc_hide_all";
|
||||
"muc_rate_limit";
|
||||
"polls";
|
||||
}
|
||||
|
||||
@@ -58,6 +58,8 @@ server {
|
||||
|
||||
add_header Strict-Transport-Security "max-age=63072000" always;
|
||||
set $prefix "";
|
||||
set $custom_index "";
|
||||
set $config_js_location /etc/jitsi/meet/jitsi-meet.example.com-config.js;
|
||||
|
||||
ssl_certificate /etc/jitsi/meet/jitsi-meet.example.com.crt;
|
||||
ssl_certificate_key /etc/jitsi/meet/jitsi-meet.example.com.key;
|
||||
@@ -77,8 +79,10 @@ server {
|
||||
gzip_proxied no-cache no-store private expired auth;
|
||||
gzip_min_length 512;
|
||||
|
||||
include /etc/jitsi/meet/jaas/*.conf;
|
||||
|
||||
location = /config.js {
|
||||
alias /etc/jitsi/meet/jitsi-meet.example.com-config.js;
|
||||
alias $config_js_location;
|
||||
}
|
||||
|
||||
location = /external_api.js {
|
||||
@@ -92,6 +96,11 @@ server {
|
||||
proxy_set_header Host $http_host;
|
||||
}
|
||||
|
||||
location ~ ^/_api/public/(.*)$ {
|
||||
autoindex off;
|
||||
alias /etc/jitsi/meet/public/$1;
|
||||
}
|
||||
|
||||
# ensure all static content can always be found first
|
||||
location ~ ^/(libs|css|static|images|fonts|lang|sounds|.well-known)/(.*)$
|
||||
{
|
||||
@@ -142,11 +151,12 @@ server {
|
||||
#}
|
||||
|
||||
location ~ ^/([^/?&:'"]+)$ {
|
||||
set $roomname "$1";
|
||||
try_files $uri @root_path;
|
||||
}
|
||||
|
||||
location @root_path {
|
||||
rewrite ^/(.*)$ / break;
|
||||
rewrite ^/(.*)$ /$custom_index break;
|
||||
}
|
||||
|
||||
location ~ ^/([^/?&:'"]+)/config.js$
|
||||
@@ -154,7 +164,7 @@ server {
|
||||
set $subdomain "$1.";
|
||||
set $subdir "$1/";
|
||||
|
||||
alias /etc/jitsi/meet/jitsi-meet.example.com-config.js;
|
||||
alias $config_js_location;
|
||||
}
|
||||
|
||||
# Matches /(TENANT)/pwa-worker.js or /(TENANT)/manifest.json to rewrite to / and look for file
|
||||
|
||||
7
doc/jaas/8x8.vc-config.js
Normal file
7
doc/jaas/8x8.vc-config.js
Normal file
@@ -0,0 +1,7 @@
|
||||
</script>
|
||||
<script src="https://8x8.vc/<!--# echo var="subdir" default="" -->config.js" onload="{
|
||||
config.p2p.disabledCodec='VP9';
|
||||
config.videoQuality.disabledCodec='VP9';
|
||||
config.e2ee = { externallyManagedKey: true };
|
||||
}"/>
|
||||
<script>
|
||||
22
doc/jaas/README.md
Normal file
22
doc/jaas/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
## How to switch your deployment to [JaaS](https://jaas.8x8.vc) in one easy step
|
||||
|
||||
Note: By default it will have e2ee(end-to-end) encryption enabled that works only on chromium based browsers (Chrome, Edge, ...). If a participant joins from another browser or mobile the e2ee is turned off.
|
||||
|
||||
In order to use your deployment with JaaS you first need to login to your [JaaS Developer console](https://jaas.8x8.vc/#/apikeys) and generate a key pair.
|
||||
Use `Add API key` button and then `Generate API key pair`. Make sure you download the generated private key from:
|
||||
|
||||
<img src="generated_key_dialog.png" height="250">
|
||||
|
||||
Make sure you transfer this downloaded private key to your server. Copy the key id from:
|
||||
|
||||
<img src="api_keys_kid.png" height="200">
|
||||
|
||||
Now on your server run the helper script passing the private key file and the key id:
|
||||
|
||||
```
|
||||
sudo /usr/share/jitsi-meet/scripts/move-to-jaas.sh /my/path/test-key.pk <key_id>
|
||||
```
|
||||
|
||||
More information about JaaS Api keys at: https://developer.8x8.com/jaas/docs/jaas-console-api-keys
|
||||
|
||||
If you want to adjust the enabled services you can do that in /etc/jits/meet/jaas/nginx-jaas.conf. The part after `proxy_set_body` is the jwt token content that will be used for the client tokens. More info about the JaaS tokens: https://developer.8x8.com/jaas/docs/api-keys-jwt
|
||||
BIN
doc/jaas/api_keys_kid.png
Normal file
BIN
doc/jaas/api_keys_kid.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
BIN
doc/jaas/generated_key_dialog.png
Normal file
BIN
doc/jaas/generated_key_dialog.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
33
doc/jaas/index-jaas.html
Normal file
33
doc/jaas/index-jaas.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src='external_api.js' async></script>
|
||||
<style>html, body, #jaas-container { height: 100%; }</style>
|
||||
<script type="text/javascript">
|
||||
function getRoomName(pathname) {
|
||||
const contextRootEndIndex = pathname.lastIndexOf('/');
|
||||
|
||||
return pathname.substring(contextRootEndIndex + 1);
|
||||
}
|
||||
window.onload = () => {
|
||||
const jaasJwt = <!--#include virtual="/jaas-jwt" -->;
|
||||
const api = new JitsiMeetExternalAPI(
|
||||
window.location.host, {
|
||||
roomName: `${jaasJwt.tenant}/${jaasJwt.confId}`,
|
||||
parentNode: document.querySelector('#jaas-container'),
|
||||
jwt: jaasJwt.token,
|
||||
e2eeKey: jaasJwt.e2eeKey
|
||||
});
|
||||
api.addListener('videoConferenceJoined', () => {
|
||||
if (jaasJwt.e2eeKey) {
|
||||
console.info('Toggling e2ee on!')
|
||||
api.executeCommand('toggleE2EE', true);
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="jaas-container" />
|
||||
</body>
|
||||
</html>
|
||||
59
doc/jaas/move-to-jaas.sh
Executable file
59
doc/jaas/move-to-jaas.sh
Executable file
@@ -0,0 +1,59 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
PRIVATE_KEY=$1
|
||||
JAAS_KEY_ID=$2
|
||||
|
||||
if [ ! -f "${PRIVATE_KEY}" ] ; then
|
||||
echo "You need to specify a correct path for the private key as a first argument."
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
if [[ ! "${JAAS_KEY_ID}" =~ ^vpaas-magic-cookie-[0-9a-z]+/[0-9a-z]+$ ]]; then
|
||||
echo "Invalid key id passed as a second argument."
|
||||
exit 2;
|
||||
fi
|
||||
|
||||
command -v node >/dev/null 2>&1 || { echo >&2 "You must install node first, go to https://nodejs.org. Aborting."; exit 4; }
|
||||
|
||||
NODE_VER=$(node -v);
|
||||
NODE_MAJOR_VER=$(echo ${NODE_VER:1} | cut -d. -f1);
|
||||
|
||||
if [ "$NODE_MAJOR_VER" -lt "18" ]; then
|
||||
echo "Please install latest LTS version of node (18+)";
|
||||
exit 3;
|
||||
fi
|
||||
|
||||
# we need this util for debconf-set-selections
|
||||
sudo apt install debconf-utils
|
||||
|
||||
# Let's pre-set some settings for token-generator
|
||||
cat << EOF | sudo debconf-set-selections
|
||||
token-generator token-generator/private-key string ${PRIVATE_KEY}
|
||||
token-generator token-generator/kid string ${JAAS_KEY_ID}
|
||||
EOF
|
||||
|
||||
apt install token-generator
|
||||
|
||||
mkdir -p /etc/jitsi/meet/jaas
|
||||
|
||||
VPASS_COOKIE=$(echo -n ${JAAS_KEY_ID}| cut -d/ -f1)
|
||||
cp /usr/share/jitsi-meet-web-config/nginx-jaas.conf /etc/jitsi/meet/jaas
|
||||
sed -i "s/jaas_magic_cookie/${VPASS_COOKIE}/g" /etc/jitsi/meet/jaas/nginx-jaas.conf
|
||||
|
||||
cp /usr/share/jitsi-meet-web-config/8x8.vc-config.js /etc/jitsi/meet/jaas/
|
||||
echo "set \$config_js_location /etc/jitsi/meet/jaas/8x8.vc-config.js;" >> /etc/jitsi/meet/jaas/jaas-vars
|
||||
echo "set \$custom_index index-jaas.html;" >> /etc/jitsi/meet/jaas/jaas-vars
|
||||
|
||||
ln -s /usr/share/jitsi-meet-web-config/index-jaas.html /usr/share/jitsi-meet/index-jaas.html
|
||||
|
||||
# let's create the daily key now
|
||||
/usr/share/jitsi-meet/scripts/update-asap-daily.sh
|
||||
|
||||
# let's add to cron daily the update of the asap key
|
||||
if [ -d /etc/cron.daily ]; then
|
||||
ln -s /usr/share/jitsi-meet/scripts/update-asap-daily.sh /etc/cron.daily/update-jaas-asap.sh
|
||||
else
|
||||
echo "No /etc/cron.daily. Please add to your cron jobs to execute as root daily the script: /usr/share/jitsi-meet/scripts/update-asap-daily.sh"
|
||||
fi
|
||||
23
doc/jaas/nginx-jaas.conf
Normal file
23
doc/jaas/nginx-jaas.conf
Normal file
@@ -0,0 +1,23 @@
|
||||
include /etc/jitsi/meet/jaas/jaas-vars;
|
||||
location = /jaas-jwt {
|
||||
include /etc/jitsi/token-generator/daily-key;
|
||||
ssi on;
|
||||
proxy_method POST;
|
||||
proxy_set_header content-type "application/json";
|
||||
proxy_set_header Accept-Encoding "";
|
||||
proxy_set_header Authorization "Bearer $jaas_asap_key";
|
||||
proxy_pass_request_body off;
|
||||
proxy_set_body '{"sub":"jaas_magic_cookie","context":{"features":{"livestreaming":false,"outbound-call":false,"sip-outbound-call":false,"transcription":false,"recording":false},"user":{"moderator":true}},"room": "$roomname"}';
|
||||
proxy_pass http://127.0.0.1:8017/generate/client?e2eeKey=true&confId=true;
|
||||
}
|
||||
|
||||
location @magic_root_path {
|
||||
rewrite ^/(.*)$ /index.html break;
|
||||
}
|
||||
|
||||
# Anything that didn't match above, and isn't a real file, assume it's a room name and redirect to /
|
||||
location ~ ^/jaas_magic_cookie/(.*)$ {
|
||||
set $subdomain "jaas_magic_cookie.";
|
||||
set $subdir "jaas_magic_cookie/";
|
||||
try_files $1 @magic_root_path;
|
||||
}
|
||||
9
doc/jaas/update-asap-daily.sh
Executable file
9
doc/jaas/update-asap-daily.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
JWT_KID=$(cat /etc/jitsi/token-generator/config | grep SYSTEM_ASAP_BASE_URL_MAPPINGS | cut -d= -f2- | jq -r .[].kid)
|
||||
JWT_DATE=$(echo -n $JWT_KID | cut -d/ -f2-)
|
||||
JWT_DATE=${JWT_DATE#jwt-}
|
||||
KEY_FILE=/etc/jitsi/token-generator/daily-key
|
||||
echo -n "set \$jaas_asap_key " > ${KEY_FILE}
|
||||
ASAP_KEY=$(ASAP_SIGNING_KEY_FILE=/etc/jitsi/token-generator/asap-${JWT_DATE}.key ASAP_JWT_KID="${JWT_KID}" ASAP_EXPIRES_IN="1 day" node /usr/share/token-generator/jwt.js| tail -n1)
|
||||
echo -n "${ASAP_KEY};" >> ${KEY_FILE}
|
||||
|
||||
service nginx reload
|
||||
7
globals.d.ts
vendored
7
globals.d.ts
vendored
@@ -10,12 +10,6 @@ declare global {
|
||||
API: any;
|
||||
conference: any;
|
||||
debugLogs: any;
|
||||
keyboardshortcut: {
|
||||
registerShortcut: Function;
|
||||
unregisterShortcut: Function;
|
||||
openDialog: Function;
|
||||
enable: Function;
|
||||
}
|
||||
};
|
||||
const interfaceConfig: any;
|
||||
|
||||
@@ -27,6 +21,7 @@ declare global {
|
||||
JitsiMeetElectron?: any;
|
||||
// selenium tests handler
|
||||
_sharedVideoPlayer: any;
|
||||
alwaysOnTop: { api: any };
|
||||
}
|
||||
|
||||
interface Document {
|
||||
|
||||
1
globals.native.d.ts
vendored
1
globals.native.d.ts
vendored
@@ -30,6 +30,7 @@ interface IWindow {
|
||||
setImmediate: typeof setImmediate;
|
||||
clearImmediate: typeof clearImmediate;
|
||||
addEventListener: Function;
|
||||
removeEventListener: Function;
|
||||
}
|
||||
|
||||
interface INavigator {
|
||||
|
||||
12
ios/Podfile
12
ios/Podfile
@@ -1,11 +1,13 @@
|
||||
require_relative '../node_modules/react-native/scripts/react_native_pods'
|
||||
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
|
||||
|
||||
platform :ios, '12.0'
|
||||
platform :ios, '12.4'
|
||||
workspace 'jitsi-meet'
|
||||
|
||||
install! 'cocoapods', :deterministic_uuids => false
|
||||
|
||||
production = ENV["PRODUCTION"] == "1"
|
||||
|
||||
target 'JitsiMeet' do
|
||||
project 'app/app.xcodeproj'
|
||||
|
||||
@@ -21,8 +23,10 @@ target 'JitsiMeetSDK' do
|
||||
#
|
||||
|
||||
config = use_native_modules!
|
||||
flags = get_default_flags()
|
||||
use_react_native!(
|
||||
:path => config["reactNativePath"],
|
||||
:path => config[:reactNativePath],
|
||||
:production => production,
|
||||
:hermes_enabled => false,
|
||||
:fabric_enabled => false,
|
||||
# An absolute path to your application root.
|
||||
@@ -42,7 +46,7 @@ target 'JitsiMeetSDK' do
|
||||
|
||||
pod 'CocoaLumberjack', '3.7.2'
|
||||
pod 'ObjectiveDropboxOfficial', '6.2.3'
|
||||
pod 'JitsiWebRTC', '~> 106.0.0'
|
||||
pod 'JitsiWebRTC', '~> 111.0.0'
|
||||
end
|
||||
|
||||
target 'JitsiMeetSDKLite' do
|
||||
@@ -81,7 +85,7 @@ post_install do |installer|
|
||||
end
|
||||
target.build_configurations.each do |config|
|
||||
config.build_settings['SUPPORTS_MACCATALYST'] = 'NO'
|
||||
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'
|
||||
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.4'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
553
ios/Podfile.lock
553
ios/Podfile.lock
@@ -3,24 +3,25 @@ PODS:
|
||||
- amplitude-react-native (2.7.0):
|
||||
- Amplitude (= 8.7.1)
|
||||
- React-Core
|
||||
- AppAuth (1.4.0):
|
||||
- AppAuth/Core (= 1.4.0)
|
||||
- AppAuth/ExternalUserAgent (= 1.4.0)
|
||||
- AppAuth/Core (1.4.0)
|
||||
- AppAuth/ExternalUserAgent (1.4.0)
|
||||
- AppAuth (1.6.1):
|
||||
- AppAuth/Core (= 1.6.1)
|
||||
- AppAuth/ExternalUserAgent (= 1.6.1)
|
||||
- AppAuth/Core (1.6.1)
|
||||
- AppAuth/ExternalUserAgent (1.6.1):
|
||||
- AppAuth/Core
|
||||
- boost (1.76.0)
|
||||
- CocoaLumberjack (3.7.2):
|
||||
- CocoaLumberjack/Core (= 3.7.2)
|
||||
- CocoaLumberjack/Core (3.7.2)
|
||||
- DoubleConversion (1.1.6)
|
||||
- FBLazyVector (0.68.6)
|
||||
- FBReactNativeSpec (0.68.6):
|
||||
- FBLazyVector (0.69.10)
|
||||
- FBReactNativeSpec (0.69.10):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTRequired (= 0.68.6)
|
||||
- RCTTypeSafety (= 0.68.6)
|
||||
- React-Core (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- ReactCommon/turbomodule/core (= 0.68.6)
|
||||
- RCTRequired (= 0.69.10)
|
||||
- RCTTypeSafety (= 0.69.10)
|
||||
- React-Core (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- ReactCommon/turbomodule/core (= 0.69.10)
|
||||
- Firebase/Analytics (8.15.0):
|
||||
- Firebase/Core
|
||||
- Firebase/Core (8.15.0):
|
||||
@@ -102,56 +103,56 @@ PODS:
|
||||
- GoogleUtilities/Network (~> 7.7)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.7)"
|
||||
- nanopb (~> 2.30908.0)
|
||||
- GoogleDataTransport (9.1.4):
|
||||
- GoogleDataTransport (9.2.2):
|
||||
- GoogleUtilities/Environment (~> 7.7)
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- PromisesObjC (< 3.0, >= 1.2)
|
||||
- GoogleSignIn (6.0.2):
|
||||
- AppAuth (~> 1.4)
|
||||
- GTMAppAuth (~> 1.0)
|
||||
- GTMSessionFetcher/Core (~> 1.1)
|
||||
- GoogleUtilities/AppDelegateSwizzler (7.7.0):
|
||||
- GoogleSignIn (6.2.4):
|
||||
- AppAuth (~> 1.5)
|
||||
- GTMAppAuth (~> 1.3)
|
||||
- GTMSessionFetcher/Core (< 3.0, >= 1.1)
|
||||
- GoogleUtilities/AppDelegateSwizzler (7.11.1):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Network
|
||||
- GoogleUtilities/Environment (7.7.0):
|
||||
- GoogleUtilities/Environment (7.11.1):
|
||||
- PromisesObjC (< 3.0, >= 1.2)
|
||||
- GoogleUtilities/Logger (7.7.0):
|
||||
- GoogleUtilities/Logger (7.11.1):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/MethodSwizzler (7.7.0):
|
||||
- GoogleUtilities/MethodSwizzler (7.11.1):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Network (7.7.0):
|
||||
- GoogleUtilities/Network (7.11.1):
|
||||
- GoogleUtilities/Logger
|
||||
- "GoogleUtilities/NSData+zlib"
|
||||
- GoogleUtilities/Reachability
|
||||
- "GoogleUtilities/NSData+zlib (7.7.0)"
|
||||
- GoogleUtilities/Reachability (7.7.0):
|
||||
- "GoogleUtilities/NSData+zlib (7.11.1)"
|
||||
- GoogleUtilities/Reachability (7.11.1):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/UserDefaults (7.7.0):
|
||||
- GoogleUtilities/UserDefaults (7.11.1):
|
||||
- GoogleUtilities/Logger
|
||||
- GTMAppAuth (1.2.2):
|
||||
- AppAuth/Core (~> 1.4)
|
||||
- GTMSessionFetcher/Core (~> 1.5)
|
||||
- GTMSessionFetcher/Core (1.7.0)
|
||||
- JitsiWebRTC (106.0.0)
|
||||
- libwebp (1.2.1):
|
||||
- libwebp/demux (= 1.2.1)
|
||||
- libwebp/mux (= 1.2.1)
|
||||
- libwebp/webp (= 1.2.1)
|
||||
- libwebp/demux (1.2.1):
|
||||
- GTMAppAuth (1.3.1):
|
||||
- AppAuth/Core (~> 1.6)
|
||||
- GTMSessionFetcher/Core (< 3.0, >= 1.5)
|
||||
- GTMSessionFetcher/Core (2.3.0)
|
||||
- JitsiWebRTC (111.0.2)
|
||||
- libwebp (1.2.4):
|
||||
- libwebp/demux (= 1.2.4)
|
||||
- libwebp/mux (= 1.2.4)
|
||||
- libwebp/webp (= 1.2.4)
|
||||
- libwebp/demux (1.2.4):
|
||||
- libwebp/webp
|
||||
- libwebp/mux (1.2.1):
|
||||
- libwebp/mux (1.2.4):
|
||||
- libwebp/demux
|
||||
- libwebp/webp (1.2.1)
|
||||
- libwebp/webp (1.2.4)
|
||||
- nanopb (2.30908.0):
|
||||
- nanopb/decode (= 2.30908.0)
|
||||
- nanopb/encode (= 2.30908.0)
|
||||
- nanopb/decode (2.30908.0)
|
||||
- nanopb/encode (2.30908.0)
|
||||
- ObjectiveDropboxOfficial (6.2.3)
|
||||
- PromisesObjC (2.1.1)
|
||||
- PromisesSwift (2.1.1):
|
||||
- PromisesObjC (= 2.1.1)
|
||||
- PromisesObjC (2.2.0)
|
||||
- PromisesSwift (2.2.0):
|
||||
- PromisesObjC (= 2.2.0)
|
||||
- RCT-Folly (2021.06.28.00-v2):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
@@ -163,201 +164,203 @@ PODS:
|
||||
- DoubleConversion
|
||||
- fmt (~> 6.2.1)
|
||||
- glog
|
||||
- RCTRequired (0.68.6)
|
||||
- RCTTypeSafety (0.68.6):
|
||||
- FBLazyVector (= 0.68.6)
|
||||
- RCTRequired (0.69.10)
|
||||
- RCTTypeSafety (0.69.10):
|
||||
- FBLazyVector (= 0.69.10)
|
||||
- RCTRequired (= 0.69.10)
|
||||
- React-Core (= 0.69.10)
|
||||
- React (0.69.10):
|
||||
- React-Core (= 0.69.10)
|
||||
- React-Core/DevSupport (= 0.69.10)
|
||||
- React-Core/RCTWebSocket (= 0.69.10)
|
||||
- React-RCTActionSheet (= 0.69.10)
|
||||
- React-RCTAnimation (= 0.69.10)
|
||||
- React-RCTBlob (= 0.69.10)
|
||||
- React-RCTImage (= 0.69.10)
|
||||
- React-RCTLinking (= 0.69.10)
|
||||
- React-RCTNetwork (= 0.69.10)
|
||||
- React-RCTSettings (= 0.69.10)
|
||||
- React-RCTText (= 0.69.10)
|
||||
- React-RCTVibration (= 0.69.10)
|
||||
- React-bridging (0.69.10):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTRequired (= 0.68.6)
|
||||
- React-Core (= 0.68.6)
|
||||
- React (0.68.6):
|
||||
- React-Core (= 0.68.6)
|
||||
- React-Core/DevSupport (= 0.68.6)
|
||||
- React-Core/RCTWebSocket (= 0.68.6)
|
||||
- React-RCTActionSheet (= 0.68.6)
|
||||
- React-RCTAnimation (= 0.68.6)
|
||||
- React-RCTBlob (= 0.68.6)
|
||||
- React-RCTImage (= 0.68.6)
|
||||
- React-RCTLinking (= 0.68.6)
|
||||
- React-RCTNetwork (= 0.68.6)
|
||||
- React-RCTSettings (= 0.68.6)
|
||||
- React-RCTText (= 0.68.6)
|
||||
- React-RCTVibration (= 0.68.6)
|
||||
- React-callinvoker (0.68.6)
|
||||
- React-Codegen (0.68.6):
|
||||
- FBReactNativeSpec (= 0.68.6)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-callinvoker (0.69.10)
|
||||
- React-Codegen (0.69.10):
|
||||
- FBReactNativeSpec (= 0.69.10)
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTRequired (= 0.68.6)
|
||||
- RCTTypeSafety (= 0.68.6)
|
||||
- React-Core (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-jsiexecutor (= 0.68.6)
|
||||
- ReactCommon/turbomodule/core (= 0.68.6)
|
||||
- React-Core (0.68.6):
|
||||
- RCTRequired (= 0.69.10)
|
||||
- RCTTypeSafety (= 0.69.10)
|
||||
- React-Core (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-jsiexecutor (= 0.69.10)
|
||||
- ReactCommon/turbomodule/core (= 0.69.10)
|
||||
- React-Core (0.69.10):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default (= 0.68.6)
|
||||
- React-cxxreact (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-jsiexecutor (= 0.68.6)
|
||||
- React-perflogger (= 0.68.6)
|
||||
- React-Core/Default (= 0.69.10)
|
||||
- React-cxxreact (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-jsiexecutor (= 0.69.10)
|
||||
- React-perflogger (= 0.69.10)
|
||||
- Yoga
|
||||
- React-Core/CoreModulesHeaders (0.68.6):
|
||||
- React-Core/CoreModulesHeaders (0.69.10):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-jsiexecutor (= 0.68.6)
|
||||
- React-perflogger (= 0.68.6)
|
||||
- React-cxxreact (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-jsiexecutor (= 0.69.10)
|
||||
- React-perflogger (= 0.69.10)
|
||||
- Yoga
|
||||
- React-Core/Default (0.68.6):
|
||||
- React-Core/Default (0.69.10):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-cxxreact (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-jsiexecutor (= 0.68.6)
|
||||
- React-perflogger (= 0.68.6)
|
||||
- React-cxxreact (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-jsiexecutor (= 0.69.10)
|
||||
- React-perflogger (= 0.69.10)
|
||||
- Yoga
|
||||
- React-Core/DevSupport (0.68.6):
|
||||
- React-Core/DevSupport (0.69.10):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default (= 0.68.6)
|
||||
- React-Core/RCTWebSocket (= 0.68.6)
|
||||
- React-cxxreact (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-jsiexecutor (= 0.68.6)
|
||||
- React-jsinspector (= 0.68.6)
|
||||
- React-perflogger (= 0.68.6)
|
||||
- React-Core/Default (= 0.69.10)
|
||||
- React-Core/RCTWebSocket (= 0.69.10)
|
||||
- React-cxxreact (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-jsiexecutor (= 0.69.10)
|
||||
- React-jsinspector (= 0.69.10)
|
||||
- React-perflogger (= 0.69.10)
|
||||
- Yoga
|
||||
- React-Core/RCTActionSheetHeaders (0.68.6):
|
||||
- React-Core/RCTActionSheetHeaders (0.69.10):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-jsiexecutor (= 0.68.6)
|
||||
- React-perflogger (= 0.68.6)
|
||||
- React-cxxreact (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-jsiexecutor (= 0.69.10)
|
||||
- React-perflogger (= 0.69.10)
|
||||
- Yoga
|
||||
- React-Core/RCTAnimationHeaders (0.68.6):
|
||||
- React-Core/RCTAnimationHeaders (0.69.10):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-jsiexecutor (= 0.68.6)
|
||||
- React-perflogger (= 0.68.6)
|
||||
- React-cxxreact (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-jsiexecutor (= 0.69.10)
|
||||
- React-perflogger (= 0.69.10)
|
||||
- Yoga
|
||||
- React-Core/RCTBlobHeaders (0.68.6):
|
||||
- React-Core/RCTBlobHeaders (0.69.10):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-jsiexecutor (= 0.68.6)
|
||||
- React-perflogger (= 0.68.6)
|
||||
- React-cxxreact (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-jsiexecutor (= 0.69.10)
|
||||
- React-perflogger (= 0.69.10)
|
||||
- Yoga
|
||||
- React-Core/RCTImageHeaders (0.68.6):
|
||||
- React-Core/RCTImageHeaders (0.69.10):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-jsiexecutor (= 0.68.6)
|
||||
- React-perflogger (= 0.68.6)
|
||||
- React-cxxreact (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-jsiexecutor (= 0.69.10)
|
||||
- React-perflogger (= 0.69.10)
|
||||
- Yoga
|
||||
- React-Core/RCTLinkingHeaders (0.68.6):
|
||||
- React-Core/RCTLinkingHeaders (0.69.10):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-jsiexecutor (= 0.68.6)
|
||||
- React-perflogger (= 0.68.6)
|
||||
- React-cxxreact (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-jsiexecutor (= 0.69.10)
|
||||
- React-perflogger (= 0.69.10)
|
||||
- Yoga
|
||||
- React-Core/RCTNetworkHeaders (0.68.6):
|
||||
- React-Core/RCTNetworkHeaders (0.69.10):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-jsiexecutor (= 0.68.6)
|
||||
- React-perflogger (= 0.68.6)
|
||||
- React-cxxreact (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-jsiexecutor (= 0.69.10)
|
||||
- React-perflogger (= 0.69.10)
|
||||
- Yoga
|
||||
- React-Core/RCTSettingsHeaders (0.68.6):
|
||||
- React-Core/RCTSettingsHeaders (0.69.10):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-jsiexecutor (= 0.68.6)
|
||||
- React-perflogger (= 0.68.6)
|
||||
- React-cxxreact (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-jsiexecutor (= 0.69.10)
|
||||
- React-perflogger (= 0.69.10)
|
||||
- Yoga
|
||||
- React-Core/RCTTextHeaders (0.68.6):
|
||||
- React-Core/RCTTextHeaders (0.69.10):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-jsiexecutor (= 0.68.6)
|
||||
- React-perflogger (= 0.68.6)
|
||||
- React-cxxreact (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-jsiexecutor (= 0.69.10)
|
||||
- React-perflogger (= 0.69.10)
|
||||
- Yoga
|
||||
- React-Core/RCTVibrationHeaders (0.68.6):
|
||||
- React-Core/RCTVibrationHeaders (0.69.10):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-jsiexecutor (= 0.68.6)
|
||||
- React-perflogger (= 0.68.6)
|
||||
- React-cxxreact (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-jsiexecutor (= 0.69.10)
|
||||
- React-perflogger (= 0.69.10)
|
||||
- Yoga
|
||||
- React-Core/RCTWebSocket (0.68.6):
|
||||
- React-Core/RCTWebSocket (0.69.10):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default (= 0.68.6)
|
||||
- React-cxxreact (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-jsiexecutor (= 0.68.6)
|
||||
- React-perflogger (= 0.68.6)
|
||||
- React-Core/Default (= 0.69.10)
|
||||
- React-cxxreact (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-jsiexecutor (= 0.69.10)
|
||||
- React-perflogger (= 0.69.10)
|
||||
- Yoga
|
||||
- React-CoreModules (0.68.6):
|
||||
- React-CoreModules (0.69.10):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.68.6)
|
||||
- React-Codegen (= 0.68.6)
|
||||
- React-Core/CoreModulesHeaders (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-RCTImage (= 0.68.6)
|
||||
- ReactCommon/turbomodule/core (= 0.68.6)
|
||||
- React-cxxreact (0.68.6):
|
||||
- RCTTypeSafety (= 0.69.10)
|
||||
- React-Codegen (= 0.69.10)
|
||||
- React-Core/CoreModulesHeaders (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-RCTImage (= 0.69.10)
|
||||
- ReactCommon/turbomodule/core (= 0.69.10)
|
||||
- React-cxxreact (0.69.10):
|
||||
- boost (= 1.76.0)
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-callinvoker (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-jsinspector (= 0.68.6)
|
||||
- React-logger (= 0.68.6)
|
||||
- React-perflogger (= 0.68.6)
|
||||
- React-runtimeexecutor (= 0.68.6)
|
||||
- React-jsi (0.68.6):
|
||||
- React-callinvoker (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-jsinspector (= 0.69.10)
|
||||
- React-logger (= 0.69.10)
|
||||
- React-perflogger (= 0.69.10)
|
||||
- React-runtimeexecutor (= 0.69.10)
|
||||
- React-jsi (0.69.10):
|
||||
- boost (= 1.76.0)
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-jsi/Default (= 0.68.6)
|
||||
- React-jsi/Default (0.68.6):
|
||||
- React-jsi/Default (= 0.69.10)
|
||||
- React-jsi/Default (0.69.10):
|
||||
- boost (= 1.76.0)
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-jsiexecutor (0.68.6):
|
||||
- React-jsiexecutor (0.69.10):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-cxxreact (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-perflogger (= 0.68.6)
|
||||
- React-jsinspector (0.68.6)
|
||||
- React-logger (0.68.6):
|
||||
- React-cxxreact (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-perflogger (= 0.69.10)
|
||||
- React-jsinspector (0.69.10)
|
||||
- React-logger (0.69.10):
|
||||
- glog
|
||||
- react-native-background-timer (2.4.1):
|
||||
- React-Core
|
||||
@@ -371,8 +374,6 @@ PODS:
|
||||
- React-Core
|
||||
- react-native-pager-view (5.4.9):
|
||||
- React-Core
|
||||
- react-native-performance (2.1.0):
|
||||
- React-Core
|
||||
- react-native-safe-area-context (4.4.1):
|
||||
- RCT-Folly
|
||||
- RCTRequired
|
||||
@@ -389,76 +390,77 @@ PODS:
|
||||
- react-native-video/Video (6.0.0-alpha.1):
|
||||
- PromisesSwift
|
||||
- React-Core
|
||||
- react-native-webrtc (106.0.7):
|
||||
- JitsiWebRTC (~> 106.0.0)
|
||||
- react-native-webrtc (111.0.1):
|
||||
- JitsiWebRTC (~> 111.0.0)
|
||||
- React-Core
|
||||
- react-native-webview (11.15.1):
|
||||
- React-Core
|
||||
- React-perflogger (0.68.6)
|
||||
- React-RCTActionSheet (0.68.6):
|
||||
- React-Core/RCTActionSheetHeaders (= 0.68.6)
|
||||
- React-RCTAnimation (0.68.6):
|
||||
- React-perflogger (0.69.10)
|
||||
- React-RCTActionSheet (0.69.10):
|
||||
- React-Core/RCTActionSheetHeaders (= 0.69.10)
|
||||
- React-RCTAnimation (0.69.10):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.68.6)
|
||||
- React-Codegen (= 0.68.6)
|
||||
- React-Core/RCTAnimationHeaders (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- ReactCommon/turbomodule/core (= 0.68.6)
|
||||
- React-RCTBlob (0.68.6):
|
||||
- RCTTypeSafety (= 0.69.10)
|
||||
- React-Codegen (= 0.69.10)
|
||||
- React-Core/RCTAnimationHeaders (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- ReactCommon/turbomodule/core (= 0.69.10)
|
||||
- React-RCTBlob (0.69.10):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Codegen (= 0.68.6)
|
||||
- React-Core/RCTBlobHeaders (= 0.68.6)
|
||||
- React-Core/RCTWebSocket (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-RCTNetwork (= 0.68.6)
|
||||
- ReactCommon/turbomodule/core (= 0.68.6)
|
||||
- React-RCTImage (0.68.6):
|
||||
- React-Codegen (= 0.69.10)
|
||||
- React-Core/RCTBlobHeaders (= 0.69.10)
|
||||
- React-Core/RCTWebSocket (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-RCTNetwork (= 0.69.10)
|
||||
- ReactCommon/turbomodule/core (= 0.69.10)
|
||||
- React-RCTImage (0.69.10):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.68.6)
|
||||
- React-Codegen (= 0.68.6)
|
||||
- React-Core/RCTImageHeaders (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-RCTNetwork (= 0.68.6)
|
||||
- ReactCommon/turbomodule/core (= 0.68.6)
|
||||
- React-RCTLinking (0.68.6):
|
||||
- React-Codegen (= 0.68.6)
|
||||
- React-Core/RCTLinkingHeaders (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- ReactCommon/turbomodule/core (= 0.68.6)
|
||||
- React-RCTNetwork (0.68.6):
|
||||
- RCTTypeSafety (= 0.69.10)
|
||||
- React-Codegen (= 0.69.10)
|
||||
- React-Core/RCTImageHeaders (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-RCTNetwork (= 0.69.10)
|
||||
- ReactCommon/turbomodule/core (= 0.69.10)
|
||||
- React-RCTLinking (0.69.10):
|
||||
- React-Codegen (= 0.69.10)
|
||||
- React-Core/RCTLinkingHeaders (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- ReactCommon/turbomodule/core (= 0.69.10)
|
||||
- React-RCTNetwork (0.69.10):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.68.6)
|
||||
- React-Codegen (= 0.68.6)
|
||||
- React-Core/RCTNetworkHeaders (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- ReactCommon/turbomodule/core (= 0.68.6)
|
||||
- React-RCTSettings (0.68.6):
|
||||
- RCTTypeSafety (= 0.69.10)
|
||||
- React-Codegen (= 0.69.10)
|
||||
- React-Core/RCTNetworkHeaders (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- ReactCommon/turbomodule/core (= 0.69.10)
|
||||
- React-RCTSettings (0.69.10):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.68.6)
|
||||
- React-Codegen (= 0.68.6)
|
||||
- React-Core/RCTSettingsHeaders (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- ReactCommon/turbomodule/core (= 0.68.6)
|
||||
- React-RCTText (0.68.6):
|
||||
- React-Core/RCTTextHeaders (= 0.68.6)
|
||||
- React-RCTVibration (0.68.6):
|
||||
- RCTTypeSafety (= 0.69.10)
|
||||
- React-Codegen (= 0.69.10)
|
||||
- React-Core/RCTSettingsHeaders (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- ReactCommon/turbomodule/core (= 0.69.10)
|
||||
- React-RCTText (0.69.10):
|
||||
- React-Core/RCTTextHeaders (= 0.69.10)
|
||||
- React-RCTVibration (0.69.10):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Codegen (= 0.68.6)
|
||||
- React-Core/RCTVibrationHeaders (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- ReactCommon/turbomodule/core (= 0.68.6)
|
||||
- React-runtimeexecutor (0.68.6):
|
||||
- React-jsi (= 0.68.6)
|
||||
- ReactCommon/turbomodule/core (0.68.6):
|
||||
- React-Codegen (= 0.69.10)
|
||||
- React-Core/RCTVibrationHeaders (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- ReactCommon/turbomodule/core (= 0.69.10)
|
||||
- React-runtimeexecutor (0.69.10):
|
||||
- React-jsi (= 0.69.10)
|
||||
- ReactCommon/turbomodule/core (0.69.10):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-callinvoker (= 0.68.6)
|
||||
- React-Core (= 0.68.6)
|
||||
- React-cxxreact (= 0.68.6)
|
||||
- React-jsi (= 0.68.6)
|
||||
- React-logger (= 0.68.6)
|
||||
- React-perflogger (= 0.68.6)
|
||||
- React-bridging (= 0.69.10)
|
||||
- React-callinvoker (= 0.69.10)
|
||||
- React-Core (= 0.69.10)
|
||||
- React-cxxreact (= 0.69.10)
|
||||
- React-jsi (= 0.69.10)
|
||||
- React-logger (= 0.69.10)
|
||||
- React-perflogger (= 0.69.10)
|
||||
- RNCalendarEvents (2.2.0):
|
||||
- React
|
||||
- RNCAsyncStorage (1.17.3):
|
||||
@@ -471,8 +473,8 @@ PODS:
|
||||
- React-Core
|
||||
- RNGestureHandler (2.9.0):
|
||||
- React-Core
|
||||
- RNGoogleSignin (7.0.4):
|
||||
- GoogleSignIn (~> 6.0.0)
|
||||
- RNGoogleSignin (9.0.2):
|
||||
- GoogleSignIn (~> 6.2)
|
||||
- React-Core
|
||||
- RNScreens (3.13.1):
|
||||
- React-Core
|
||||
@@ -500,16 +502,16 @@ DEPENDENCIES:
|
||||
- Firebase/DynamicLinks (~> 8.0)
|
||||
- "giphy-react-native-sdk (from `../node_modules/@giphy/react-native-sdk`)"
|
||||
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
|
||||
- JitsiWebRTC (~> 106.0.0)
|
||||
- JitsiWebRTC (~> 111.0.0)
|
||||
- ObjectiveDropboxOfficial (= 6.2.3)
|
||||
- RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
|
||||
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
|
||||
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
|
||||
- React (from `../node_modules/react-native/`)
|
||||
- React-bridging (from `../node_modules/react-native/ReactCommon`)
|
||||
- React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`)
|
||||
- React-Codegen (from `build/generated/ios`)
|
||||
- React-Core (from `../node_modules/react-native/`)
|
||||
- React-Core/DevSupport (from `../node_modules/react-native/`)
|
||||
- React-Core/RCTWebSocket (from `../node_modules/react-native/`)
|
||||
- React-CoreModules (from `../node_modules/react-native/React/CoreModules`)
|
||||
- React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`)
|
||||
@@ -523,7 +525,6 @@ DEPENDENCIES:
|
||||
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
|
||||
- react-native-orientation-locker (from `../node_modules/react-native-orientation-locker`)
|
||||
- react-native-pager-view (from `../node_modules/react-native-pager-view`)
|
||||
- react-native-performance (from `../node_modules/react-native-performance/ios`)
|
||||
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
|
||||
- "react-native-slider (from `../node_modules/@react-native-community/slider`)"
|
||||
- react-native-splash-screen (from `../node_modules/react-native-splash-screen`)
|
||||
@@ -605,6 +606,8 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/Libraries/TypeSafety"
|
||||
React:
|
||||
:path: "../node_modules/react-native/"
|
||||
React-bridging:
|
||||
:path: "../node_modules/react-native/ReactCommon"
|
||||
React-callinvoker:
|
||||
:path: "../node_modules/react-native/ReactCommon/callinvoker"
|
||||
React-Codegen:
|
||||
@@ -635,8 +638,6 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native-orientation-locker"
|
||||
react-native-pager-view:
|
||||
:path: "../node_modules/react-native-pager-view"
|
||||
react-native-performance:
|
||||
:path: "../node_modules/react-native-performance/ios"
|
||||
react-native-safe-area-context:
|
||||
:path: "../node_modules/react-native-safe-area-context"
|
||||
react-native-slider:
|
||||
@@ -701,12 +702,12 @@ EXTERNAL SOURCES:
|
||||
SPEC CHECKSUMS:
|
||||
Amplitude: 834c7332dfb9640a751e21c13efb22a07c0c12d4
|
||||
amplitude-react-native: 0ed8cab759aafaa94961b82122bf56297da607ad
|
||||
AppAuth: 31bcec809a638d7bd2f86ea8a52bd45f6e81e7c7
|
||||
AppAuth: e48b432bb4ba88b10cb2bcc50d7f3af21e78b9c2
|
||||
boost: a7c83b31436843459a1961bfd74b96033dc77234
|
||||
CocoaLumberjack: b7e05132ff94f6ae4dfa9d5bce9141893a21d9da
|
||||
DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662
|
||||
FBLazyVector: 74b042924fe14da854ac4e87cefc417f583b22b1
|
||||
FBReactNativeSpec: cc0037b9914b9b1d92a15f179bc3e2e2c7cc0c6f
|
||||
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
|
||||
FBLazyVector: a8af91c2b5a0029d12ff6b32e428863d63c48991
|
||||
FBReactNativeSpec: ec5e878f6452a3de5430e0b2324a4d4ae6ac63f6
|
||||
Firebase: 5f8193dff4b5b7c5d5ef72ae54bb76c08e2b841d
|
||||
FirebaseAnalytics: 7761cbadb00a717d8d0939363eb46041526474fa
|
||||
FirebaseCore: 5743c5785c074a794d35f2fff7ecc254a91e08b1
|
||||
@@ -717,70 +718,70 @@ SPEC CHECKSUMS:
|
||||
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
|
||||
Giphy: b6d5087521d251bb8c99cdc0eb07bbdf86d142d5
|
||||
giphy-react-native-sdk: 7abccf2b52123a0f30ce99da895ab6288023680c
|
||||
glog: 476ee3e89abb49e07f822b48323c51c57124b572
|
||||
glog: 3d02b25ca00c2d456734d0bcff864cbc62f6ae1a
|
||||
GoogleAppMeasurement: 4c19f031220c72464d460c9daa1fb5d1acce958e
|
||||
GoogleDataTransport: 5fffe35792f8b96ec8d6775f5eccd83c998d5a3b
|
||||
GoogleSignIn: fd381840dbe7c1137aa6dc30849a5c3e070c034a
|
||||
GoogleUtilities: e0913149f6b0625b553d70dae12b49fc62914fd1
|
||||
GTMAppAuth: ad5c2b70b9a8689e1a04033c9369c4915bfcbe89
|
||||
GTMSessionFetcher: 43748f93435c2aa068b1cbe39655aaf600652e91
|
||||
JitsiWebRTC: f441eb0e2d67f0588bf24e21c5162e97342714fb
|
||||
libwebp: 98a37e597e40bfdb4c911fc98f2c53d0b12d05fc
|
||||
GoogleDataTransport: 8378d1fa8ac49753ea6ce70d65a7cb70ce5f66e6
|
||||
GoogleSignIn: 5651ce3a61e56ca864160e79b484cd9ed3f49b7a
|
||||
GoogleUtilities: 9aa0ad5a7bc171f8bae016300bfcfa3fb8425749
|
||||
GTMAppAuth: 0ff230db599948a9ad7470ca667337803b3fc4dd
|
||||
GTMSessionFetcher: 3a63d75eecd6aa32c2fc79f578064e1214dfdec2
|
||||
JitsiWebRTC: 80f62908fcf2a1160e0d14b584323fb6e6be630b
|
||||
libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef
|
||||
nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
|
||||
ObjectiveDropboxOfficial: fe206ce8c0bc49976c249d472db7fdbc53ebbd53
|
||||
PromisesObjC: ab77feca74fa2823e7af4249b8326368e61014cb
|
||||
PromisesSwift: 99fddfe4a0ec88a56486644c0da106694c92a604
|
||||
RCT-Folly: 4d8508a426467c48885f1151029bc15fa5d7b3b8
|
||||
RCTRequired: 92cbd71369a2de6add25fd2403ac39838f1b694f
|
||||
RCTTypeSafety: 494e8af41d7410ed0b877210859ee3984f37e6b4
|
||||
React: 59989499c0e8926a90d34a9ae0bdb2d1b5b53406
|
||||
React-callinvoker: 8187db1c71cf2c1c66e8f7328a0cf77a2b255d94
|
||||
React-Codegen: e806dc2f10ddae645d855cb58acf73ce41eb8ea5
|
||||
React-Core: fc7339b493e368ae079850a4721bdf716cf3dba2
|
||||
React-CoreModules: 2f54f6bbf2764044379332089fcbdaf79197021e
|
||||
React-cxxreact: ee119270006794976e1ab271f0111a5a88b16bcf
|
||||
React-jsi: ec691b2a475d13b1fd39f697145a526eeeb6661c
|
||||
React-jsiexecutor: b4ce4afc5dd9c8fdd2ac59049ccf420f288ecef7
|
||||
React-jsinspector: e396d5e56af08fce39f50571726b68a40f1e302d
|
||||
React-logger: cec52b3f8fb0be0d47b2cb75dec69de60f2de3b6
|
||||
PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef
|
||||
PromisesSwift: cf9eb58666a43bbe007302226e510b16c1e10959
|
||||
RCT-Folly: b9d9fe1fc70114b751c076104e52f3b1b5e5a95a
|
||||
RCTRequired: 3581db0757e7ff9be10718a56b3d79b6a6bd3bdf
|
||||
RCTTypeSafety: ce13e630c48340401ebfb28710959913f74b8b36
|
||||
React: cca8f2b7cce018f79847ca79847fa367b206e8a1
|
||||
React-bridging: b893643f09d3964afba6c347e00dd86cf10691e5
|
||||
React-callinvoker: 9ac7cba30428eddf7a06d1253f8e7561b5c97334
|
||||
React-Codegen: 65ff9fbddf8a17a6d4f495f71d365288f934a93a
|
||||
React-Core: 550b694774bc778b5c7bf7608fc12a484e01ec05
|
||||
React-CoreModules: c332d5b416cb3ccf972e7af79d496498a700e073
|
||||
React-cxxreact: c5c4106bfd2d0cee80b848e33b7ff4e35a721b16
|
||||
React-jsi: 6ff3fb9b9764a499c959e0096c0d384fa2b4beef
|
||||
React-jsiexecutor: 388f1c99404c848141d7ea162f61233d04829ede
|
||||
React-jsinspector: a4463b3411b8b9b37153255ef694a84c77ba3c7f
|
||||
React-logger: 2a0497622cbabc47fb769d97620952df14c1f814
|
||||
react-native-background-timer: 17ea5e06803401a379ebf1f20505b793ac44d0fe
|
||||
react-native-get-random-values: 30b3f74ca34e30e2e480de48e4add2706a40ac8f
|
||||
react-native-keep-awake: afad8a51dfef9fe9655a6344771be32c8596d774
|
||||
react-native-netinfo: 27f287f2d191693f3b9d01a4273137fcf91c3b5d
|
||||
react-native-orientation-locker: 851f6510d8046ea2f14aa169b1e01fcd309a94ba
|
||||
react-native-pager-view: 3ee7d4c7697fb3ef788346e834a60cca97ed8540
|
||||
react-native-performance: f4b6604a9d5a8a7407e34a82fab6c641d9a3ec12
|
||||
react-native-safe-area-context: 99b24a0c5acd0d5dcac2b1a7f18c49ea317be99a
|
||||
react-native-slider: 6e9b86e76cce4b9e35b3403193a6432ed07e0c81
|
||||
react-native-splash-screen: 4312f786b13a81b5169ef346d76d33bc0c6dc457
|
||||
react-native-video: bb6f12a7198db53b261fefb5d609dc77417acc8b
|
||||
react-native-webrtc: 0df36747802476e758af6b6dceccdeaed8c826c2
|
||||
react-native-webrtc: 2702afae1e59882b423e6077768ca0d1e6fc42ed
|
||||
react-native-webview: ea4899a1056c782afa96dd082179a66cbebf5504
|
||||
React-perflogger: 46620fc6d1c3157b60ed28434e08f7fd7f3f3353
|
||||
React-RCTActionSheet: b1f7e72a0ba760ec684df335c61f730b5179f5ff
|
||||
React-RCTAnimation: d73b62d42867ab608dfb10e100d8b91106275b18
|
||||
React-RCTBlob: b5f59693721d50967c35598158e6ca01b474c7de
|
||||
React-RCTImage: 37cf34d0c2fbef2e0278d42a7c5e8ea06a9fed6b
|
||||
React-RCTLinking: a11dced20019cf1c2ec7fd120f18b08f2851f79e
|
||||
React-RCTNetwork: ba097188e5eac42e070029e7cedd9b978940833a
|
||||
React-RCTSettings: 147073708a1c1bde521cf3af045a675682772726
|
||||
React-RCTText: 23f76ebfb2717d181476432e5ecf1c6c4a104c5e
|
||||
React-RCTVibration: be5f18ffc644f96f904e0e673ab639ca5d673ee8
|
||||
React-runtimeexecutor: d5498cfb7059bf8397b6416db4777843f3f4c1e7
|
||||
ReactCommon: 1974dab5108c79b40199f12a4833d2499b9f6303
|
||||
React-perflogger: bc57c4a953c1ec913b0d984cf4f2b9842a12bde0
|
||||
React-RCTActionSheet: 3efa3546119a1050f6c34a461b386dd9e36eaf0b
|
||||
React-RCTAnimation: e58fb9f1adf7b38af329881ea2740f43ffeea854
|
||||
React-RCTBlob: d2238645553c3ec787324268c0676148d86e6cc4
|
||||
React-RCTImage: e6d7c9ab978cae99364fcc96b9238fc7740a13da
|
||||
React-RCTLinking: 329e88ce217dad464ef34b5d0c40b3ceaac6c9ec
|
||||
React-RCTNetwork: c8967f2382aac31761ddb750fee53fa34cf7a4ee
|
||||
React-RCTSettings: 8a825b4b5ea58f6713a7c97eea6cc82e9895188b
|
||||
React-RCTText: ffcaac5c66bc065f2ccf79b6fe34585adb9e589b
|
||||
React-RCTVibration: 0039c986626b78242401931bb23c803935fae9d1
|
||||
React-runtimeexecutor: 5ebf1ddaa706bf2986123f22d2cad905443c2c5f
|
||||
ReactCommon: 65754b8932ea80272714988268bbfb9f303264a5
|
||||
RNCalendarEvents: 7e65eb4a94f53c1744d1e275f7fafcfaa619f7a3
|
||||
RNCAsyncStorage: 005c0e2f09575360f142d0d1f1f15e4ec575b1af
|
||||
RNCClipboard: 41d8d918092ae8e676f18adada19104fa3e68495
|
||||
RNDefaultPreference: 08bdb06cfa9188d5da97d4642dac745218d7fb31
|
||||
RNDeviceInfo: 0400a6d0c94186d1120c3cbd97b23abc022187a9
|
||||
RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39
|
||||
RNGoogleSignin: c4381751eefd73c552b923ba347a9bfc6f18771c
|
||||
RNGoogleSignin: 22e468a9474dbcb8618d8847205ad4f0b2575d13
|
||||
RNScreens: 40a2cb40a02a609938137a1e0acfbf8fc9eebf19
|
||||
RNSound: 27e8268bdb0a1f191f219a33267f7e0445e8d62f
|
||||
RNSVG: f3b60aeeaa81960e2e0536c3a9eef50b667ef3a9
|
||||
RNWatch: dae6c858a2051dbdcfb00b9a86cf4d90400263b4
|
||||
Yoga: 7929b92b1828675c1bebeb114dae8cb8fa7ef6a3
|
||||
Yoga: d24d6184b6b85f742536bd93bd07d69d7b9bb4c1
|
||||
|
||||
PODFILE CHECKSUM: e671cdcdb80fab67e305861c36bfae8ed5a5b0ef
|
||||
PODFILE CHECKSUM: e3579df5272b8b697c9fdc0e55aa0845b189c4dd
|
||||
|
||||
COCOAPODS: 1.11.3
|
||||
|
||||
@@ -439,7 +439,7 @@
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "app" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
compatibilityVersion = "Xcode 12.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
@@ -1025,9 +1025,10 @@
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
@@ -1078,8 +1079,9 @@
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
||||
@@ -39,6 +39,11 @@
|
||||
[builder setFeatureFlag:@"ios.screensharing.enabled" withBoolean:YES];
|
||||
[builder setFeatureFlag:@"ios.recording.enabled" withBoolean:YES];
|
||||
builder.serverURL = [NSURL URLWithString:@"https://meet.jit.si"];
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
// CallKit has started to create problems starting with the iOS 16 simulator.
|
||||
// Disable it since it never worked in the simulator anyway.
|
||||
[builder setFeatureFlag:@"call-integration.enabled" withBoolean:NO];
|
||||
#endif
|
||||
}];
|
||||
|
||||
[jitsiMeet application:application didFinishLaunchingWithOptions:launchOptions];
|
||||
|
||||
@@ -98,7 +98,6 @@ platform :ios do
|
||||
demo_account_required: false,
|
||||
distribute_external: true,
|
||||
groups: ENV["JITSI_BETA_TESTING_GROUPS"],
|
||||
reject_build_waiting_for_review: true,
|
||||
uses_non_exempt_encryption: false
|
||||
)
|
||||
|
||||
|
||||
@@ -472,7 +472,7 @@
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 0BD906DF1EC0C00300C8C18E /* Build configuration list for PBXProject "sdk" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
compatibilityVersion = "Xcode 12.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
@@ -526,7 +526,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "export NODE_BINARY=node\nexport NODE_ARGS=\"--max_old_space_size=4096\"\n../../node_modules/react-native/scripts/react-native-xcode.sh\n";
|
||||
shellScript = "WITH_ENVIRONMENT=\"../../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n";
|
||||
};
|
||||
26796D8589142D80C8AFDA51 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
@@ -551,17 +551,12 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-JitsiMeetSDK/Pods-JitsiMeetSDK-resources.sh",
|
||||
"${PODS_ROOT}/Amplitude/Sources/Resources/ComodoRsaDomainValidationCA.der",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/GoogleSignIn/GoogleSignIn.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-JitsiMeetSDK/Pods-JitsiMeetSDK-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ComodoRsaDomainValidationCA.der",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleSignIn.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-JitsiMeetSDK/Pods-JitsiMeetSDK-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
@@ -641,15 +636,12 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-JitsiMeetSDKLite/Pods-JitsiMeetSDKLite-resources.sh",
|
||||
"${PODS_ROOT}/Amplitude/Sources/Resources/ComodoRsaDomainValidationCA.der",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-JitsiMeetSDKLite/Pods-JitsiMeetSDKLite-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ComodoRsaDomainValidationCA.der",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-JitsiMeetSDKLite/Pods-JitsiMeetSDKLite-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
@@ -781,9 +773,10 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
@@ -837,8 +830,9 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
#import <Intents/Intents.h>
|
||||
#import <WebRTC/RTCLogging.h>
|
||||
|
||||
#import "Orientation.h"
|
||||
|
||||
#import "JitsiMeet+Private.h"
|
||||
@@ -26,6 +26,8 @@
|
||||
#import "RNSplashScreen.h"
|
||||
#import "ScheenshareEventEmiter.h"
|
||||
|
||||
#import <react-native-webrtc/WebRTCModuleOptions.h>
|
||||
|
||||
#if !defined(JITSI_MEET_SDK_LITE)
|
||||
#import <RNGoogleSignin/RNGoogleSignin.h>
|
||||
#import "Dropbox.h"
|
||||
@@ -52,6 +54,12 @@
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
#if 0
|
||||
// Initialize WebRTC options.
|
||||
WebRTCModuleOptions *options = [WebRTCModuleOptions sharedInstance];
|
||||
options.loggingSeverity = RTCLoggingSeverityInfo;
|
||||
#endif
|
||||
|
||||
// Initialize the one and only bridge for interfacing with React Native.
|
||||
_bridgeWrapper = [[RCTBridgeWrapper alloc] init];
|
||||
|
||||
@@ -63,11 +71,6 @@
|
||||
|
||||
// Register a log handler for React.
|
||||
registerReactLogHandler();
|
||||
|
||||
#if 0
|
||||
// Enable WebRTC logs
|
||||
RTCSetMinDebugLogLevel(RTCLoggingSeverityInfo);
|
||||
#endif
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -156,6 +156,7 @@
|
||||
"localport_plural": "Portas locais:",
|
||||
"maxEnabledResolution": "enviar máx",
|
||||
"more": "Mostrar mais",
|
||||
"no": "não",
|
||||
"packetloss": "Perda de pacote:",
|
||||
"participant_id": "Participante id:",
|
||||
"quality": {
|
||||
@@ -174,7 +175,8 @@
|
||||
"status": "Ligação:",
|
||||
"transport": "Transporte:",
|
||||
"transport_plural": "Transportes:",
|
||||
"video_ssrc": "Vídeo SSRC:"
|
||||
"video_ssrc": "Vídeo SSRC:",
|
||||
"yes": "sim"
|
||||
},
|
||||
"dateUtils": {
|
||||
"earlier": "Mais cedo",
|
||||
@@ -319,13 +321,13 @@
|
||||
"micPermissionDeniedError": "Não concedeu autorização para utilizar o seu microfone. Ainda pode participar na conferência, mas outros não o ouvirão. Use o botão da câmara na barra de endereço para corrigir isto.",
|
||||
"micTimeoutError": "Não foi possível iniciar a fonte de áudio. Tempo limite expirado!",
|
||||
"micUnknownError": "Não pode usar microfone por uma razão desconhecida.",
|
||||
"moderationAudioLabel": "Permitir aos participantes reativar o som",
|
||||
"moderationVideoLabel": "Permitir aos participantes reativar o vídeo",
|
||||
"muteEveryoneDialog": "Os participantes podem reativar o som a qualquer momento.",
|
||||
"moderationAudioLabel": "Permitir aos participantes ligar o som",
|
||||
"moderationVideoLabel": "Permitir aos participantes ligar a câmara",
|
||||
"muteEveryoneDialog": "Os participantes podem ligar o som a qualquer momento.",
|
||||
"muteEveryoneDialogModerationOn": "Os participantes podem enviar um pedido para falar a qualquer momento.",
|
||||
"muteEveryoneElseDialog": "Uma vez silenciados, não poderá reativá-los, mas eles podem reativar-se a qualquer momento.",
|
||||
"muteEveryoneElseDialog": "Uma vez silenciados, não poderá reativá-los, mas eles podem ligar o microfone a qualquer momento.",
|
||||
"muteEveryoneElseTitle": "Silenciar todos excepto {{whom}}?",
|
||||
"muteEveryoneElsesVideoDialog": "Quando a câmara for desativada, não poderá voltar a ligá-la, mas eles podem voltar a ligá-la em qualquer momento.",
|
||||
"muteEveryoneElsesVideoDialog": "Quando a câmara for desligada, não poderá voltar a ligá-la, mas eles podem voltar a ligá-la em qualquer momento.",
|
||||
"muteEveryoneElsesVideoTitle": "Parar o vídeo de todos excepto {{whom}}?",
|
||||
"muteEveryoneSelf": "você mesmo",
|
||||
"muteEveryoneStartMuted": "A partir de agora, toda a gente começa a ficar calada",
|
||||
@@ -673,8 +675,10 @@
|
||||
"connectedTwoMembers": "{{first}} e {{second}} entraram na reunião",
|
||||
"dataChannelClosed": "Deficiência na qualidade do vídeo",
|
||||
"dataChannelClosedDescription": "O canal de ponte foi desconectado e, portanto, a qualidade do vídeo está limitada à sua configuração mais baixa.",
|
||||
"disabledIframe": "A incorporação destina-se apenas a fins de demonstração, pelo que esta chamada será desligada em {{timeout}} minutos.",
|
||||
"disconnected": "desconectado",
|
||||
"displayNotifications": "Mostrar notificações para",
|
||||
"dontRemindMe": "Não me lembre",
|
||||
"focus": "Foco da conferência",
|
||||
"focusFail": "{{component}} não disponĩvel - tente em {{ms}} seg.",
|
||||
"gifsMenu": "GIPHY",
|
||||
@@ -754,8 +758,8 @@
|
||||
"actions": {
|
||||
"allow": "Permitir aos participantes:",
|
||||
"allowVideo": "Permitir vídeo",
|
||||
"askUnmute": "Pedir para ligar o microfone",
|
||||
"audioModeration": "Ativar o microfone deles",
|
||||
"askUnmute": "Pedir para ligar o som",
|
||||
"audioModeration": "Ligar o microfone deles",
|
||||
"blockEveryoneMicCamera": "Bloquear o microfone e a câmara de todos",
|
||||
"invite": "Convidar alguém",
|
||||
"moreModerationActions": "Mais opções de moderação",
|
||||
@@ -866,9 +870,11 @@
|
||||
"lookGood": "O seu microfone funciona corretamente",
|
||||
"or": "ou",
|
||||
"premeeting": "Pré-reunião",
|
||||
"proceedAnyway": "Continuar na mesma",
|
||||
"screenSharingError": "Erro de partilha de ecrã:",
|
||||
"showScreen": "Ativar o ecrã de pré-reunião",
|
||||
"startWithPhone": "Iniciar com o áudio do telefone",
|
||||
"unsafeRoomConsent": "Compreendo os riscos, quero participar na reunião",
|
||||
"videoOnlyError": "Erro de vídeo:",
|
||||
"videoTrackError": "Não foi possível criar a pista de vídeo.",
|
||||
"viewAllNumbers": "ver todos os números"
|
||||
@@ -944,7 +950,7 @@
|
||||
"noStreams": "Não foi detetado nenhum sinal áudio ou vídeo.",
|
||||
"off": "Gravação parada",
|
||||
"offBy": "{{name}} parou a gravação",
|
||||
"on": "Gravando",
|
||||
"on": "Começou a gravação",
|
||||
"onBy": "{{name}} iniciou a gravação",
|
||||
"onlyRecordSelf": "Gravar apenas as minhas transmissões áudio e vídeo",
|
||||
"pending": "Preparando para gravar a reunião...",
|
||||
@@ -970,8 +976,14 @@
|
||||
"security": {
|
||||
"about": "Pode adicionar uma $t(lockRoomPassword) à sua reunião. Os participantes terão de fornecer a $t(lockRoomPassword) antes de serem autorizados a participar na reunião.",
|
||||
"aboutReadOnly": "Os participantes moderadores podem acrescentar uma $t(lockRoomPassword) à reunião. Os participantes terão de fornecer a $t(lockRoomPassword) antes de serem autorizados a participar na reunião.",
|
||||
"insecureRoomNameWarning": "O nome da sala é inseguro. Participantes indesejados podem juntar-se à sua conferência. Considere proteger a sua reunião utilizando o botão de segurança.",
|
||||
"title": "Opções de segurança"
|
||||
"insecureRoomNameWarningNative": "O nome da sala não é seguro. Participantes indesejados podem juntar-se à sua reunião. {{recommendAction}} Saiba mais sobre como proteger a sua reunião ",
|
||||
"insecureRoomNameWarningWeb": "O nome da sala não é seguro. Participantes indesejados podem juntar-se à sua reunião. {{recommendAction}} Saiba mais sobre como proteger a sua reunião <a href=\"{{securityUrl}}\" rel=\"security\" target=\"_blank\">here</a>.",
|
||||
"title": "Opções de Segurança",
|
||||
"unsafeRoomActions": {
|
||||
"meeting": "Considere a possibilidade de proteger a sua reunião utilizando o botão de segurança.",
|
||||
"prejoin": "Considere a utilização de um nome de reunião mais personalizado.",
|
||||
"welcome": "Considere utilizar um nome de reunião mais personalizado ou selecione uma das sugestões."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"audio": "Áudio",
|
||||
@@ -1146,6 +1158,7 @@
|
||||
"privateMessage": "Enviar mensagem privada",
|
||||
"profile": "Editar o seu perfil",
|
||||
"raiseHand": "Levantar a mão",
|
||||
"reactions": "Reações",
|
||||
"reactionsMenu": "Menu de reações",
|
||||
"recording": "Mudar gravação",
|
||||
"remoteMute": "Participante sem som",
|
||||
@@ -1243,6 +1256,7 @@
|
||||
"reactionLike": "Enviar reação de aprovado",
|
||||
"reactionSilence": "Enviar reação de silêncio",
|
||||
"reactionSurprised": "Enviar reação de surpreendido",
|
||||
"reactions": "Reações",
|
||||
"security": "Opções de segurança",
|
||||
"selectBackground": "Selecionar plano de fundo",
|
||||
"shareRoom": "Convidar alguém",
|
||||
@@ -1376,7 +1390,14 @@
|
||||
"webAssemblyWarning": "WebAssembly não suportado",
|
||||
"webAssemblyWarningDescription": "WebAssembly desactivado ou não suportado por este navegador"
|
||||
},
|
||||
"visitorsLabel": "Número de visitantes: {{count}}",
|
||||
"visitors": {
|
||||
"chatIndicator": "(visitante)",
|
||||
"labelTooltip": "Número de visitantes: {{count}}",
|
||||
"notification": {
|
||||
"description": "Para participar levante a sua mão",
|
||||
"title": "É um visitante na reunião"
|
||||
}
|
||||
},
|
||||
"volumeSlider": "Controlo de volume",
|
||||
"welcomepage": {
|
||||
"accessibilityLabel": {
|
||||
|
||||
@@ -675,6 +675,7 @@
|
||||
"connectedTwoMembers": "{{first}} and {{second}} joined the meeting",
|
||||
"dataChannelClosed": "Video quality impaired",
|
||||
"dataChannelClosedDescription": "The bridge channel has been disconnected and thus video quality is limited to its lowest setting.",
|
||||
"disabledIframe": "Embedding is only meant for demo purposes, so this call will disconnect in {{timeout}} minutes.",
|
||||
"disconnected": "disconnected",
|
||||
"displayNotifications": "Display notifications for",
|
||||
"dontRemindMe": "Do not remind me",
|
||||
@@ -869,9 +870,11 @@
|
||||
"lookGood": "Your microphone is working properly",
|
||||
"or": "or",
|
||||
"premeeting": "Pre meeting",
|
||||
"proceedAnyway": "Proceed anyway",
|
||||
"screenSharingError": "Screen sharing error:",
|
||||
"showScreen": "Enable pre meeting screen",
|
||||
"startWithPhone": "Start with phone audio",
|
||||
"unsafeRoomConsent": "I understand the risks, I want to join the meeting",
|
||||
"videoOnlyError": "Video error:",
|
||||
"videoTrackError": "Could not create video track.",
|
||||
"viewAllNumbers": "view all numbers"
|
||||
@@ -973,8 +976,14 @@
|
||||
"security": {
|
||||
"about": "You can add a $t(lockRoomPassword) to your meeting. Participants will need to provide the $t(lockRoomPassword) before they are allowed to join the meeting.",
|
||||
"aboutReadOnly": "Moderator participants can add a $t(lockRoomPassword) to the meeting. Participants will need to provide the $t(lockRoomPassword) before they are allowed to join the meeting.",
|
||||
"insecureRoomNameWarning": "The room name is unsafe. Unwanted participants may join your conference. Consider securing your meeting using the security button.",
|
||||
"title": "Security Options"
|
||||
"insecureRoomNameWarningNative": "The room name is unsafe. Unwanted participants may join your meeting. {{recommendAction}} Learn more about securing you meeting ",
|
||||
"insecureRoomNameWarningWeb": "The room name is unsafe. Unwanted participants may join your meeting. {{recommendAction}} Learn more about securing you meeting <a href=\"{{securityUrl}}\" rel=\"security\" target=\"_blank\">here</a>.",
|
||||
"title": "Security Options",
|
||||
"unsafeRoomActions": {
|
||||
"meeting": "Consider securing your meeting using the security button.",
|
||||
"prejoin": "Consider using a more unique meeting name.",
|
||||
"welcome": "Consider using a more unique meeting name, or pick one of the suggestions."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"audio": "Audio",
|
||||
@@ -1149,6 +1158,7 @@
|
||||
"privateMessage": "Send private message",
|
||||
"profile": "Edit your profile",
|
||||
"raiseHand": "Raise your hand",
|
||||
"reactions": "Reactions",
|
||||
"reactionsMenu": "Reactions menu",
|
||||
"recording": "Toggle recording",
|
||||
"remoteMute": "Mute participant",
|
||||
@@ -1246,6 +1256,7 @@
|
||||
"reactionLike": "Send thumbs up reaction",
|
||||
"reactionSilence": "Send silence reaction",
|
||||
"reactionSurprised": "Send surprised reaction",
|
||||
"reactions": "Reactions",
|
||||
"security": "Security options",
|
||||
"selectBackground": "Select background",
|
||||
"shareRoom": "Invite someone",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// @flow
|
||||
|
||||
/* global APP */
|
||||
import Logger from '@jitsi/logger';
|
||||
|
||||
import { createApiEvent } from '../../react/features/analytics/AnalyticsEvents';
|
||||
@@ -113,14 +112,17 @@ import { isAudioMuteButtonDisabled } from '../../react/features/toolbox/function
|
||||
import { setTileView, toggleTileView } from '../../react/features/video-layout/actions.any';
|
||||
import { muteAllParticipants } from '../../react/features/video-menu/actions';
|
||||
import { setVideoQuality } from '../../react/features/video-quality/actions';
|
||||
import { toggleWhiteboard } from '../../react/features/whiteboard/actions.any';
|
||||
import { getJitsiMeetTransport } from '../transport';
|
||||
|
||||
import { API_ID, ENDPOINT_TEXT_MESSAGE_NAME } from './constants';
|
||||
import {
|
||||
API_ID,
|
||||
ASSUMED_BANDWIDTH_BPS,
|
||||
ENDPOINT_TEXT_MESSAGE_NAME
|
||||
} from './constants';
|
||||
|
||||
const logger = Logger.getLogger(__filename);
|
||||
|
||||
declare var APP: Object;
|
||||
|
||||
/**
|
||||
* List of the available commands.
|
||||
*/
|
||||
@@ -310,6 +312,23 @@ function initCommands() {
|
||||
|
||||
APP.store.dispatch(sendTones(tones, duration, pause));
|
||||
},
|
||||
'set-assumed-bandwidth-bps': value => {
|
||||
logger.debug('Set assumed bandwidth bps command received', value);
|
||||
|
||||
if (typeof value !== 'number' || isNaN(value)) {
|
||||
logger.error('Assumed bandwidth bps must be a number.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const { conference } = APP.store.getState()['features/base/conference'];
|
||||
|
||||
if (conference) {
|
||||
conference.setAssumedBandwidthBps(value < ASSUMED_BANDWIDTH_BPS
|
||||
? ASSUMED_BANDWIDTH_BPS
|
||||
: value);
|
||||
}
|
||||
},
|
||||
'set-follow-me': value => {
|
||||
logger.debug('Set follow me command received');
|
||||
|
||||
@@ -323,15 +342,16 @@ function initCommands() {
|
||||
},
|
||||
'set-large-video-participant': (participantId, videoType) => {
|
||||
logger.debug('Set large video participant command received');
|
||||
const { getState, dispatch } = APP.store;
|
||||
|
||||
if (!participantId) {
|
||||
sendAnalytics(createApiEvent('largevideo.participant.set'));
|
||||
APP.store.dispatch(selectParticipantInLargeVideo());
|
||||
dispatch(selectParticipantInLargeVideo());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const state = APP.store.getState();
|
||||
const state = getState();
|
||||
const participant = videoType === VIDEO_TYPE.DESKTOP
|
||||
? getVirtualScreenshareParticipantByOwnerId(state, participantId)
|
||||
: getParticipantById(state, participantId);
|
||||
@@ -342,8 +362,9 @@ function initCommands() {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(setTileView(false));
|
||||
sendAnalytics(createApiEvent('largevideo.participant.set'));
|
||||
APP.store.dispatch(selectParticipantInLargeVideo(participant.id));
|
||||
dispatch(selectParticipantInLargeVideo(participant.id));
|
||||
},
|
||||
'set-participant-volume': (participantId, volume) => {
|
||||
APP.store.dispatch(setVolume(participantId, volume));
|
||||
@@ -812,6 +833,9 @@ function initCommands() {
|
||||
} else {
|
||||
logger.error(' End Conference not supported');
|
||||
}
|
||||
},
|
||||
'toggle-whiteboard': () => {
|
||||
APP.store.dispatch(toggleWhiteboard());
|
||||
}
|
||||
};
|
||||
transport.on('event', ({ data, name }) => {
|
||||
@@ -1009,7 +1033,7 @@ function toggleScreenSharing(enable) {
|
||||
* @param {MouseEvent} event - The mouse event to sanitize.
|
||||
* @returns {Object}
|
||||
*/
|
||||
function sanitizeMouseEvent(event: MouseEvent) {
|
||||
function sanitizeMouseEvent(event) {
|
||||
const {
|
||||
clientX,
|
||||
clientY,
|
||||
@@ -1047,7 +1071,7 @@ function sanitizeMouseEvent(event: MouseEvent) {
|
||||
* Jitsi Meet.
|
||||
*/
|
||||
class API {
|
||||
_enabled: boolean;
|
||||
_enabled;
|
||||
|
||||
/**
|
||||
* Initializes the API. Setups message event listeners that will receive
|
||||
@@ -1082,7 +1106,7 @@ class API {
|
||||
* otherwise.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyLargeVideoVisibilityChanged(isHidden: boolean) {
|
||||
notifyLargeVideoVisibilityChanged(isHidden) {
|
||||
this._sendEvent({
|
||||
name: 'large-video-visibility-changed',
|
||||
isVisible: !isHidden
|
||||
@@ -1096,7 +1120,7 @@ class API {
|
||||
* @param {Object} event - The message to pass onto spot.
|
||||
* @returns {void}
|
||||
*/
|
||||
sendProxyConnectionEvent(event: Object) {
|
||||
sendProxyConnectionEvent(event) {
|
||||
this._sendEvent({
|
||||
name: 'proxy-connection-event',
|
||||
...event
|
||||
@@ -1109,7 +1133,7 @@ class API {
|
||||
* @param {Object} event - The event to be sent.
|
||||
* @returns {void}
|
||||
*/
|
||||
_sendEvent(event: Object = {}) {
|
||||
_sendEvent(event = {}) {
|
||||
if (this._enabled) {
|
||||
transport.sendEvent(event);
|
||||
}
|
||||
@@ -1122,7 +1146,7 @@ class API {
|
||||
* @param {boolean} isOpen - True if the chat panel is open.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyChatUpdated(unreadCount: number, isOpen: boolean) {
|
||||
notifyChatUpdated(unreadCount, isOpen) {
|
||||
this._sendEvent({
|
||||
name: 'chat-updated',
|
||||
unreadCount,
|
||||
@@ -1137,7 +1161,7 @@ class API {
|
||||
* @param {boolean} privateMessage - True if the message was a private message.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifySendingChatMessage(message: string, privateMessage: boolean) {
|
||||
notifySendingChatMessage(message, privateMessage) {
|
||||
this._sendEvent({
|
||||
name: 'outgoing-message',
|
||||
message,
|
||||
@@ -1151,7 +1175,7 @@ class API {
|
||||
* @param {MouseEvent} event - The mousemove event.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyMouseEnter(event: MouseEvent) {
|
||||
notifyMouseEnter(event) {
|
||||
this._sendEvent({
|
||||
name: 'mouse-enter',
|
||||
event: sanitizeMouseEvent(event)
|
||||
@@ -1164,7 +1188,7 @@ class API {
|
||||
* @param {MouseEvent} event - The mousemove event.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyMouseLeave(event: MouseEvent) {
|
||||
notifyMouseLeave(event) {
|
||||
this._sendEvent({
|
||||
name: 'mouse-leave',
|
||||
event: sanitizeMouseEvent(event)
|
||||
@@ -1177,7 +1201,7 @@ class API {
|
||||
* @param {MouseEvent} event - The mousemove event.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyMouseMove(event: MouseEvent) {
|
||||
notifyMouseMove(event) {
|
||||
this._sendEvent({
|
||||
name: 'mouse-move',
|
||||
event: sanitizeMouseEvent(event)
|
||||
@@ -1191,7 +1215,7 @@ class API {
|
||||
* @param {boolean} enabled - Whether or not the new moderation status is enabled.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyModerationChanged(mediaType: string, enabled: boolean) {
|
||||
notifyModerationChanged(mediaType, enabled) {
|
||||
this._sendEvent({
|
||||
name: 'moderation-status-changed',
|
||||
mediaType,
|
||||
@@ -1206,7 +1230,7 @@ class API {
|
||||
* @param {string} mediaType - Media type for which the participant was approved.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyParticipantApproved(participantId: string, mediaType: string) {
|
||||
notifyParticipantApproved(participantId, mediaType) {
|
||||
this._sendEvent({
|
||||
name: 'moderation-participant-approved',
|
||||
id: participantId,
|
||||
@@ -1221,7 +1245,7 @@ class API {
|
||||
* @param {string} mediaType - Media type for which the participant was rejected.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyParticipantRejected(participantId: string, mediaType: string) {
|
||||
notifyParticipantRejected(participantId, mediaType) {
|
||||
this._sendEvent({
|
||||
name: 'moderation-participant-rejected',
|
||||
id: participantId,
|
||||
@@ -1237,7 +1261,7 @@ class API {
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyNotificationTriggered(title: string, description: string) {
|
||||
notifyNotificationTriggered(title, description) {
|
||||
this._sendEvent({
|
||||
description,
|
||||
name: 'notification-triggered',
|
||||
@@ -1251,7 +1275,7 @@ class API {
|
||||
* @param {number} videoQuality - The video quality. The number represents the maximum height of the video streams.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyVideoQualityChanged(videoQuality: number) {
|
||||
notifyVideoQualityChanged(videoQuality) {
|
||||
this._sendEvent({
|
||||
name: 'video-quality-changed',
|
||||
videoQuality
|
||||
@@ -1266,9 +1290,7 @@ class API {
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyReceivedChatMessage(
|
||||
{ body, id, nick, privateMessage, ts }: {
|
||||
body: *, id: string, nick: string, privateMessage: boolean, ts: *
|
||||
} = {}) {
|
||||
{ body, id, nick, privateMessage, ts } = {}) {
|
||||
if (APP.conference.isLocalId(id)) {
|
||||
return;
|
||||
}
|
||||
@@ -1291,7 +1313,7 @@ class API {
|
||||
* @param {Object} props - The display name of the user.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyUserJoined(id: string, props: Object) {
|
||||
notifyUserJoined(id, props) {
|
||||
this._sendEvent({
|
||||
name: 'participant-joined',
|
||||
id,
|
||||
@@ -1306,7 +1328,7 @@ class API {
|
||||
* @param {string} id - User id.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyUserLeft(id: string) {
|
||||
notifyUserLeft(id) {
|
||||
this._sendEvent({
|
||||
name: 'participant-left',
|
||||
id
|
||||
@@ -1321,7 +1343,7 @@ class API {
|
||||
* @param {string} role - The new user role.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyUserRoleChanged(id: string, role: string) {
|
||||
notifyUserRoleChanged(id, role) {
|
||||
this._sendEvent({
|
||||
name: 'participant-role-changed',
|
||||
id,
|
||||
@@ -1337,7 +1359,7 @@ class API {
|
||||
* @param {string} avatarURL - The new avatar URL of the participant.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyAvatarChanged(id: string, avatarURL: string) {
|
||||
notifyAvatarChanged(id, avatarURL) {
|
||||
this._sendEvent({
|
||||
name: 'avatar-changed',
|
||||
avatarURL,
|
||||
@@ -1352,7 +1374,7 @@ class API {
|
||||
* @param {Object} data - The event data.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyEndpointTextMessageReceived(data: Object) {
|
||||
notifyEndpointTextMessageReceived(data) {
|
||||
this._sendEvent({
|
||||
name: 'endpoint-text-message-received',
|
||||
data
|
||||
@@ -1366,7 +1388,7 @@ class API {
|
||||
* @param {string} faceExpression - Detected face expression.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyFaceLandmarkDetected(faceBox: Object, faceExpression: string) {
|
||||
notifyFaceLandmarkDetected(faceBox, faceExpression) {
|
||||
this._sendEvent({
|
||||
name: 'face-landmark-detected',
|
||||
faceBox,
|
||||
@@ -1380,7 +1402,7 @@ class API {
|
||||
* @param {Object} data - The event data.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifySharingParticipantsChanged(data: Object) {
|
||||
notifySharingParticipantsChanged(data) {
|
||||
this._sendEvent({
|
||||
name: 'content-sharing-participants-changed',
|
||||
data
|
||||
@@ -1394,7 +1416,7 @@ class API {
|
||||
* @param {Object} devices - The new device list.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyDeviceListChanged(devices: Object) {
|
||||
notifyDeviceListChanged(devices) {
|
||||
this._sendEvent({
|
||||
name: 'device-list-changed',
|
||||
devices
|
||||
@@ -1412,8 +1434,8 @@ class API {
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyDisplayNameChanged(
|
||||
id: string,
|
||||
{ displayName, formattedDisplayName }: Object) {
|
||||
id,
|
||||
{ displayName, formattedDisplayName }) {
|
||||
this._sendEvent({
|
||||
name: 'display-name-change',
|
||||
displayname: displayName,
|
||||
@@ -1431,8 +1453,8 @@ class API {
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyEmailChanged(
|
||||
id: string,
|
||||
{ email }: Object) {
|
||||
id,
|
||||
{ email }) {
|
||||
this._sendEvent({
|
||||
name: 'email-change',
|
||||
email,
|
||||
@@ -1444,10 +1466,10 @@ 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.
|
||||
* @param {Array<string>} args - Array of strings composing the log message.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyLog(logLevel: string, args: Array<string>) {
|
||||
notifyLog(logLevel, args) {
|
||||
this._sendEvent({
|
||||
name: 'log',
|
||||
logLevel,
|
||||
@@ -1465,7 +1487,7 @@ class API {
|
||||
* user and the type of the room.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyConferenceJoined(roomName: string, id: string, props: Object) {
|
||||
notifyConferenceJoined(roomName, id, props) {
|
||||
this._sendEvent({
|
||||
name: 'video-conference-joined',
|
||||
roomName,
|
||||
@@ -1480,7 +1502,7 @@ class API {
|
||||
* @param {string} roomName - User id.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyConferenceLeft(roomName: string) {
|
||||
notifyConferenceLeft(roomName) {
|
||||
this._sendEvent({
|
||||
name: 'video-conference-left',
|
||||
roomName
|
||||
@@ -1495,7 +1517,7 @@ class API {
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyDataChannelClosed(code: number, reason: string) {
|
||||
notifyDataChannelClosed(code, reason) {
|
||||
this._sendEvent({
|
||||
name: 'data-channel-closed',
|
||||
code,
|
||||
@@ -1538,7 +1560,7 @@ class API {
|
||||
* @param {boolean} muted - The new muted status.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyAudioMutedStatusChanged(muted: boolean) {
|
||||
notifyAudioMutedStatusChanged(muted) {
|
||||
this._sendEvent({
|
||||
name: 'audio-mute-status-changed',
|
||||
muted
|
||||
@@ -1552,7 +1574,7 @@ class API {
|
||||
* @param {boolean} muted - The new muted status.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyVideoMutedStatusChanged(muted: boolean) {
|
||||
notifyVideoMutedStatusChanged(muted) {
|
||||
this._sendEvent({
|
||||
name: 'video-mute-status-changed',
|
||||
muted
|
||||
@@ -1566,7 +1588,7 @@ class API {
|
||||
* @param {boolean} available - True if available and false otherwise.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyAudioAvailabilityChanged(available: boolean) {
|
||||
notifyAudioAvailabilityChanged(available) {
|
||||
audioAvailable = available;
|
||||
this._sendEvent({
|
||||
name: 'audio-availability-changed',
|
||||
@@ -1581,7 +1603,7 @@ class API {
|
||||
* @param {boolean} available - True if available and false otherwise.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyVideoAvailabilityChanged(available: boolean) {
|
||||
notifyVideoAvailabilityChanged(available) {
|
||||
videoAvailable = available;
|
||||
this._sendEvent({
|
||||
name: 'video-availability-changed',
|
||||
@@ -1596,7 +1618,7 @@ class API {
|
||||
* @param {string} id - User id of the new on stage participant.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyOnStageParticipantChanged(id: string) {
|
||||
notifyOnStageParticipantChanged(id) {
|
||||
this._sendEvent({
|
||||
name: 'on-stage-participant-changed',
|
||||
id
|
||||
@@ -1610,7 +1632,7 @@ class API {
|
||||
* @param {boolean} isVisible - Whether the prejoin video is visible.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyPrejoinVideoVisibilityChanged(isVisible: boolean) {
|
||||
notifyPrejoinVideoVisibilityChanged(isVisible) {
|
||||
this._sendEvent({
|
||||
name: 'on-prejoin-video-changed',
|
||||
isVisible
|
||||
@@ -1644,7 +1666,7 @@ class API {
|
||||
* @param {string} message - Additional information about the error.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyOnCameraError(type: string, message: string) {
|
||||
notifyOnCameraError(type, message) {
|
||||
this._sendEvent({
|
||||
name: 'camera-error',
|
||||
type,
|
||||
@@ -1660,7 +1682,7 @@ class API {
|
||||
* @param {string} message - Additional information about the error.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyOnMicError(type: string, message: string) {
|
||||
notifyOnMicError(type, message) {
|
||||
this._sendEvent({
|
||||
name: 'mic-error',
|
||||
type,
|
||||
@@ -1676,7 +1698,7 @@ class API {
|
||||
* @param {string} error - A failure message, if any.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyFeedbackSubmitted(error: string) {
|
||||
notifyFeedbackSubmitted(error) {
|
||||
this._sendEvent({
|
||||
name: 'feedback-submitted',
|
||||
error
|
||||
@@ -1701,7 +1723,7 @@ class API {
|
||||
* be displayed or hidden.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyFilmstripDisplayChanged(visible: boolean) {
|
||||
notifyFilmstripDisplayChanged(visible) {
|
||||
this._sendEvent({
|
||||
name: 'filmstrip-display-changed',
|
||||
visible
|
||||
@@ -1718,7 +1740,7 @@ class API {
|
||||
* other participant.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyKickedOut(kicked: Object, kicker: Object) {
|
||||
notifyKickedOut(kicked, kicker) {
|
||||
this._sendEvent({
|
||||
name: 'participant-kicked-out',
|
||||
kicked,
|
||||
@@ -1747,7 +1769,7 @@ class API {
|
||||
* share is capturing.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyScreenSharingStatusChanged(on: boolean, details: Object) {
|
||||
notifyScreenSharingStatusChanged(on, details) {
|
||||
this._sendEvent({
|
||||
name: 'screen-sharing-status-changed',
|
||||
on,
|
||||
@@ -1762,7 +1784,7 @@ class API {
|
||||
* @param {string} id - Id of the dominant participant.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyDominantSpeakerChanged(id: string) {
|
||||
notifyDominantSpeakerChanged(id) {
|
||||
this._sendEvent({
|
||||
name: 'dominant-speaker-changed',
|
||||
id
|
||||
@@ -1776,7 +1798,7 @@ class API {
|
||||
* @param {string} subject - Conference subject.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifySubjectChanged(subject: string) {
|
||||
notifySubjectChanged(subject) {
|
||||
this._sendEvent({
|
||||
name: 'subject-change',
|
||||
subject
|
||||
@@ -1791,7 +1813,7 @@ class API {
|
||||
* otherwise.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyTileViewChanged(enabled: boolean) {
|
||||
notifyTileViewChanged(enabled) {
|
||||
this._sendEvent({
|
||||
name: 'tile-view-changed',
|
||||
enabled
|
||||
@@ -1804,7 +1826,7 @@ class API {
|
||||
* @param {string} localStorageContent - The new localStorageContent.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyLocalStorageChanged(localStorageContent: string) {
|
||||
notifyLocalStorageChanged(localStorageContent) {
|
||||
this._sendEvent({
|
||||
name: 'local-storage-changed',
|
||||
localStorageContent
|
||||
@@ -1818,7 +1840,7 @@ class API {
|
||||
* @param {boolean} handRaised - Whether user has raised hand.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyRaiseHandUpdated(id: string, handRaised: boolean) {
|
||||
notifyRaiseHandUpdated(id, handRaised) {
|
||||
this._sendEvent({
|
||||
name: 'raise-hand-updated',
|
||||
handRaised,
|
||||
@@ -1834,7 +1856,7 @@ class API {
|
||||
* @param {string} error - Error type or null if success.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyRecordingStatusChanged(on: boolean, mode: string, error?: string) {
|
||||
notifyRecordingStatusChanged(on, mode, error) {
|
||||
this._sendEvent({
|
||||
name: 'recording-status-changed',
|
||||
on,
|
||||
@@ -1851,7 +1873,7 @@ class API {
|
||||
* @param {number} ttl - The recording download link time to live.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyRecordingLinkAvailable(link: string, ttl: number) {
|
||||
notifyRecordingLinkAvailable(link, ttl) {
|
||||
this._sendEvent({
|
||||
name: 'recording-link-available',
|
||||
link,
|
||||
@@ -1865,7 +1887,7 @@ class API {
|
||||
* @param {Object} participant - Participant data such as id and name.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyKnockingParticipant(participant: Object) {
|
||||
notifyKnockingParticipant(participant) {
|
||||
this._sendEvent({
|
||||
name: 'knocking-participant',
|
||||
participant
|
||||
@@ -1878,7 +1900,7 @@ class API {
|
||||
* @param {Object} error - The error.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyError(error: Object) {
|
||||
notifyError(error) {
|
||||
this._sendEvent({
|
||||
name: 'error-occurred',
|
||||
error
|
||||
@@ -1892,7 +1914,7 @@ class API {
|
||||
* @param {boolean} preventExecution - Whether execution of the button click was prevented or not.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyToolbarButtonClicked(key: string, preventExecution: boolean) {
|
||||
notifyToolbarButtonClicked(key, preventExecution) {
|
||||
this._sendEvent({
|
||||
name: 'toolbar-button-clicked',
|
||||
key,
|
||||
@@ -1906,7 +1928,7 @@ class API {
|
||||
* @param {boolean} supported - If browser is supported or not.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyBrowserSupport(supported: boolean) {
|
||||
notifyBrowserSupport(supported) {
|
||||
this._sendEvent({
|
||||
name: 'browser-support',
|
||||
supported
|
||||
@@ -1993,6 +2015,20 @@ class API {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify external application (if API is enabled) if whiteboard state is
|
||||
* changed.
|
||||
*
|
||||
* @param {WhiteboardStatus} status - The new whiteboard status.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyWhiteboardStatusChanged(status) {
|
||||
this._sendEvent({
|
||||
name: 'whiteboard-status-changed',
|
||||
status
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes the allocated resources.
|
||||
*
|
||||
|
||||
@@ -15,3 +15,10 @@ export const API_ID = parseURLParams(window.location).jitsi_meet_external_api_id
|
||||
* The payload name for the datachannel/endpoint text message event.
|
||||
*/
|
||||
export const ENDPOINT_TEXT_MESSAGE_NAME = 'endpoint-text-message';
|
||||
|
||||
/**
|
||||
* The min value that can be set for the assumed bandwidth.
|
||||
* Setting it to this value means not assuming any bandwidth,
|
||||
* but rather allowing the estimations to take place.
|
||||
*/
|
||||
export const ASSUMED_BANDWIDTH_BPS = -1;
|
||||
|
||||
38
modules/API/external/external_api.js
vendored
38
modules/API/external/external_api.js
vendored
@@ -36,7 +36,6 @@ const commands = {
|
||||
cancelPrivateChat: 'cancel-private-chat',
|
||||
closeBreakoutRoom: 'close-breakout-room',
|
||||
displayName: 'display-name',
|
||||
e2eeKey: 'e2ee-key',
|
||||
endConference: 'end-conference',
|
||||
email: 'email',
|
||||
grantModerator: 'grant-moderator',
|
||||
@@ -59,6 +58,7 @@ const commands = {
|
||||
sendEndpointTextMessage: 'send-endpoint-text-message',
|
||||
sendParticipantToRoom: 'send-participant-to-room',
|
||||
sendTones: 'send-tones',
|
||||
setAssumedBandwidthBps: 'set-assumed-bandwidth-bps',
|
||||
setFollowMe: 'set-follow-me',
|
||||
setLargeVideoParticipant: 'set-large-video-participant',
|
||||
setMediaEncryptionKey: 'set-media-encryption-key',
|
||||
@@ -89,7 +89,8 @@ const commands = {
|
||||
toggleSubtitles: 'toggle-subtitles',
|
||||
toggleTileView: 'toggle-tile-view',
|
||||
toggleVirtualBackgroundDialog: 'toggle-virtual-background',
|
||||
toggleVideo: 'toggle-video'
|
||||
toggleVideo: 'toggle-video',
|
||||
toggleWhiteboard: 'toggle-whiteboard'
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -153,7 +154,8 @@ const events = {
|
||||
'subject-change': 'subjectChange',
|
||||
'suspend-detected': 'suspendDetected',
|
||||
'tile-view-changed': 'tileViewChanged',
|
||||
'toolbar-button-clicked': 'toolbarButtonClicked'
|
||||
'toolbar-button-clicked': 'toolbarButtonClicked',
|
||||
'whiteboard-status-changed': 'whiteboardStatusChanged'
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -313,6 +315,7 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
* @param {string} [options.e2eeKey] - The key used for End-to-End encryption.
|
||||
* THIS IS EXPERIMENTAL.
|
||||
* @param {string} [options.release] - The key used for specifying release if enabled on the backend.
|
||||
* @param {string} [options.sandbox] - Sandbox directive for the created iframe, if desired.
|
||||
*/
|
||||
constructor(domain, ...args) {
|
||||
super();
|
||||
@@ -330,7 +333,8 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
devices,
|
||||
userInfo,
|
||||
e2eeKey,
|
||||
release
|
||||
release,
|
||||
sandbox = ''
|
||||
} = parseArguments(args);
|
||||
const localStorageContent = jitsiLocalStorage.getItem('jitsiLocalStorage');
|
||||
|
||||
@@ -348,7 +352,7 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
},
|
||||
release
|
||||
});
|
||||
this._createIFrame(height, width, onload);
|
||||
this._createIFrame(height, width, onload, sandbox);
|
||||
this._transport = new Transport({
|
||||
backend: new PostMessageTransportBackend({
|
||||
postisOptions: {
|
||||
@@ -381,11 +385,12 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
* parseSizeParam for format details.
|
||||
* @param {Function} onload - The function that will listen
|
||||
* for onload event.
|
||||
* @param {string} sandbox - Sandbox directive for the created iframe, if desired.
|
||||
* @returns {void}
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_createIFrame(height, width, onload) {
|
||||
_createIFrame(height, width, onload, sandbox) {
|
||||
const frameName = `jitsiConferenceFrame${id}`;
|
||||
|
||||
this._frame = document.createElement('iframe');
|
||||
@@ -396,6 +401,10 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
this._frame.setAttribute('allowFullScreen', 'true');
|
||||
this._frame.style.border = 0;
|
||||
|
||||
if (sandbox) {
|
||||
this._frame.sandbox = sandbox;
|
||||
}
|
||||
|
||||
if (onload) {
|
||||
// waits for iframe resources to load
|
||||
// and fires event when it is done
|
||||
@@ -551,7 +560,22 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
switch (name) {
|
||||
case 'video-conference-joined': {
|
||||
if (typeof this._tmpE2EEKey !== 'undefined') {
|
||||
this.executeCommand(commands.e2eeKey, this._tmpE2EEKey);
|
||||
|
||||
const hexToBytes = hex => {
|
||||
const bytes = [];
|
||||
|
||||
for (let c = 0; c < hex.length; c += 2) {
|
||||
bytes.push(parseInt(hex.substring(c, c + 2), 16));
|
||||
}
|
||||
|
||||
return bytes;
|
||||
};
|
||||
|
||||
this.executeCommand('setMediaEncryptionKey', JSON.stringify({
|
||||
exportedKey: hexToBytes(this._tmpE2EEKey),
|
||||
index: 0
|
||||
}));
|
||||
|
||||
this._tmpE2EEKey = undefined;
|
||||
}
|
||||
|
||||
|
||||
20
modules/API/external/functions.js
vendored
20
modules/API/external/functions.js
vendored
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import Logger from '@jitsi/logger';
|
||||
|
||||
const logger = Logger.getLogger(__filename);
|
||||
@@ -11,7 +9,7 @@ const logger = Logger.getLogger(__filename);
|
||||
* the external communication.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function getAvailableDevices(transport: Object) {
|
||||
export function getAvailableDevices(transport) {
|
||||
return transport.sendRequest({
|
||||
type: 'devices',
|
||||
name: 'getAvailableDevices'
|
||||
@@ -29,7 +27,7 @@ export function getAvailableDevices(transport: Object) {
|
||||
* the external communication.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function getCurrentDevices(transport: Object) {
|
||||
export function getCurrentDevices(transport) {
|
||||
return transport.sendRequest({
|
||||
type: 'devices',
|
||||
name: 'getCurrentDevices'
|
||||
@@ -50,7 +48,7 @@ export function getCurrentDevices(transport: Object) {
|
||||
* Default - 'input'.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function isDeviceChangeAvailable(transport: Object, deviceType: string) {
|
||||
export function isDeviceChangeAvailable(transport, deviceType) {
|
||||
return transport.sendRequest({
|
||||
deviceType,
|
||||
type: 'devices',
|
||||
@@ -66,7 +64,7 @@ export function isDeviceChangeAvailable(transport: Object, deviceType: string) {
|
||||
* the external communication.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function isDeviceListAvailable(transport: Object) {
|
||||
export function isDeviceListAvailable(transport) {
|
||||
return transport.sendRequest({
|
||||
type: 'devices',
|
||||
name: 'isDeviceListAvailable'
|
||||
@@ -81,7 +79,7 @@ export function isDeviceListAvailable(transport: Object) {
|
||||
* the external communication.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function isMultipleAudioInputSupported(transport: Object) {
|
||||
export function isMultipleAudioInputSupported(transport) {
|
||||
return transport.sendRequest({
|
||||
type: 'devices',
|
||||
name: 'isMultipleAudioInputSupported'
|
||||
@@ -97,7 +95,7 @@ export function isMultipleAudioInputSupported(transport: Object) {
|
||||
* @param {string} id - The id of the new device.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function setAudioInputDevice(transport: Object, label: string, id: string) {
|
||||
export function setAudioInputDevice(transport, label, id) {
|
||||
return _setDevice(transport, {
|
||||
id,
|
||||
kind: 'audioinput',
|
||||
@@ -114,7 +112,7 @@ export function setAudioInputDevice(transport: Object, label: string, id: string
|
||||
* @param {string} id - The id of the new device.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function setAudioOutputDevice(transport: Object, label: string, id: string) {
|
||||
export function setAudioOutputDevice(transport, label, id) {
|
||||
return _setDevice(transport, {
|
||||
id,
|
||||
kind: 'audiooutput',
|
||||
@@ -130,7 +128,7 @@ export function setAudioOutputDevice(transport: Object, label: string, id: strin
|
||||
* @param {Object} device - The new device to be used.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
function _setDevice(transport: Object, device) {
|
||||
function _setDevice(transport, device) {
|
||||
return transport.sendRequest({
|
||||
type: 'devices',
|
||||
name: 'setDevice',
|
||||
@@ -147,7 +145,7 @@ function _setDevice(transport: Object, device) {
|
||||
* @param {string} id - The id of the new device.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function setVideoInputDevice(transport: Object, label: string, id: string) {
|
||||
export function setVideoInputDevice(transport, label, id) {
|
||||
return _setDevice(transport, {
|
||||
id,
|
||||
kind: 'videoinput',
|
||||
|
||||
@@ -11,11 +11,11 @@ import { setColorAlpha } from '../../react/features/base/util/helpers';
|
||||
import { setDocumentUrl } from '../../react/features/etherpad/actions';
|
||||
import { setFilmstripVisible } from '../../react/features/filmstrip/actions.any';
|
||||
import {
|
||||
joinLeaveNotificationsDisabled,
|
||||
setNotificationsEnabled,
|
||||
showNotification
|
||||
} from '../../react/features/notifications/actions';
|
||||
import { NOTIFICATION_TIMEOUT_TYPE } from '../../react/features/notifications/constants';
|
||||
import { joinLeaveNotificationsDisabled } from '../../react/features/notifications/functions';
|
||||
import {
|
||||
dockToolbox,
|
||||
setToolboxEnabled,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// @flow
|
||||
|
||||
/* global APP */
|
||||
import Logger from '@jitsi/logger';
|
||||
|
||||
import { openConnection } from '../../../connection';
|
||||
@@ -23,7 +22,6 @@ import ExternalLoginDialog from './LoginDialog';
|
||||
|
||||
|
||||
let externalAuthWindow;
|
||||
declare var APP: Object;
|
||||
|
||||
const logger = Logger.getLogger(__filename);
|
||||
|
||||
@@ -77,7 +75,7 @@ function doExternalAuth(room, lockPassword) {
|
||||
* back with "?jwt={the JWT token}" query parameter added.
|
||||
* @param {string} [roomName] the name of the conference room.
|
||||
*/
|
||||
export function redirectToTokenAuthService(roomName: string) {
|
||||
export function redirectToTokenAuthService(roomName) {
|
||||
const config = APP.store.getState()['features/base/config'];
|
||||
|
||||
// FIXME: This method will not preserve the other URL params that were
|
||||
@@ -174,7 +172,7 @@ function initJWTTokenListener(room) {
|
||||
* @param {JitsiConference} room
|
||||
* @param {string} [lockPassword] password to use if the conference is locked
|
||||
*/
|
||||
function authenticate(room: Object, lockPassword: string) {
|
||||
function authenticate(room, lockPassword) {
|
||||
const config = APP.store.getState()['features/base/config'];
|
||||
|
||||
if (isTokenAuthEnabled(config) || room.isExternalAuthEnabled()) {
|
||||
@@ -189,7 +187,7 @@ function authenticate(room: Object, lockPassword: string) {
|
||||
* @param {JitsiConference} room
|
||||
* @param {string} [lockPassword] password to use if the conference is locked
|
||||
*/
|
||||
function requireAuth(room: Object, lockPassword: string) {
|
||||
function requireAuth(room, lockPassword) {
|
||||
if (isDialogOpen(APP.store, WaitForOwnerDialog) || isDialogOpen(APP.store, LoginDialog)) {
|
||||
return;
|
||||
}
|
||||
@@ -207,7 +205,7 @@ function requireAuth(room: Object, lockPassword: string) {
|
||||
* @param {string} [lockPassword] password to use if the conference is locked
|
||||
* @returns {Promise}
|
||||
*/
|
||||
function logout(room: Object) {
|
||||
function logout(room) {
|
||||
return new Promise(resolve => {
|
||||
room.room.moderator.logout(resolve);
|
||||
}).then(url => {
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// @flow
|
||||
|
||||
declare var APP: Object;
|
||||
/* global APP */
|
||||
|
||||
export default {
|
||||
|
||||
@@ -10,7 +8,7 @@ export default {
|
||||
* @param {function} callback - callback to invoke when auth popup is closed.
|
||||
* @returns auth dialog
|
||||
*/
|
||||
showExternalAuthDialog(url: string, callback: ?Function) {
|
||||
showExternalAuthDialog(url, callback) {
|
||||
const dialog = APP.UI.messageHandler.openCenteredPopup(
|
||||
url, 910, 660,
|
||||
|
||||
|
||||
@@ -1,261 +0,0 @@
|
||||
/* global APP */
|
||||
import { jitsiLocalStorage } from '@jitsi/js-utils';
|
||||
import Logger from '@jitsi/logger';
|
||||
|
||||
import {
|
||||
ACTION_SHORTCUT_PRESSED as PRESSED,
|
||||
ACTION_SHORTCUT_RELEASED as RELEASED,
|
||||
createShortcutEvent
|
||||
} from '../../react/features/analytics/AnalyticsEvents';
|
||||
import { sendAnalytics } from '../../react/features/analytics/functions';
|
||||
import { clickOnVideo } from '../../react/features/filmstrip/actions';
|
||||
import { openSettingsDialog } from '../../react/features/settings/actions';
|
||||
import { SETTINGS_TABS } from '../../react/features/settings/constants';
|
||||
|
||||
const logger = Logger.getLogger(__filename);
|
||||
|
||||
/**
|
||||
* Map of shortcuts. When a shortcut is registered it enters the mapping.
|
||||
* @type {Map}
|
||||
*/
|
||||
const _shortcuts = new Map();
|
||||
|
||||
/**
|
||||
* Map of registered keyboard keys and translation keys describing the
|
||||
* action performed by the key.
|
||||
* @type {Map}
|
||||
*/
|
||||
const _shortcutsHelp = new Map();
|
||||
|
||||
/**
|
||||
* The key used to save in local storage if keyboard shortcuts are enabled.
|
||||
*/
|
||||
const _enableShortcutsKey = 'enableShortcuts';
|
||||
|
||||
/**
|
||||
* Prefer keyboard handling of these elements over global shortcuts.
|
||||
* If a button is triggered using the Spacebar it should not trigger PTT.
|
||||
* If an input element is focused and M is pressed it should not mute audio.
|
||||
*/
|
||||
const _elementsBlacklist = [
|
||||
'input',
|
||||
'textarea',
|
||||
'button',
|
||||
'[role=button]',
|
||||
'[role=menuitem]',
|
||||
'[role=radio]',
|
||||
'[role=tab]',
|
||||
'[role=option]',
|
||||
'[role=switch]',
|
||||
'[role=range]',
|
||||
'[role=log]'
|
||||
];
|
||||
|
||||
/**
|
||||
* An element selector for elements that have their own keyboard handling.
|
||||
*/
|
||||
const _focusedElementsSelector = `:focus:is(${_elementsBlacklist.join(',')})`;
|
||||
|
||||
/**
|
||||
* Maps keycode to character, id of popover for given function and function.
|
||||
*/
|
||||
const KeyboardShortcut = {
|
||||
|
||||
init() {
|
||||
this._initGlobalShortcuts();
|
||||
|
||||
window.onkeyup = e => {
|
||||
if (!this.getEnabled()) {
|
||||
return;
|
||||
}
|
||||
const key = this._getKeyboardKey(e).toUpperCase();
|
||||
const num = parseInt(key, 10);
|
||||
|
||||
if (!document.querySelector(_focusedElementsSelector)) {
|
||||
if (_shortcuts.has(key)) {
|
||||
_shortcuts.get(key).function(e);
|
||||
} else if (!isNaN(num) && num >= 0 && num <= 9) {
|
||||
APP.store.dispatch(clickOnVideo(num));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.onkeydown = e => {
|
||||
if (!this.getEnabled()) {
|
||||
return;
|
||||
}
|
||||
const focusedElement = document.querySelector(_focusedElementsSelector);
|
||||
|
||||
if (!focusedElement) {
|
||||
if (this._getKeyboardKey(e).toUpperCase() === ' ') {
|
||||
if (APP.conference.isLocalAudioMuted()) {
|
||||
sendAnalytics(createShortcutEvent(
|
||||
'push.to.talk',
|
||||
PRESSED));
|
||||
logger.log('Talk shortcut pressed');
|
||||
APP.conference.muteAudio(false);
|
||||
}
|
||||
}
|
||||
} else if (this._getKeyboardKey(e).toUpperCase() === 'ESCAPE') {
|
||||
// Allow to remove focus from selected elements using ESC key.
|
||||
if (focusedElement && focusedElement.blur) {
|
||||
focusedElement.blur();
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables/Disables the keyboard shortcuts.
|
||||
* @param {boolean} value - the new value.
|
||||
*/
|
||||
enable(value) {
|
||||
jitsiLocalStorage.setItem(_enableShortcutsKey, value);
|
||||
},
|
||||
|
||||
getEnabled() {
|
||||
// Should be enabled if not explicitly set to false
|
||||
// eslint-disable-next-line no-unneeded-ternary
|
||||
return jitsiLocalStorage.getItem(_enableShortcutsKey) === 'false' ? false : true;
|
||||
},
|
||||
|
||||
getShortcutsDescriptions() {
|
||||
return _shortcutsHelp;
|
||||
},
|
||||
|
||||
/**
|
||||
* Opens the {@SettingsDialog} dialog on the Shortcuts page.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
openDialog() {
|
||||
APP.store.dispatch(openSettingsDialog(SETTINGS_TABS.SHORTCUTS, false));
|
||||
},
|
||||
|
||||
/**
|
||||
* Registers a new shortcut.
|
||||
*
|
||||
* @param shortcutChar the shortcut character triggering the action
|
||||
* @param shortcutAttr the "shortcut" html element attribute mapping an
|
||||
* element to this shortcut and used to show the shortcut character on the
|
||||
* element tooltip
|
||||
* @param exec the function to be executed when the shortcut is pressed
|
||||
* @param helpDescription the description of the shortcut that would appear
|
||||
* in the help menu
|
||||
* @param altKey whether or not the alt key must be pressed.
|
||||
*/
|
||||
registerShortcut(// eslint-disable-line max-params
|
||||
shortcutChar,
|
||||
shortcutAttr,
|
||||
exec,
|
||||
helpDescription,
|
||||
altKey = false) {
|
||||
_shortcuts.set(altKey ? `:${shortcutChar}` : shortcutChar, {
|
||||
character: shortcutChar,
|
||||
function: exec,
|
||||
shortcutAttr,
|
||||
altKey
|
||||
});
|
||||
|
||||
if (helpDescription) {
|
||||
this._addShortcutToHelp(altKey ? `:${shortcutChar}` : shortcutChar, helpDescription);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Unregisters a shortcut.
|
||||
*
|
||||
* @param shortcutChar unregisters the given shortcut, which means it will
|
||||
* no longer be usable
|
||||
* @param altKey whether or not shortcut is combo with alt key
|
||||
*/
|
||||
unregisterShortcut(shortcutChar, altKey = false) {
|
||||
_shortcuts.delete(altKey ? `:${shortcutChar}` : shortcutChar);
|
||||
_shortcutsHelp.delete(shortcutChar);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param e a KeyboardEvent
|
||||
* @returns {string} e.key or something close if not supported
|
||||
*/
|
||||
_getKeyboardKey(e) {
|
||||
// If alt is pressed a different char can be returned so this takes
|
||||
// the char from the code. It also prefixes with a colon to differentiate
|
||||
// alt combo from simple keypress.
|
||||
if (e.altKey) {
|
||||
const key = e.code.replace('Key', '');
|
||||
|
||||
return `:${key}`;
|
||||
}
|
||||
|
||||
// If e.key is a string, then it is assumed it already plainly states
|
||||
// the key pressed. This may not be true in all cases, such as with Edge
|
||||
// and "?", when the browser cannot properly map a key press event to a
|
||||
// keyboard key. To be safe, when a key is "Unidentified" it must be
|
||||
// further analyzed by jitsi to a key using e.which.
|
||||
if (typeof e.key === 'string' && e.key !== 'Unidentified') {
|
||||
return e.key;
|
||||
}
|
||||
if (e.type === 'keypress'
|
||||
&& ((e.which >= 32 && e.which <= 126)
|
||||
|| (e.which >= 160 && e.which <= 255))) {
|
||||
return String.fromCharCode(e.which);
|
||||
}
|
||||
|
||||
// try to fallback (0-9A-Za-z and QWERTY keyboard)
|
||||
switch (e.which) {
|
||||
case 27:
|
||||
return 'Escape';
|
||||
case 191:
|
||||
return e.shiftKey ? '?' : '/';
|
||||
}
|
||||
if (e.shiftKey || e.type === 'keypress') {
|
||||
return String.fromCharCode(e.which);
|
||||
}
|
||||
|
||||
return String.fromCharCode(e.which).toLowerCase();
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds the given shortcut to the help dialog.
|
||||
*
|
||||
* @param shortcutChar the shortcut character
|
||||
* @param shortcutDescriptionKey the description of the shortcut
|
||||
* @private
|
||||
*/
|
||||
_addShortcutToHelp(shortcutChar, shortcutDescriptionKey) {
|
||||
_shortcutsHelp.set(shortcutChar, shortcutDescriptionKey);
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialise global shortcuts.
|
||||
* Global shortcuts are shortcuts for features that don't have a button or
|
||||
* link associated with the action. In other words they represent actions
|
||||
* triggered _only_ with a shortcut.
|
||||
*/
|
||||
_initGlobalShortcuts() {
|
||||
this.registerShortcut('?', null, () => {
|
||||
sendAnalytics(createShortcutEvent('help'));
|
||||
this.openDialog();
|
||||
}, 'keyboardShortcuts.toggleShortcuts');
|
||||
|
||||
// register SPACE shortcut in two steps to insure visibility of help
|
||||
// message
|
||||
this.registerShortcut(' ', null, () => {
|
||||
sendAnalytics(createShortcutEvent('push.to.talk', RELEASED));
|
||||
logger.log('Talk shortcut released');
|
||||
APP.conference.muteAudio(true);
|
||||
});
|
||||
this._addShortcutToHelp('SPACE', 'keyboardShortcuts.pushToTalk');
|
||||
|
||||
/**
|
||||
* FIXME: Currently focus keys are directly implemented below in
|
||||
* onkeyup. They should be moved to the SmallVideo instead.
|
||||
*/
|
||||
this._addShortcutToHelp('0', 'keyboardShortcuts.focusLocal');
|
||||
this._addShortcutToHelp('1-9', 'keyboardShortcuts.focusRemote');
|
||||
}
|
||||
};
|
||||
|
||||
export default KeyboardShortcut;
|
||||
@@ -1,15 +1,8 @@
|
||||
/* @flow */
|
||||
|
||||
import $ from 'jquery';
|
||||
import jqueryI18next from 'jquery-i18next';
|
||||
|
||||
import i18next from '../../react/features/base/i18n/i18next';
|
||||
|
||||
|
||||
type DocumentElement = {
|
||||
lang: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies that the {@link i18next} instance has finished its initialization.
|
||||
*
|
||||
@@ -18,7 +11,7 @@ type DocumentElement = {
|
||||
*/
|
||||
function _onI18nInitialized() {
|
||||
|
||||
const documentElement: DocumentElement
|
||||
const documentElement
|
||||
= document.documentElement || {};
|
||||
|
||||
$('[data-i18n]').localize();
|
||||
@@ -47,7 +40,7 @@ class Translation {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
generateTranslationHTML(key: string, options: Object) {
|
||||
generateTranslationHTML(key, options) {
|
||||
const optAttr
|
||||
= options ? ` data-i18n-options='${JSON.stringify(options)}'` : '';
|
||||
|
||||
@@ -60,7 +53,7 @@ class Translation {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
translateElement(selector: Object, options: Object) {
|
||||
translateElement(selector, options) {
|
||||
// XXX i18next expects undefined if options are missing.
|
||||
selector.localize(options ? options : undefined);
|
||||
}
|
||||
|
||||
8479
package-lock.json
generated
8479
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
81
package.json
81
package.json
@@ -16,30 +16,26 @@
|
||||
"readmeFilename": "README.md",
|
||||
"dependencies": {
|
||||
"@amplitude/react-native": "2.7.0",
|
||||
"@atlaskit/inline-dialog": "13.0.9",
|
||||
"@atlaskit/inline-message": "11.0.8",
|
||||
"@atlaskit/multi-select": "15.0.5",
|
||||
"@atlaskit/theme": "11.0.2",
|
||||
"@emotion/react": "11.10.0",
|
||||
"@emotion/styled": "11.10.0",
|
||||
"@emotion/react": "11.10.6",
|
||||
"@emotion/styled": "11.10.6",
|
||||
"@giphy/js-fetch-api": "4.7.1",
|
||||
"@giphy/react-components": "5.6.0",
|
||||
"@giphy/react-components": "6.8.1",
|
||||
"@giphy/react-native-sdk": "1.7.0",
|
||||
"@hapi/bourne": "2.0.0",
|
||||
"@jitsi/excalidraw": "https://github.com/jitsi/excalidraw/releases/download/v0.0.12/jitsi-excalidraw-0.0.12.tgz",
|
||||
"@jitsi/excalidraw": "https://github.com/jitsi/excalidraw/releases/download/v0.0.13/jitsi-excalidraw-0.0.13.tgz",
|
||||
"@jitsi/js-utils": "2.0.5",
|
||||
"@jitsi/logger": "2.0.0",
|
||||
"@jitsi/rnnoise-wasm": "0.1.0",
|
||||
"@jitsi/rtcstats": "9.5.1",
|
||||
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.3.tgz",
|
||||
"@microsoft/microsoft-graph-client": "3.0.1",
|
||||
"@mui/material": "5.10.2",
|
||||
"@mui/styles": "5.10.2",
|
||||
"@mui/material": "5.12.1",
|
||||
"@mui/styles": "5.12.0",
|
||||
"@react-native-async-storage/async-storage": "1.17.3",
|
||||
"@react-native-community/clipboard": "1.5.1",
|
||||
"@react-native-community/netinfo": "7.1.7",
|
||||
"@react-native-community/slider": "4.1.12",
|
||||
"@react-native-google-signin/google-signin": "7.0.4",
|
||||
"@react-native-google-signin/google-signin": "9.0.2",
|
||||
"@react-navigation/bottom-tabs": "6.5.3",
|
||||
"@react-navigation/elements": "1.3.13",
|
||||
"@react-navigation/material-top-tabs": "6.5.2",
|
||||
@@ -48,13 +44,9 @@
|
||||
"@svgr/webpack": "6.3.1",
|
||||
"@tensorflow/tfjs-backend-wasm": "3.13.0",
|
||||
"@tensorflow/tfjs-core": "3.13.0",
|
||||
"@types/amplitude-js": "8.16.2",
|
||||
"@types/audioworklet": "0.0.29",
|
||||
"@types/w3c-image-capture": "1.0.6",
|
||||
"@types/w3c-web-hid": "1.0.3",
|
||||
"@vladmandic/human": "2.6.5",
|
||||
"@vladmandic/human-models": "2.5.9",
|
||||
"@xmldom/xmldom": "0.7.9",
|
||||
"@xmldom/xmldom": "0.8.7",
|
||||
"amplitude-js": "8.2.1",
|
||||
"base64-js": "1.3.1",
|
||||
"bc-css-flags": "3.0.0",
|
||||
@@ -73,7 +65,7 @@
|
||||
"js-md5": "0.6.1",
|
||||
"js-sha512": "0.8.0",
|
||||
"jwt-decode": "2.2.0",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1615.0.0+a23a8c7c/lib-jitsi-meet.tgz",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1637.0.0+8f836678/lib-jitsi-meet.tgz",
|
||||
"lodash": "4.17.21",
|
||||
"moment": "2.29.4",
|
||||
"moment-duration-format": "2.2.2",
|
||||
@@ -81,13 +73,13 @@
|
||||
"optional-require": "1.0.3",
|
||||
"promise.allsettled": "1.0.4",
|
||||
"punycode": "2.1.1",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-emoji-render": "1.2.4",
|
||||
"react-focus-lock": "2.5.1",
|
||||
"react-focus-lock": "2.9.4",
|
||||
"react-i18next": "10.11.4",
|
||||
"react-linkify": "1.0.0-alpha",
|
||||
"react-native": "0.68.6",
|
||||
"react-native": "0.69.10",
|
||||
"react-native-background-timer": "2.4.1",
|
||||
"react-native-calendar-events": "2.2.0",
|
||||
"react-native-callstats": "3.73.7",
|
||||
@@ -112,7 +104,7 @@
|
||||
"react-native-url-polyfill": "1.3.0",
|
||||
"react-native-video": "https://git@github.com/react-native-video/react-native-video#7c48ae7c8544b2b537fb60194e9620b9fcceae52",
|
||||
"react-native-watch-connectivity": "1.0.11",
|
||||
"react-native-webrtc": "106.0.7",
|
||||
"react-native-webrtc": "111.0.1",
|
||||
"react-native-webview": "11.15.1",
|
||||
"react-native-youtube-iframe": "2.2.1",
|
||||
"react-redux": "7.1.0",
|
||||
@@ -123,7 +115,6 @@
|
||||
"redux-thunk": "2.4.1",
|
||||
"resemblejs": "4.0.0",
|
||||
"seamless-scroll-polyfill": "2.1.8",
|
||||
"styled-components": "3.4.9",
|
||||
"tss-react": "4.4.4",
|
||||
"util": "0.12.1",
|
||||
"uuid": "8.3.2",
|
||||
@@ -134,53 +125,63 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.16.0",
|
||||
"@babel/eslint-parser": "7.16.0",
|
||||
"@babel/eslint-parser": "7.21.8",
|
||||
"@babel/plugin-proposal-export-default-from": "7.16.0",
|
||||
"@babel/preset-env": "7.16.0",
|
||||
"@babel/preset-flow": "7.16.0",
|
||||
"@babel/preset-react": "7.16.0",
|
||||
"@jitsi/eslint-config": "4.1.5",
|
||||
"@types/amplitude-js": "8.16.2",
|
||||
"@types/audioworklet": "0.0.29",
|
||||
"@types/js-md5": "0.4.3",
|
||||
"@types/lodash": "4.14.182",
|
||||
"@types/punycode": "2.1.0",
|
||||
"@types/react": "17.0.14",
|
||||
"@types/react-dom": "17.0.14",
|
||||
"@types/react-linkify": "1.0.1",
|
||||
"@types/react-native": "0.68.9",
|
||||
"@types/react-native": "0.69.20",
|
||||
"@types/react-native-keep-awake": "2.0.3",
|
||||
"@types/react-native-video": "5.0.14",
|
||||
"@types/react-redux": "7.1.24",
|
||||
"@types/react-window": "1.8.5",
|
||||
"@types/resemblejs": "^4.1.0",
|
||||
"@types/unorm": "1.3.28",
|
||||
"@types/uuid": "8.3.4",
|
||||
"@types/w3c-image-capture": "1.0.6",
|
||||
"@types/w3c-web-hid": "1.0.3",
|
||||
"@types/zxcvbn": "4.4.1",
|
||||
"@typescript-eslint/eslint-plugin": "5.30.5",
|
||||
"@typescript-eslint/parser": "5.30.4",
|
||||
"@typescript-eslint/eslint-plugin": "5.59.5",
|
||||
"@typescript-eslint/parser": "5.59.5",
|
||||
"babel-loader": "8.2.3",
|
||||
"babel-plugin-optional-require": "0.3.1",
|
||||
"circular-dependency-plugin": "5.2.0",
|
||||
"clean-css-cli": "4.3.0",
|
||||
"css-loader": "3.6.0",
|
||||
"eslint": "8.35.0",
|
||||
"eslint-plugin-flowtype": "8.0.3",
|
||||
"eslint-plugin-import": "2.25.2",
|
||||
"eslint": "8.40.0",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
"eslint-plugin-jsdoc": "37.0.3",
|
||||
"eslint-plugin-react": "7.26.1",
|
||||
"eslint-plugin-react-native": "3.11.0",
|
||||
"eslint-plugin-typescript-sort-keys": "2.1.0",
|
||||
"eslint-plugin-react": "7.32.2",
|
||||
"eslint-plugin-react-native": "4.0.0",
|
||||
"eslint-plugin-typescript-sort-keys": "2.3.0",
|
||||
"jetifier": "1.6.4",
|
||||
"metro-react-native-babel-preset": "0.67.0",
|
||||
"metro-react-native-babel-preset": "0.70.3",
|
||||
"patch-package": "6.4.7",
|
||||
"process": "0.11.10",
|
||||
"sass": "1.26.8",
|
||||
"style-loader": "3.3.1",
|
||||
"traverse": "0.6.6",
|
||||
"ts-loader": "9.4.1",
|
||||
"typescript": "4.7.4",
|
||||
"ts-loader": "9.4.2",
|
||||
"typescript": "5.0.4",
|
||||
"unorm": "1.6.0",
|
||||
"webpack": "5.57.1",
|
||||
"webpack": "5.76.0",
|
||||
"webpack-bundle-analyzer": "4.4.2",
|
||||
"webpack-cli": "4.9.0",
|
||||
"webpack-dev-server": "4.7.3"
|
||||
},
|
||||
"overrides": {
|
||||
"strophe.js@1.5.0": {
|
||||
"@xmldom/xmldom": "0.8.7"
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0",
|
||||
"npm": ">=7.0.0"
|
||||
@@ -191,12 +192,14 @@
|
||||
"tsc:web": "tsc --noEmit --project tsconfig.web.json",
|
||||
"tsc:native": "tsc --noEmit --project tsconfig.native.json",
|
||||
"tsc:ci": "npm run tsc:web && npm run tsc:native",
|
||||
"lint:ci": "eslint --ext .js,.ts,.tsx --max-warnings 0 . && npm run tsc:ci && npm run lint:lang",
|
||||
"lint:ci": "eslint --ext .js,.ts,.tsx --max-warnings 0 .",
|
||||
"lint:lang": "for file in lang/*.json; do npx --yes jsonlint -q $file || exit 1; done",
|
||||
"lang-sort": "./resources/lang-sort.sh",
|
||||
"lint-fix": "eslint --ext .js,.ts,.tsx --max-warnings 0 --fix .",
|
||||
"postinstall": "patch-package --error-on-fail && jetify",
|
||||
"validate": "npm ls",
|
||||
"tsc-test:web": "tsc --project tsconfig.web.json --listFilesOnly | grep -v node_modules | grep native",
|
||||
"tsc-test:native": "tsc --project tsconfig.native.json --listFilesOnly | grep -v node_modules | grep web",
|
||||
"start": "make dev"
|
||||
},
|
||||
"resolutions": {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
diff --git a/node_modules/@giphy/js-analytics/dist/send-pingback.js b/node_modules/@giphy/js-analytics/dist/send-pingback.js
|
||||
index 001345a..f303443 100644
|
||||
index 989f0ff..149e77c 100644
|
||||
--- a/node_modules/@giphy/js-analytics/dist/send-pingback.js
|
||||
+++ b/node_modules/@giphy/js-analytics/dist/send-pingback.js
|
||||
@@ -10,6 +10,9 @@ var global_1 = __importDefault(require("./global"));
|
||||
var environment = (global_1.default === null || global_1.default === void 0 ? void 0 : global_1.default.GIPHY_PINGBACK_URL) || 'https://pingback.giphy.com';
|
||||
var pingBackUrl = environment + "/v2/pingback?apikey=l0HlIwPWyBBUDAUgM";
|
||||
var pingBackUrl = "".concat(environment, "/v2/pingback?apikey=l0HlIwPWyBBUDAUgM");
|
||||
var sendPingback = function (events) {
|
||||
+ // Disabled.
|
||||
+ return Promise.resolve();
|
||||
+
|
||||
var headers = js_util_1.getGiphySDKRequestHeaders();
|
||||
var headers = (0, js_util_1.getGiphySDKRequestHeaders)();
|
||||
/* istanbul ignore next */
|
||||
headers === null || headers === void 0 ? void 0 : headers.set('Content-Type', 'application/json');
|
||||
@@ -1,12 +0,0 @@
|
||||
diff --git a/node_modules/@giphy/js-brand/dist/typography.js b/node_modules/@giphy/js-brand/dist/typography.js
|
||||
index af796bc..585fa00 100644
|
||||
--- a/node_modules/@giphy/js-brand/dist/typography.js
|
||||
+++ b/node_modules/@giphy/js-brand/dist/typography.js
|
||||
@@ -7,7 +7,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.css = exports.fontSize = exports.fontFamily = void 0;
|
||||
var emotion_1 = require("emotion");
|
||||
// eslint-disable-next-line
|
||||
-emotion_1.injectGlobal(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n@font-face {\n font-family: 'interface';\n font-style: normal;\n font-weight: normal;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_Rg.woff2') format('woff2'),\n url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_Rg.woff') format('woff');\n}\n\n@font-face {\n font-family: 'interface';\n font-style: normal;\n font-weight: bold;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_Bd.woff2') format('woff2'),\n url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_Bd.woff') format('woff');\n}\n@font-face {\n font-family: 'interface';\n font-style: normal;\n font-weight: 900;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_XBd.woff') format('woff');\n}\n@font-face {\n font-family: 'nexablack'; \n font-style: normal;\n font-weight: normal;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/nexa_black-webfont.woff2') format('woff2'),\n url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/nexa_black-webfont.woff') format('woff');\n}\n@font-face {\n font-family: 'SSStandard'; \n font-style: normal;\n font-weight: normal;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/ss-standard.woff') format('woff');\n}\n@font-face {\n font-family: 'SSSocial'; \n font-style: normal;\n font-weight: normal;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/ss-social.woff') format('woff');\n}\n"], ["\n@font-face {\n font-family: 'interface';\n font-style: normal;\n font-weight: normal;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_Rg.woff2') format('woff2'),\n url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_Rg.woff') format('woff');\n}\n\n@font-face {\n font-family: 'interface';\n font-style: normal;\n font-weight: bold;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_Bd.woff2') format('woff2'),\n url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_Bd.woff') format('woff');\n}\n@font-face {\n font-family: 'interface';\n font-style: normal;\n font-weight: 900;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_XBd.woff') format('woff');\n}\n@font-face {\n font-family: 'nexablack'; \n font-style: normal;\n font-weight: normal;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/nexa_black-webfont.woff2') format('woff2'),\n url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/nexa_black-webfont.woff') format('woff');\n}\n@font-face {\n font-family: 'SSStandard'; \n font-style: normal;\n font-weight: normal;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/ss-standard.woff') format('woff');\n}\n@font-face {\n font-family: 'SSSocial'; \n font-style: normal;\n font-weight: normal;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/ss-social.woff') format('woff');\n}\n"])));
|
||||
exports.fontFamily = {
|
||||
title: "'nexablack', sans-serif",
|
||||
body: 'interface, Helvetica Neue, helvetica, sans-serif;',
|
||||
13
patches/@giphy+js-brand+2.2.2.patch
Normal file
13
patches/@giphy+js-brand+2.2.2.patch
Normal file
@@ -0,0 +1,13 @@
|
||||
diff --git a/node_modules/@giphy/js-brand/dist/typography.js b/node_modules/@giphy/js-brand/dist/typography.js
|
||||
index 75ad96b..815cb8b 100644
|
||||
--- a/node_modules/@giphy/js-brand/dist/typography.js
|
||||
+++ b/node_modules/@giphy/js-brand/dist/typography.js
|
||||
@@ -6,7 +6,7 @@ var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cook
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.css = exports.fontSize = exports.fontFamily = exports.addFonts = void 0;
|
||||
var emotion_1 = require("emotion");
|
||||
-var addFonts = function () { return (0, emotion_1.injectGlobal)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n@font-face {\n font-family: 'interface';\n font-style: normal;\n font-weight: normal;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_Rg.woff2') format('woff2'),\n url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_Rg.woff') format('woff');\n}\n\n@font-face {\n font-family: 'interface';\n font-style: normal;\n font-weight: bold;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_Bd.woff2') format('woff2'),\n url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_Bd.woff') format('woff');\n}\n@font-face {\n font-family: 'interface';\n font-style: normal;\n font-weight: 900;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_XBd.woff') format('woff');\n}\n@font-face {\n font-family: 'nexablack'; \n font-style: normal;\n font-weight: normal;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/nexa_black-webfont.woff2') format('woff2'),\n url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/nexa_black-webfont.woff') format('woff');\n}\n@font-face {\n font-family: 'SSStandard'; \n font-style: normal;\n font-weight: normal;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/ss-standard.woff') format('woff');\n}\n@font-face {\n font-family: 'SSSocial'; \n font-style: normal;\n font-weight: normal;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/ss-social.woff') format('woff');\n}\n"], ["\n@font-face {\n font-family: 'interface';\n font-style: normal;\n font-weight: normal;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_Rg.woff2') format('woff2'),\n url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_Rg.woff') format('woff');\n}\n\n@font-face {\n font-family: 'interface';\n font-style: normal;\n font-weight: bold;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_Bd.woff2') format('woff2'),\n url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_Bd.woff') format('woff');\n}\n@font-face {\n font-family: 'interface';\n font-style: normal;\n font-weight: 900;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/InterFace_W_XBd.woff') format('woff');\n}\n@font-face {\n font-family: 'nexablack'; \n font-style: normal;\n font-weight: normal;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/nexa_black-webfont.woff2') format('woff2'),\n url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/nexa_black-webfont.woff') format('woff');\n}\n@font-face {\n font-family: 'SSStandard'; \n font-style: normal;\n font-weight: normal;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/ss-standard.woff') format('woff');\n}\n@font-face {\n font-family: 'SSSocial'; \n font-style: normal;\n font-weight: normal;\n src: url('https://s3.amazonaws.com/giphyscripts/react-giphy-brand/fonts/ss-social.woff') format('woff');\n}\n"]))); };
|
||||
+var addFonts = function () { };
|
||||
exports.addFonts = addFonts;
|
||||
try {
|
||||
// in an env where process.env exists,
|
||||
@@ -1,11 +0,0 @@
|
||||
diff --git a/node_modules/eslint-plugin-flowtype/dist/configs/recommended.json b/node_modules/eslint-plugin-flowtype/dist/configs/recommended.json
|
||||
index 90a0d69..2ad7d68 100644
|
||||
--- a/node_modules/eslint-plugin-flowtype/dist/configs/recommended.json
|
||||
+++ b/node_modules/eslint-plugin-flowtype/dist/configs/recommended.json
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
- "parser": "@babel/eslint",
|
||||
+ "parser": "@babel/eslint-parser",
|
||||
"parserOptions": {
|
||||
"babelOptions": {
|
||||
"plugins": [
|
||||
@@ -26,10 +26,5 @@ module.exports = {
|
||||
ios: null
|
||||
}
|
||||
}
|
||||
},
|
||||
project: {
|
||||
ios: {
|
||||
project: '.ios/jitsi-meet.xcworkspace'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
module.exports = {
|
||||
'extends': [
|
||||
'../.eslintrc.js',
|
||||
'@jitsi/eslint-config/flow',
|
||||
'@jitsi/eslint-config/jsdoc',
|
||||
'@jitsi/eslint-config/react',
|
||||
'.eslintrc-react-native.js'
|
||||
@@ -30,15 +29,10 @@ module.exports = {
|
||||
}
|
||||
],
|
||||
'rules': {
|
||||
'flowtype/no-types-missing-file-annotation': 0,
|
||||
|
||||
// XXX remove this eventually.
|
||||
'react/jsx-indent-props': 0
|
||||
},
|
||||
'settings': {
|
||||
'flowtype': {
|
||||
'onlyFilesWithFlowAnnotation': true
|
||||
},
|
||||
'react': {
|
||||
'version': 'detect'
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
// We need to reference these files directly to avoid loading things that are not available
|
||||
@@ -19,15 +17,15 @@ const TOOLBAR_TIMEOUT = 4000;
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link AlwaysOnTop}.
|
||||
*/
|
||||
type State = {
|
||||
avatarURL: string,
|
||||
customAvatarBackgrounds: Array<string>,
|
||||
displayName: string,
|
||||
formattedDisplayName: string,
|
||||
isVideoDisplayed: boolean,
|
||||
userID: string,
|
||||
visible: boolean
|
||||
};
|
||||
interface IState {
|
||||
avatarURL: string;
|
||||
customAvatarBackgrounds: Array<string>;
|
||||
displayName: string;
|
||||
formattedDisplayName: string;
|
||||
isVideoDisplayed: boolean;
|
||||
userID: string;
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the always on top page.
|
||||
@@ -35,7 +33,7 @@ type State = {
|
||||
* @class AlwaysOnTop
|
||||
* @augments Component
|
||||
*/
|
||||
export default class AlwaysOnTop extends Component<*, State> {
|
||||
export default class AlwaysOnTop extends Component<any, IState> {
|
||||
_hovered: boolean;
|
||||
|
||||
/**
|
||||
@@ -44,7 +42,7 @@ export default class AlwaysOnTop extends Component<*, State> {
|
||||
* @param {*} props - The read-only properties with which the new instance
|
||||
* is to be initialized.
|
||||
*/
|
||||
constructor(props: *) {
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
@@ -68,28 +66,25 @@ export default class AlwaysOnTop extends Component<*, State> {
|
||||
this._onMouseOver = this._onMouseOver.bind(this);
|
||||
}
|
||||
|
||||
_avatarChangedListener: () => void;
|
||||
|
||||
/**
|
||||
* Handles avatar changed api events.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_avatarChangedListener({ avatarURL, id }) {
|
||||
_avatarChangedListener({ avatarURL, id }: { avatarURL: string; id: string; }) {
|
||||
if (api._getOnStageParticipant() === id
|
||||
&& avatarURL !== this.state.avatarURL) {
|
||||
this.setState({ avatarURL });
|
||||
}
|
||||
}
|
||||
|
||||
_displayNameChangedListener: () => void;
|
||||
|
||||
/**
|
||||
* Handles display name changed api events.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_displayNameChangedListener({ displayname, formattedDisplayName, id }) {
|
||||
_displayNameChangedListener({ displayname, formattedDisplayName, id }: { displayname: string;
|
||||
formattedDisplayName: string; id: string; }) {
|
||||
if (api._getOnStageParticipant() === id
|
||||
&& (formattedDisplayName !== this.state.formattedDisplayName
|
||||
|| displayname !== this.state.displayName)) {
|
||||
@@ -118,8 +113,6 @@ export default class AlwaysOnTop extends Component<*, State> {
|
||||
TOOLBAR_TIMEOUT);
|
||||
}
|
||||
|
||||
_videoChangedListener: () => void;
|
||||
|
||||
/**
|
||||
* Handles large video changed api events.
|
||||
*
|
||||
@@ -141,8 +134,6 @@ export default class AlwaysOnTop extends Component<*, State> {
|
||||
});
|
||||
}
|
||||
|
||||
_mouseMove: () => void;
|
||||
|
||||
/**
|
||||
* Handles mouse move events.
|
||||
*
|
||||
@@ -152,8 +143,6 @@ export default class AlwaysOnTop extends Component<*, State> {
|
||||
this.state.visible || this.setState({ visible: true });
|
||||
}
|
||||
|
||||
_onMouseOut: () => void;
|
||||
|
||||
/**
|
||||
* Toolbar mouse out handler.
|
||||
*
|
||||
@@ -163,8 +152,6 @@ export default class AlwaysOnTop extends Component<*, State> {
|
||||
this._hovered = false;
|
||||
}
|
||||
|
||||
_onMouseOver: () => void;
|
||||
|
||||
/**
|
||||
* Toolbar mouse over handler.
|
||||
*
|
||||
@@ -229,7 +216,7 @@ export default class AlwaysOnTop extends Component<*, State> {
|
||||
|
||||
this._hideToolbarAfterTimeout();
|
||||
api.getCustomAvatarBackgrounds()
|
||||
.then(res =>
|
||||
.then((res: { avatarBackgrounds?: string[]; }) =>
|
||||
this.setState({
|
||||
customAvatarBackgrounds: res.avatarBackgrounds || []
|
||||
}))
|
||||
@@ -242,7 +229,7 @@ export default class AlwaysOnTop extends Component<*, State> {
|
||||
* @inheritdoc
|
||||
* @returns {void}
|
||||
*/
|
||||
componentDidUpdate(prevProps: *, prevState: State) {
|
||||
componentDidUpdate(_prevProps: any, prevState: IState) {
|
||||
if (!prevState.visible && this.state.visible) {
|
||||
this._hideToolbarAfterTimeout();
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
// We need to reference these files directly to avoid loading things that are not available
|
||||
// in this environment (e.g. JitsiMeetJS or interfaceConfig)
|
||||
import { IconMic, IconMicSlash } from '../base/icons/svg';
|
||||
import type { Props } from '../base/toolbox/components/AbstractButton';
|
||||
import { IProps } from '../base/toolbox/components/AbstractButton';
|
||||
|
||||
import ToolbarButton from './ToolbarButton';
|
||||
|
||||
@@ -14,23 +12,25 @@ const { api } = window.alwaysOnTop;
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link AudioMuteButton}.
|
||||
*/
|
||||
type State = {
|
||||
interface IState {
|
||||
|
||||
/**
|
||||
* Whether audio is available is not.
|
||||
*/
|
||||
audioAvailable: boolean,
|
||||
audioAvailable: boolean;
|
||||
|
||||
/**
|
||||
* Whether audio is muted or not.
|
||||
*/
|
||||
audioMuted: boolean
|
||||
};
|
||||
audioMuted: boolean;
|
||||
}
|
||||
|
||||
type Props = Partial<IProps>;
|
||||
|
||||
/**
|
||||
* Stateless "mute/unmute audio" button for the Always-on-Top windows.
|
||||
*/
|
||||
export default class AudioMuteButton extends Component<Props, State> {
|
||||
export default class AudioMuteButton extends Component<Props, IState> {
|
||||
icon = IconMic;
|
||||
toggledIcon = IconMicSlash;
|
||||
accessibilityLabel = 'Audio mute';
|
||||
@@ -38,7 +38,7 @@ export default class AudioMuteButton extends Component<Props, State> {
|
||||
/**
|
||||
* Initializes a new {@code AudioMuteButton} instance.
|
||||
*
|
||||
* @param {Props} props - The React {@code Component} props to initialize
|
||||
* @param {IProps} props - The React {@code Component} props to initialize
|
||||
* the new {@code AudioMuteButton} instance with.
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
@@ -94,27 +94,23 @@ export default class AudioMuteButton extends Component<Props, State> {
|
||||
this._audioMutedListener);
|
||||
}
|
||||
|
||||
_audioAvailabilityListener: ({ available: boolean }) => void;
|
||||
|
||||
/**
|
||||
* Handles audio available api events.
|
||||
*
|
||||
* @param {{ available: boolean }} status - The new available status.
|
||||
* @returns {void}
|
||||
*/
|
||||
_audioAvailabilityListener({ available }) {
|
||||
_audioAvailabilityListener({ available }: { available: boolean; }) {
|
||||
this.setState({ audioAvailable: available });
|
||||
}
|
||||
|
||||
_audioMutedListener: ({ muted: boolean }) => void;
|
||||
|
||||
/**
|
||||
* Handles audio muted api events.
|
||||
*
|
||||
* @param {{ muted: boolean }} status - The new muted status.
|
||||
* @returns {void}
|
||||
*/
|
||||
_audioMutedListener({ muted }) {
|
||||
_audioMutedListener({ muted }: { muted: boolean; }) {
|
||||
this.setState({ audioMuted: muted });
|
||||
}
|
||||
|
||||
@@ -144,16 +140,14 @@ export default class AudioMuteButton extends Component<Props, State> {
|
||||
* Changes the muted state.
|
||||
*
|
||||
* @override
|
||||
* @param {boolean} audioMuted - Whether audio should be muted or not.
|
||||
* @param {boolean} _audioMuted - Whether audio should be muted or not.
|
||||
* @protected
|
||||
* @returns {void}
|
||||
*/
|
||||
_setAudioMuted(audioMuted: boolean) { // eslint-disable-line no-unused-vars
|
||||
_setAudioMuted(_audioMuted: boolean) {
|
||||
this.state.audioAvailable && api.executeCommand('toggleAudio');
|
||||
}
|
||||
|
||||
_onClick: () => {};
|
||||
|
||||
/**
|
||||
* Handles clicking / pressing the button, and toggles the audio mute state
|
||||
* accordingly.
|
||||
@@ -173,11 +167,13 @@ export default class AudioMuteButton extends Component<Props, State> {
|
||||
render() {
|
||||
const toggled = this._isAudioMuted();
|
||||
|
||||
return (<ToolbarButton
|
||||
accessibilityLabel = { this.accessibilityLabel }
|
||||
disabled = { this._isDisabled() }
|
||||
icon = { toggled ? this.toggledIcon : this.icon }
|
||||
onClick = { this._onClick }
|
||||
toggled = { toggled } />);
|
||||
return (
|
||||
<ToolbarButton
|
||||
accessibilityLabel = { this.accessibilityLabel }
|
||||
disabled = { this._isDisabled() }
|
||||
icon = { toggled ? this.toggledIcon : this.icon }
|
||||
onClick = { this._onClick }
|
||||
toggled = { toggled } />
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,20 @@
|
||||
// @flow
|
||||
import React, { Component } from 'react';
|
||||
|
||||
// We need to reference these files directly to avoid loading things that are not available
|
||||
// in this environment (e.g. JitsiMeetJS or interfaceConfig)
|
||||
import { IconHangup } from '../base/icons/svg';
|
||||
import type { Props } from '../base/toolbox/components/AbstractButton';
|
||||
import { IProps } from '../base/toolbox/components/AbstractButton';
|
||||
|
||||
import ToolbarButton from './ToolbarButton';
|
||||
|
||||
const { api } = window.alwaysOnTop;
|
||||
|
||||
type Props = Partial<IProps>;
|
||||
|
||||
/**
|
||||
* Stateless hangup button for the Always-on-Top windows.
|
||||
*/
|
||||
export default class HangupButton extends Component<Props, *> {
|
||||
export default class HangupButton extends Component<Props> {
|
||||
|
||||
accessibilityLabel = 'Hangup';
|
||||
icon = IconHangup;
|
||||
@@ -21,7 +22,7 @@ export default class HangupButton extends Component<Props, *> {
|
||||
/**
|
||||
* Initializes a new {@code HangupButton} instance.
|
||||
*
|
||||
* @param {Props} props - The React {@code Component} props to initialize
|
||||
* @param {IProps} props - The React {@code Component} props to initialize
|
||||
* the new {@code HangupButton} instance with.
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
@@ -31,8 +32,6 @@ export default class HangupButton extends Component<Props, *> {
|
||||
this._onClick = this._onClick.bind(this);
|
||||
}
|
||||
|
||||
_onClick: () => {};
|
||||
|
||||
/**
|
||||
* Handles clicking / pressing the button, and disconnects the conference.
|
||||
*
|
||||
@@ -50,10 +49,12 @@ export default class HangupButton extends Component<Props, *> {
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
return (<ToolbarButton
|
||||
accessibilityLabel = { this.accessibilityLabel }
|
||||
customClass = 'hangup-button'
|
||||
icon = { this.icon }
|
||||
onClick = { this._onClick } />);
|
||||
return (
|
||||
<ToolbarButton
|
||||
accessibilityLabel = { this.accessibilityLabel }
|
||||
customClass = 'hangup-button'
|
||||
icon = { this.icon }
|
||||
onClick = { this._onClick } />
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import AudioMuteButton from './AudioMuteButton';
|
||||
@@ -9,30 +7,30 @@ import VideoMuteButton from './VideoMuteButton';
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link Toolbar}.
|
||||
*/
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* Additional CSS class names to add to the root of the toolbar.
|
||||
*/
|
||||
className: string,
|
||||
className: string;
|
||||
|
||||
/**
|
||||
* Callback invoked when no longer moused over the toolbar.
|
||||
*/
|
||||
onMouseOut: Function,
|
||||
onMouseOut: (e?: React.MouseEvent) => void;
|
||||
|
||||
/**
|
||||
* Callback invoked when the mouse has moved over the toolbar.
|
||||
*/
|
||||
onMouseOver: Function
|
||||
};
|
||||
onMouseOver: (e?: React.MouseEvent) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the toolbar in the Always On Top window.
|
||||
*
|
||||
* @augments Component
|
||||
*/
|
||||
export default class Toolbar extends Component<Props> {
|
||||
export default class Toolbar extends Component<IProps> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
@@ -2,38 +2,38 @@ import React, { useCallback } from 'react';
|
||||
|
||||
import Icon from '../base/icons/components/Icon';
|
||||
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* Accessibility label for button.
|
||||
*/
|
||||
accessibilityLabel: string,
|
||||
accessibilityLabel: string;
|
||||
|
||||
/**
|
||||
* An extra class name to be added at the end of the element's class name
|
||||
* in order to enable custom styling.
|
||||
*/
|
||||
customClass?: string,
|
||||
customClass?: string;
|
||||
|
||||
/**
|
||||
* Whether or not the button is disabled.
|
||||
*/
|
||||
disabled?: boolean,
|
||||
|
||||
/**
|
||||
* Click handler.
|
||||
*/
|
||||
onClick: Function,
|
||||
disabled?: boolean;
|
||||
|
||||
/**
|
||||
* Button icon.
|
||||
*/
|
||||
icon: Object,
|
||||
icon: Function;
|
||||
|
||||
/**
|
||||
* Click handler.
|
||||
*/
|
||||
onClick: (e?: React.MouseEvent) => void;
|
||||
|
||||
/**
|
||||
* Whether or not the button is toggled.
|
||||
*/
|
||||
toggled?: boolean
|
||||
toggled?: boolean;
|
||||
}
|
||||
|
||||
const ToolbarButton = ({
|
||||
@@ -43,7 +43,7 @@ const ToolbarButton = ({
|
||||
onClick,
|
||||
icon,
|
||||
toggled = false
|
||||
}: Props) => {
|
||||
}: IProps) => {
|
||||
const onKeyPress = useCallback(event => {
|
||||
if (event.key === 'Enter' || event.key === ' ') {
|
||||
event.preventDefault();
|
||||
@@ -1,15 +1,16 @@
|
||||
// @flow
|
||||
import React, { Component } from 'react';
|
||||
|
||||
// We need to reference these files directly to avoid loading things that are not available
|
||||
// in this environment (e.g. JitsiMeetJS or interfaceConfig)
|
||||
import { IconVideo, IconVideoOff } from '../base/icons/svg';
|
||||
import type { Props } from '../base/toolbox/components/AbstractButton';
|
||||
import { IProps } from '../base/toolbox/components/AbstractButton';
|
||||
|
||||
import ToolbarButton from './ToolbarButton';
|
||||
|
||||
const { api } = window.alwaysOnTop;
|
||||
|
||||
type Props = Partial<IProps>;
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link VideoMuteButton}.
|
||||
*/
|
||||
@@ -18,12 +19,12 @@ type State = {
|
||||
/**
|
||||
* Whether video is available is not.
|
||||
*/
|
||||
videoAvailable: boolean,
|
||||
videoAvailable: boolean;
|
||||
|
||||
/**
|
||||
* Whether video is muted or not.
|
||||
*/
|
||||
videoMuted: boolean
|
||||
videoMuted: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -119,40 +120,34 @@ export default class VideoMuteButton extends Component<Props, State> {
|
||||
* Changes the muted state.
|
||||
*
|
||||
* @override
|
||||
* @param {boolean} videoMuted - Whether video should be muted or not.
|
||||
* @param {boolean} _videoMuted - Whether video should be muted or not.
|
||||
* @protected
|
||||
* @returns {void}
|
||||
*/
|
||||
_setVideoMuted(videoMuted: boolean) { // eslint-disable-line no-unused-vars
|
||||
_setVideoMuted(_videoMuted: boolean) {
|
||||
this.state.videoAvailable && api.executeCommand('toggleVideo', false, true);
|
||||
}
|
||||
|
||||
_videoAvailabilityListener: ({ available: boolean }) => void;
|
||||
|
||||
/**
|
||||
* Handles video available api events.
|
||||
*
|
||||
* @param {{ available: boolean }} status - The new available status.
|
||||
* @returns {void}
|
||||
*/
|
||||
_videoAvailabilityListener({ available }) {
|
||||
_videoAvailabilityListener({ available }: { available: boolean; }) {
|
||||
this.setState({ videoAvailable: available });
|
||||
}
|
||||
|
||||
_videoMutedListener: ({ muted: boolean }) => void;
|
||||
|
||||
/**
|
||||
* Handles video muted api events.
|
||||
*
|
||||
* @param {{ muted: boolean }} status - The new muted status.
|
||||
* @returns {void}
|
||||
*/
|
||||
_videoMutedListener({ muted }) {
|
||||
_videoMutedListener({ muted }: { muted: boolean; }) {
|
||||
this.setState({ videoMuted: muted });
|
||||
}
|
||||
|
||||
_onClick: () => {};
|
||||
|
||||
/**
|
||||
* Handles clicking / pressing the button, and toggles the video mute state
|
||||
* accordingly.
|
||||
@@ -173,11 +168,13 @@ export default class VideoMuteButton extends Component<Props, State> {
|
||||
render() {
|
||||
const toggled = this._isVideoMuted();
|
||||
|
||||
return (<ToolbarButton
|
||||
accessibilityLabel = { this.accessibilityLabel }
|
||||
disabled = { this._isDisabled() }
|
||||
icon = { toggled ? this.toggledIcon : this.icon }
|
||||
onClick = { this._onClick }
|
||||
toggled = { toggled } />);
|
||||
return (
|
||||
<ToolbarButton
|
||||
accessibilityLabel = { this.accessibilityLabel }
|
||||
disabled = { this._isDisabled() }
|
||||
icon = { toggled ? this.toggledIcon : this.icon }
|
||||
onClick = { this._onClick }
|
||||
toggled = { toggled } />
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,11 @@
|
||||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import AlwaysOnTop from './AlwaysOnTop';
|
||||
|
||||
// Render the main/root Component.
|
||||
// $FlowExpectedError
|
||||
ReactDOM.render(<AlwaysOnTop />, document.getElementById('react'));
|
||||
|
||||
window.addEventListener(
|
||||
'beforeunload',
|
||||
() => ReactDOM.unmountComponentAtNode(document.getElementById('react')));
|
||||
() => ReactDOM.unmountComponentAtNode(document.getElementById('react') ?? document.body));
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* The type of (redux) action which signals that local media duration has changed.
|
||||
*
|
||||
|
||||
@@ -173,7 +173,15 @@ export function initAnalytics(store: IStore, handlers: Array<Object>) {
|
||||
const { group, server } = state['features/base/jwt'];
|
||||
const { locationURL = { href: '' } } = state['features/base/connection'];
|
||||
const { tenant } = parseURIString(locationURL.href) || {};
|
||||
const permanentProperties: any = {};
|
||||
const permanentProperties: {
|
||||
appName?: string;
|
||||
externalApi?: boolean;
|
||||
group?: string;
|
||||
inIframe?: boolean;
|
||||
server?: string;
|
||||
tenant?: string;
|
||||
websocket?: boolean;
|
||||
} & typeof deploymentInfo = {};
|
||||
|
||||
if (server) {
|
||||
permanentProperties.server = server;
|
||||
@@ -202,7 +210,8 @@ export function initAnalytics(store: IStore, handlers: Array<Object>) {
|
||||
if (deploymentInfo) {
|
||||
for (const key in deploymentInfo) {
|
||||
if (deploymentInfo.hasOwnProperty(key)) {
|
||||
permanentProperties[key] = deploymentInfo[key as keyof typeof deploymentInfo];
|
||||
permanentProperties[key as keyof typeof deploymentInfo] = deploymentInfo[
|
||||
key as keyof typeof deploymentInfo];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -235,7 +244,7 @@ export function initAnalytics(store: IStore, handlers: Array<Object>) {
|
||||
* @returns {Promise} Resolves with the handlers that have been successfully loaded and rejects if there are no handlers
|
||||
* loaded or the analytics is disabled.
|
||||
*/
|
||||
function _loadHandlers(scriptURLs: any[] = [], handlerConstructorOptions: Object) {
|
||||
function _loadHandlers(scriptURLs: string[] = [], handlerConstructorOptions: Object) {
|
||||
const promises: Promise<{ error?: Error; type: string; url?: string; }>[] = [];
|
||||
|
||||
for (const url of scriptURLs) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Amplitude } from '@amplitude/react-native';
|
||||
import DefaultPreference from 'react-native-default-preference';
|
||||
import DeviceInfo from 'react-native-device-info';
|
||||
|
||||
@@ -7,7 +8,7 @@ import DeviceInfo from 'react-native-device-info';
|
||||
* @param {AmplitudeClient} amplitude - The amplitude instance.
|
||||
* @returns {void}
|
||||
*/
|
||||
export async function fixDeviceID(amplitude: any) {
|
||||
export async function fixDeviceID(amplitude: Amplitude) {
|
||||
await DefaultPreference.setName('jitsi-preferences');
|
||||
|
||||
const current = await DefaultPreference.get('amplitudeDeviceId');
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { AmplitudeClient } from 'amplitude-js';
|
||||
|
||||
/**
|
||||
* Custom logic for setting the correct device id.
|
||||
*
|
||||
* @param {AmplitudeClient} _amplitude - The amplitude instance.
|
||||
* @returns {void}
|
||||
*/
|
||||
export function fixDeviceID(_amplitude: any): Promise<any> {
|
||||
export function fixDeviceID(_amplitude: AmplitudeClient): Promise<any> {
|
||||
return new Promise(resolve => resolve(true));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { setRoom } from '../base/conference/actions';
|
||||
import {
|
||||
configWillLoad,
|
||||
@@ -13,6 +12,7 @@ import {
|
||||
import { connect, disconnect, setLocationURL } from '../base/connection/actions';
|
||||
import { loadConfig } from '../base/lib-jitsi-meet/functions.native';
|
||||
import { createDesiredLocalTracks } from '../base/tracks/actions';
|
||||
import isInsecureRoomName from '../base/util/isInsecureRoomName';
|
||||
import { parseURLParams } from '../base/util/parseURLParams';
|
||||
import {
|
||||
appendURLParam,
|
||||
@@ -20,14 +20,11 @@ import {
|
||||
parseURIString,
|
||||
toURLString
|
||||
} from '../base/util/uri';
|
||||
// @ts-ignore
|
||||
import { isPrejoinPageEnabled } from '../mobile/navigation/functions';
|
||||
import {
|
||||
goBackToRoot,
|
||||
navigateRoot
|
||||
// @ts-ignore
|
||||
} from '../mobile/navigation/rootNavigationContainerRef';
|
||||
// @ts-ignore
|
||||
import { screen } from '../mobile/navigation/routes';
|
||||
import { clearNotifications } from '../notifications/actions';
|
||||
|
||||
@@ -55,7 +52,7 @@ export function appNavigate(uri?: string, options: IReloadNowOptions = {}) {
|
||||
|
||||
// If the specified location (URI) does not identify a host, use the app's
|
||||
// default.
|
||||
if (!location || !location.host) {
|
||||
if (!location?.host) {
|
||||
const defaultLocation = parseURIString(getDefaultURL(getState));
|
||||
|
||||
if (location) {
|
||||
@@ -140,10 +137,14 @@ export function appNavigate(uri?: string, options: IReloadNowOptions = {}) {
|
||||
dispatch(setRoom(room));
|
||||
|
||||
if (room) {
|
||||
if (isInsecureRoomName(room)) {
|
||||
navigateRoot(screen.unsafeRoomWarning);
|
||||
|
||||
return;
|
||||
}
|
||||
dispatch(createDesiredLocalTracks());
|
||||
dispatch(clearNotifications());
|
||||
|
||||
// @ts-ignore
|
||||
const { hidePrejoin } = options;
|
||||
|
||||
if (!hidePrejoin && isPrejoinPageEnabled(getState())) {
|
||||
|
||||
@@ -49,7 +49,7 @@ export function appNavigate(uri?: string) {
|
||||
|
||||
// If the specified location (URI) does not identify a host, use the app's
|
||||
// default.
|
||||
if (!location || !location.host) {
|
||||
if (!location?.host) {
|
||||
const defaultLocation = parseURIString(getDefaultURL(getState));
|
||||
|
||||
if (location) {
|
||||
|
||||
@@ -12,7 +12,7 @@ export interface IProps {
|
||||
* XXX Refer to the implementation of loadURLObject: in
|
||||
* ios/sdk/src/JitsiMeetView.m for further information.
|
||||
*/
|
||||
timestamp: any;
|
||||
timestamp: number;
|
||||
|
||||
/**
|
||||
* The URL, if any, with which the app was launched.
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { AtlasKitThemeProvider } from '@atlaskit/theme';
|
||||
import React from 'react';
|
||||
|
||||
import GlobalStyles from '../../base/ui/components/GlobalStyles.web';
|
||||
@@ -43,14 +42,12 @@ export class App extends AbstractApp {
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
_createMainElement(component: React.ComponentType, props: any) {
|
||||
_createMainElement(component: React.ComponentType, props?: Object) {
|
||||
return (
|
||||
<JitsiThemeProvider>
|
||||
<AtlasKitThemeProvider mode = 'dark'>
|
||||
<GlobalStyles />
|
||||
<ChromeExtensionBanner />
|
||||
{ super._createMainElement(component, props) }
|
||||
</AtlasKitThemeProvider>
|
||||
<GlobalStyles />
|
||||
<ChromeExtensionBanner />
|
||||
{ super._createMainElement(component, props) }
|
||||
</JitsiThemeProvider>
|
||||
);
|
||||
}
|
||||
@@ -63,9 +60,7 @@ export class App extends AbstractApp {
|
||||
_renderDialogContainer() {
|
||||
return (
|
||||
<JitsiThemeProvider>
|
||||
<AtlasKitThemeProvider mode = 'dark'>
|
||||
<DialogContainer />
|
||||
</AtlasKitThemeProvider>
|
||||
<DialogContainer />
|
||||
</JitsiThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import { IStateful } from '../base/app/types';
|
||||
import { isRoomValid } from '../base/conference/functions';
|
||||
import { isSupportedBrowser } from '../base/environment/environment';
|
||||
import { toState } from '../base/redux/functions';
|
||||
// eslint-disable-next-line lines-around-comment
|
||||
// @ts-ignore
|
||||
import Conference from '../conference/components/web/Conference';
|
||||
import { getDeepLinkingPage } from '../deep-linking/functions';
|
||||
import UnsupportedDesktopBrowser from '../unsupported-browser/components/UnsupportedDesktopBrowser';
|
||||
|
||||
@@ -5,6 +5,7 @@ import '../base/media/middleware';
|
||||
import '../dynamic-branding/middleware';
|
||||
import '../e2ee/middleware';
|
||||
import '../external-api/middleware';
|
||||
import '../keyboard-shortcuts/middleware';
|
||||
import '../no-audio-signal/middleware';
|
||||
import '../notifications/middleware';
|
||||
import '../noise-detection/middleware';
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import '../analytics/reducer';
|
||||
import '../authentication/reducer';
|
||||
import '../av-moderation/reducer';
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import '../mobile/audio-mode/reducer';
|
||||
import '../mobile/background/reducer';
|
||||
import '../mobile/call-integration/reducer';
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import '../base/devices/reducer';
|
||||
import '../base/premeeting/reducer';
|
||||
import '../base/tooltip/reducer';
|
||||
import '../e2ee/reducer';
|
||||
import '../face-landmarks/reducer';
|
||||
import '../feedback/reducer';
|
||||
import '../keyboard-shortcuts/reducer';
|
||||
import '../no-audio-signal/reducer';
|
||||
import '../noise-detection/reducer';
|
||||
import '../participants-pane/reducer';
|
||||
|
||||
@@ -20,6 +20,7 @@ import { ILoggingState } from '../base/logging/reducer';
|
||||
import { IMediaState } from '../base/media/reducer';
|
||||
import { INetInfoState } from '../base/net-info/reducer';
|
||||
import { IParticipantsState } from '../base/participants/reducer';
|
||||
import { IPreMeetingState } from '../base/premeeting/types';
|
||||
import { IResponsiveUIState } from '../base/responsive-ui/reducer';
|
||||
import { ISettingsState } from '../base/settings/reducer';
|
||||
import { ISoundsState } from '../base/sounds/reducer';
|
||||
@@ -43,6 +44,7 @@ import { IGifsState } from '../gifs/reducer';
|
||||
import { IGoogleApiState } from '../google-api/reducer';
|
||||
import { IInviteState } from '../invite/reducer';
|
||||
import { IJaaSState } from '../jaas/reducer';
|
||||
import { IKeyboardShortcutsState } from '../keyboard-shortcuts/types';
|
||||
import { ILargeVideoState } from '../large-video/reducer';
|
||||
import { ILobbyState } from '../lobby/reducer';
|
||||
import { IMobileAudioModeState } from '../mobile/audio-mode/reducer';
|
||||
@@ -109,6 +111,7 @@ export interface IReduxState {
|
||||
'features/base/net-info': INetInfoState;
|
||||
'features/base/no-src-data': INoSrcDataState;
|
||||
'features/base/participants': IParticipantsState;
|
||||
'features/base/premeeting': IPreMeetingState;
|
||||
'features/base/responsive-ui': IResponsiveUIState;
|
||||
'features/base/settings': ISettingsState;
|
||||
'features/base/sounds': ISoundsState;
|
||||
@@ -133,6 +136,7 @@ export interface IReduxState {
|
||||
'features/google-api': IGoogleApiState;
|
||||
'features/invite': IInviteState;
|
||||
'features/jaas': IJaaSState;
|
||||
'features/keyboard-shortcuts': IKeyboardShortcutsState;
|
||||
'features/large-video': ILargeVideoState;
|
||||
'features/lobby': ILobbyState;
|
||||
'features/mobile/audio-mode': IMobileAudioModeState;
|
||||
|
||||
@@ -27,13 +27,13 @@ export function cancelLogin() {
|
||||
// a reaction to CONNECTION_FAILED). Since the
|
||||
// app/user is going to navigate to WelcomePage, the SDK
|
||||
// clients/consumers need an event.
|
||||
const { error, passwordRequired }
|
||||
const { error = { recoverable: undefined }, passwordRequired }
|
||||
= getState()['features/base/connection'];
|
||||
|
||||
passwordRequired
|
||||
&& dispatch(
|
||||
connectionFailed(
|
||||
passwordRequired, // @ts-ignore
|
||||
passwordRequired,
|
||||
set(error, 'recoverable', false) as any));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
export { default as LoginDialog } from './native/LoginDialog';
|
||||
// eslint-disable-next-line lines-around-comment
|
||||
// @ts-ignore
|
||||
export { default as WaitForOwnerDialog } from './native/WaitForOwnerDialog';
|
||||
|
||||
@@ -203,7 +203,7 @@ class LoginDialog extends Component<IProps, IState> {
|
||||
t
|
||||
} = this.props;
|
||||
const { username, password } = this.state;
|
||||
const messageOptions: any = {};
|
||||
const messageOptions: { msg?: string; } = {};
|
||||
let messageKey;
|
||||
|
||||
if (progress && progress < 1) {
|
||||
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
openLoginDialog,
|
||||
openWaitForOwnerDialog,
|
||||
stopWaitForOwner,
|
||||
waitForOwner } from './actions.native'; // @ts-ignore
|
||||
waitForOwner } from './actions.native';
|
||||
import { LoginDialog, WaitForOwnerDialog } from './components';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* The type of (redux) action which sets the audio-only flag for the current
|
||||
* conference.
|
||||
|
||||
@@ -239,7 +239,7 @@ class Avatar<P extends IProps> extends PureComponent<P, IState> {
|
||||
* @param {boolean} params.dontRetry - If false we will retry to load the Avatar with different CORS mode.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onAvatarLoadError(params: any = {}) {
|
||||
_onAvatarLoadError(params: { dontRetry?: boolean; } = {}) {
|
||||
const { dontRetry = false } = params;
|
||||
|
||||
if (Boolean(this.props.useCORS) === this.state.isUsingCORS && !dontRetry) {
|
||||
|
||||
@@ -88,7 +88,7 @@ class ColorSchemeRegistry {
|
||||
_applyColorScheme(
|
||||
stateful: IStateful,
|
||||
componentName: string,
|
||||
style: StyleType): StyleType {
|
||||
style: StyleType | null): StyleType {
|
||||
let schemedStyle: any;
|
||||
|
||||
if (Array.isArray(style)) {
|
||||
@@ -115,8 +115,8 @@ class ColorSchemeRegistry {
|
||||
// The value is another style object, we apply the same
|
||||
// transformation recursively.
|
||||
schemedStyle[styleName]
|
||||
= this._applyColorScheme( // @ts-ignore
|
||||
stateful, componentName, styleValue);
|
||||
= this._applyColorScheme(
|
||||
stateful, componentName, styleValue as StyleType);
|
||||
} else if (typeof styleValue === 'function') {
|
||||
// The value is a function, which indicates that it's a
|
||||
// dynamic, schemed color we need to resolve.
|
||||
|
||||
@@ -3,6 +3,7 @@ import { sendAnalytics } from '../../analytics/functions';
|
||||
import { appNavigate } from '../../app/actions';
|
||||
import { IReduxState, IStore } from '../../app/types';
|
||||
import { endpointMessageReceived } from '../../subtitles/actions.any';
|
||||
import { iAmVisitor } from '../../visitors/functions';
|
||||
import { getReplaceParticipant } from '../config/functions';
|
||||
import { disconnect } from '../connection/actions';
|
||||
import { JITSI_CONNECTION_CONFERENCE_KEY } from '../connection/constants';
|
||||
@@ -97,34 +98,32 @@ function _addConferenceListeners(conference: IJitsiConference, dispatch: IStore[
|
||||
JitsiConferenceEvents.AUTH_STATUS_CHANGED,
|
||||
(authEnabled: boolean, authLogin: string) => dispatch(authStatusChanged(authEnabled, authLogin)));
|
||||
conference.on(
|
||||
JitsiConferenceEvents.CONFERENCE_FAILED, // @ts-ignore
|
||||
(...args: any[]) => dispatch(conferenceFailed(conference, ...args)));
|
||||
JitsiConferenceEvents.CONFERENCE_FAILED,
|
||||
(err: string, ...args: any[]) => dispatch(conferenceFailed(conference, err, ...args)));
|
||||
conference.on(
|
||||
JitsiConferenceEvents.CONFERENCE_JOINED, // @ts-ignore
|
||||
(...args: any[]) => dispatch(conferenceJoined(conference, ...args)));
|
||||
JitsiConferenceEvents.CONFERENCE_JOINED,
|
||||
(..._args: any[]) => dispatch(conferenceJoined(conference)));
|
||||
conference.on(
|
||||
JitsiConferenceEvents.CONFERENCE_UNIQUE_ID_SET, // @ts-ignore
|
||||
(...args: any[]) => dispatch(conferenceUniqueIdSet(conference, ...args)));
|
||||
JitsiConferenceEvents.CONFERENCE_UNIQUE_ID_SET,
|
||||
(..._args: any[]) => dispatch(conferenceUniqueIdSet(conference)));
|
||||
conference.on(
|
||||
JitsiConferenceEvents.CONFERENCE_JOIN_IN_PROGRESS, // @ts-ignore
|
||||
(...args: any[]) => dispatch(conferenceJoinInProgress(conference, ...args)));
|
||||
JitsiConferenceEvents.CONFERENCE_JOIN_IN_PROGRESS,
|
||||
(..._args: any[]) => dispatch(conferenceJoinInProgress(conference)));
|
||||
conference.on(
|
||||
JitsiConferenceEvents.CONFERENCE_LEFT,
|
||||
(...args: any[]) => {
|
||||
(..._args: any[]) => {
|
||||
dispatch(conferenceTimestampChanged(0));
|
||||
|
||||
// @ts-ignore
|
||||
dispatch(conferenceLeft(conference, ...args));
|
||||
dispatch(conferenceLeft(conference));
|
||||
});
|
||||
conference.on(JitsiConferenceEvents.SUBJECT_CHANGED, // @ts-ignore
|
||||
(...args: any[]) => dispatch(conferenceSubjectChanged(...args)));
|
||||
conference.on(JitsiConferenceEvents.SUBJECT_CHANGED,
|
||||
(subject: string) => dispatch(conferenceSubjectChanged(subject)));
|
||||
|
||||
conference.on(JitsiConferenceEvents.CONFERENCE_CREATED_TIMESTAMP, // @ts-ignore
|
||||
(...args: any[]) => dispatch(conferenceTimestampChanged(...args)));
|
||||
conference.on(JitsiConferenceEvents.CONFERENCE_CREATED_TIMESTAMP,
|
||||
(timestamp: number) => dispatch(conferenceTimestampChanged(timestamp)));
|
||||
|
||||
conference.on(
|
||||
JitsiConferenceEvents.KICKED, // @ts-ignore
|
||||
(...args: any[]) => dispatch(kickedOut(conference, ...args)));
|
||||
JitsiConferenceEvents.KICKED,
|
||||
(participant: any) => dispatch(kickedOut(conference, participant)));
|
||||
|
||||
conference.on(
|
||||
JitsiConferenceEvents.PARTICIPANT_KICKED,
|
||||
@@ -135,8 +134,8 @@ function _addConferenceListeners(conference: IJitsiConference, dispatch: IStore[
|
||||
(jitsiParticipant: IJitsiParticipant) => dispatch(participantSourcesUpdated(jitsiParticipant)));
|
||||
|
||||
conference.on(
|
||||
JitsiConferenceEvents.LOCK_STATE_CHANGED, // @ts-ignore
|
||||
(...args: any[]) => dispatch(lockStateChanged(conference, ...args)));
|
||||
JitsiConferenceEvents.LOCK_STATE_CHANGED,
|
||||
(locked: boolean) => dispatch(lockStateChanged(conference, locked)));
|
||||
|
||||
// Dispatches into features/base/media follow:
|
||||
|
||||
@@ -219,12 +218,12 @@ function _addConferenceListeners(conference: IJitsiConference, dispatch: IStore[
|
||||
});
|
||||
|
||||
conference.on(
|
||||
JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED, // @ts-ignore
|
||||
(...args: any[]) => dispatch(endpointMessageReceived(...args)));
|
||||
JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
|
||||
(participant: Object, json: Object) => dispatch(endpointMessageReceived(participant, json)));
|
||||
|
||||
conference.on(
|
||||
JitsiConferenceEvents.NON_PARTICIPANT_MESSAGE_RECEIVED, // @ts-ignore
|
||||
(...args: any[]) => dispatch(nonParticipantMessageReceived(...args)));
|
||||
JitsiConferenceEvents.NON_PARTICIPANT_MESSAGE_RECEIVED,
|
||||
(id: string, json: Object) => dispatch(nonParticipantMessageReceived(id, json)));
|
||||
|
||||
conference.on(
|
||||
JitsiConferenceEvents.USER_JOINED,
|
||||
@@ -233,15 +232,15 @@ function _addConferenceListeners(conference: IJitsiConference, dispatch: IStore[
|
||||
JitsiConferenceEvents.USER_LEFT,
|
||||
(_id: string, user: any) => commonUserLeftHandling({ dispatch }, conference, user));
|
||||
conference.on(
|
||||
JitsiConferenceEvents.USER_ROLE_CHANGED, // @ts-ignore
|
||||
(...args: any[]) => dispatch(participantRoleChanged(...args)));
|
||||
JitsiConferenceEvents.USER_ROLE_CHANGED,
|
||||
(id: string, role: string) => dispatch(participantRoleChanged(id, role)));
|
||||
conference.on(
|
||||
JitsiConferenceEvents.USER_STATUS_CHANGED, // @ts-ignore
|
||||
(...args: any[]) => dispatch(participantPresenceChanged(...args)));
|
||||
JitsiConferenceEvents.USER_STATUS_CHANGED,
|
||||
(id: string, presence: string) => dispatch(participantPresenceChanged(id, presence)));
|
||||
|
||||
conference.on(
|
||||
JitsiE2ePingEvents.E2E_RTT_CHANGED, // @ts-ignore
|
||||
(...args: any[]) => dispatch(e2eRttChanged(...args)));
|
||||
JitsiE2ePingEvents.E2E_RTT_CHANGED,
|
||||
(participant: Object, rtt: number) => dispatch(e2eRttChanged(participant, rtt)));
|
||||
|
||||
conference.on(
|
||||
JitsiConferenceEvents.BOT_TYPE_CHANGED,
|
||||
@@ -450,11 +449,12 @@ export function conferenceUniqueIdSet(conference: IJitsiConference) {
|
||||
*/
|
||||
export function _conferenceWillJoin(conference: IJitsiConference) {
|
||||
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
const state = getState();
|
||||
const localTracks
|
||||
= getLocalTracks(getState()['features/base/tracks'])
|
||||
= getLocalTracks(state['features/base/tracks'])
|
||||
.map(t => t.jitsiTrack);
|
||||
|
||||
if (localTracks.length) {
|
||||
if (localTracks.length && !iAmVisitor(state)) {
|
||||
_addLocalTracksToConference(conference, localTracks);
|
||||
}
|
||||
|
||||
@@ -631,7 +631,7 @@ export function endConference() {
|
||||
* participant: JitsiParticipant
|
||||
* }}
|
||||
*/
|
||||
export function kickedOut(conference: Object, participant: Object) {
|
||||
export function kickedOut(conference: IJitsiConference, participant: Object) {
|
||||
return {
|
||||
type: KICKED_OUT,
|
||||
conference,
|
||||
@@ -671,7 +671,7 @@ export function leaveConference() {
|
||||
* locked: boolean
|
||||
* }}
|
||||
*/
|
||||
export function lockStateChanged(conference: Object, locked: boolean) {
|
||||
export function lockStateChanged(conference: IJitsiConference, locked: boolean) {
|
||||
return {
|
||||
type: LOCK_STATE_CHANGED,
|
||||
conference,
|
||||
@@ -690,7 +690,7 @@ export function lockStateChanged(conference: Object, locked: boolean) {
|
||||
* json: Object
|
||||
* }}
|
||||
*/
|
||||
export function nonParticipantMessageReceived(id: String, json: Object) {
|
||||
export function nonParticipantMessageReceived(id: string, json: Object) {
|
||||
return {
|
||||
type: NON_PARTICIPANT_MESSAGE_RECEIVED,
|
||||
id,
|
||||
@@ -806,7 +806,7 @@ export function setStartReactionsMuted(muted: boolean, updateBackend = false) {
|
||||
export function setPassword(
|
||||
conference: IJitsiConference | undefined,
|
||||
method: Function | undefined,
|
||||
password: string) {
|
||||
password?: string) {
|
||||
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
if (!conference) {
|
||||
return;
|
||||
|
||||
@@ -159,7 +159,6 @@ export function forEachConference(
|
||||
// Does the value of the base/conference's property look like a
|
||||
// JitsiConference?
|
||||
if (v && typeof v === 'object') {
|
||||
// $FlowFixMe
|
||||
const url: URL = v[JITSI_CONFERENCE_URL_KEY];
|
||||
|
||||
// XXX The Web version of Jitsi Meet does not utilize
|
||||
@@ -293,7 +292,7 @@ export function getVisitorOptions(stateful: IStateful, params: Array<string>) {
|
||||
|
||||
const config = toState(stateful)['features/base/config'];
|
||||
|
||||
if (!config || !config.hosts) {
|
||||
if (!config?.hosts) {
|
||||
logger.warn('Wrong configuration, missing hosts.');
|
||||
|
||||
return;
|
||||
@@ -301,7 +300,8 @@ export function getVisitorOptions(stateful: IStateful, params: Array<string>) {
|
||||
|
||||
if (!vnode) {
|
||||
// this is redirecting back to main, lets restore config
|
||||
// no point of updating disableFocus, we can skip the initial iq to jicofo
|
||||
// not updating disableFocus, as if the room capacity is full the promotion to the main room will fail
|
||||
// and the visitor will be redirected back to a vnode from jicofo
|
||||
if (config.oldConfig && username) {
|
||||
return {
|
||||
hosts: {
|
||||
@@ -309,7 +309,9 @@ export function getVisitorOptions(stateful: IStateful, params: Array<string>) {
|
||||
muc: config.oldConfig.hosts.muc
|
||||
},
|
||||
focusUserJid: focusJid,
|
||||
disableLocalStats: false,
|
||||
bosh: config.oldConfig.bosh && appendURLParam(config.oldConfig.bosh, 'customusername', username),
|
||||
p2p: config.oldConfig.p2p,
|
||||
websocket: config.oldConfig.websocket
|
||||
&& appendURLParam(config.oldConfig.websocket, 'customusername', username),
|
||||
oldConfig: undefined // clears it up
|
||||
@@ -326,6 +328,7 @@ export function getVisitorOptions(stateful: IStateful, params: Array<string>) {
|
||||
},
|
||||
focusUserJid: config.focusUserJid,
|
||||
bosh: config.bosh,
|
||||
p2p: config.p2p,
|
||||
websocket: config.websocket
|
||||
};
|
||||
|
||||
@@ -339,7 +342,12 @@ export function getVisitorOptions(stateful: IStateful, params: Array<string>) {
|
||||
},
|
||||
focusUserJid: focusJid,
|
||||
disableFocus: true, // This flag disables sending the initial conference request
|
||||
disableLocalStats: true,
|
||||
bosh: config.bosh && appendURLParam(config.bosh, 'vnode', vnode),
|
||||
p2p: {
|
||||
...config.p2p,
|
||||
enabled: false
|
||||
},
|
||||
websocket: config.websocket && appendURLParam(config.websocket, 'vnode', vnode)
|
||||
};
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user