mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-01-10 00:30:19 +00:00
Compare commits
31 Commits
7213
...
android-ap
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2521bc67a | ||
|
|
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 |
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ buildscript {
|
||||
ext {
|
||||
buildToolsVersion = "31.0.0"
|
||||
compileSdkVersion = 32
|
||||
minSdkVersion = 23
|
||||
minSdkVersion = 24
|
||||
targetSdkVersion = 32
|
||||
supportLibVersion = "28.0.0"
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -227,11 +226,9 @@ class ReactInstanceManagerHolder {
|
||||
* 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.
|
||||
* @param activity {@code Activity} current running Activity.
|
||||
*/
|
||||
static void initReactInstanceManager(Application app) {
|
||||
static void initReactInstanceManager(Activity activity) {
|
||||
if (reactInstanceManager != null) {
|
||||
return;
|
||||
}
|
||||
@@ -244,34 +241,7 @@ class ReactInstanceManagerHolder {
|
||||
options.videoDecoderFactory = new H264AndSoftwareVideoDecoderFactory(eglContext);
|
||||
options.videoEncoderFactory = new H264AndSoftwareVideoEncoderFactory(eglContext);
|
||||
|
||||
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
|
||||
* time. All {@code ReactRootView} instances will be tied to the one and
|
||||
* only {@code ReactInstanceManager}.
|
||||
*
|
||||
* @param activity {@code Activity} current running Activity.
|
||||
*/
|
||||
static void initReactInstanceManager(Activity activity) {
|
||||
if (reactInstanceManager != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(ReactInstanceManagerHolder.class.getCanonicalName(), "initializing RN with Activity");
|
||||
Log.d(TAG, "initializing RN with Activity");
|
||||
|
||||
reactInstanceManager
|
||||
= ReactInstanceManager.builder()
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
@@ -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';
|
||||
@@ -2308,10 +2309,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'];
|
||||
|
||||
@@ -1406,6 +1406,7 @@ var config = {
|
||||
disableAGC
|
||||
disableAP
|
||||
disableHPF
|
||||
disableLocalStats
|
||||
disableNS
|
||||
enableTalkWhileMuted
|
||||
forceJVB121Ratio
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
a:active {
|
||||
color: black;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-corner {
|
||||
background: #3a3a3a;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -108,6 +108,10 @@
|
||||
#largeVideoContainer {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
#largeVideoWrapper {
|
||||
|
||||
@@ -57,6 +57,10 @@
|
||||
line-height: 24px;
|
||||
border-collapse: collapse;
|
||||
|
||||
* {
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
thead {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
@@ -84,8 +84,12 @@ Component "conference.jitmeet.example.com" "muc"
|
||||
"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
|
||||
|
||||
|
||||
6
globals.d.ts
vendored
6
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;
|
||||
|
||||
|
||||
@@ -424,8 +424,8 @@
|
||||
"tokenAuthFailedTitle": "Нэвтрэлт амжилтгүй",
|
||||
"transcribing": "Орчуулах",
|
||||
"unlockRoom": "$t(lockRoomPassword) уулзалтыг устгана уу",
|
||||
"user": "User",
|
||||
"userIdentifier": "User identifier",
|
||||
"user": "Хэрэглэгч",
|
||||
"userIdentifier": "Хэрэглэгчийн ID",
|
||||
"userPassword": "хэрэглэгчийн нууц үг",
|
||||
"verifyParticipantConfirm": "Нууц үгс хоорондоо тохирч байна",
|
||||
"verifyParticipantDismiss": "Нууц үгс хоорондоо тохирохгүй байна",
|
||||
@@ -451,8 +451,8 @@
|
||||
"bad": "Муу",
|
||||
"detailsLabel": "Энэ талаар илүү дэлгэрэнгүй.",
|
||||
"good": "Сайн",
|
||||
"rateExperience": "Уулзалтын туршлагаа үнэлэх",
|
||||
"star": "Star",
|
||||
"rateExperience": "Уулзалтыг үнэлэх",
|
||||
"star": "Од",
|
||||
"veryBad": "Маш муу",
|
||||
"veryGood": "Маш сайн"
|
||||
},
|
||||
@@ -586,10 +586,10 @@
|
||||
"youtubeTerms": "YouTube үйлчилгээний нөхцөл"
|
||||
},
|
||||
"lobby": {
|
||||
"admit": "O",
|
||||
"admit": "Ok",
|
||||
"admitAll": "Бүгдийг зөвшөөр",
|
||||
"backToKnockModeButton": "Зөвшөөрөл хүсэх",
|
||||
"chat": "Чат",
|
||||
"chat": "Зурвас",
|
||||
"dialogTitle": "Лобби горим",
|
||||
"disableDialogContent": "Лобби горим идэвхитэй байна. Ингэснээр таны уулзалтад зөвшөөрөлгүй хүн орох боломжгүй болдог. Та горимоо идэвхигүй болгохыг хүсч байна уу?",
|
||||
"disableDialogSubmit": "Идэвхигүй болгох",
|
||||
@@ -730,7 +730,7 @@
|
||||
"participantsWantToJoin": "Уулзалтанд орохыг хүсч байна",
|
||||
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) өөр оролцогч устгасан",
|
||||
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) өөр оролцогчоос хийсэн",
|
||||
"raiseHandAction": "Гараа өргө",
|
||||
"raiseHandAction": "Гараа өргөнө үү",
|
||||
"raisedHand": "{{name}} ярихыг хүсч байна.",
|
||||
"raisedHands": "Нэмж {{participantName}} ба {{raisedHands}} хүмүүс",
|
||||
"reactionSounds": "Дууг хаах",
|
||||
@@ -991,14 +991,14 @@
|
||||
"desktopShareWarning": "Шинэ тохиргоог идэвхижүүлэхийн тулд та дэлгэц хуваалцахаа дахин эхлүүлэх шаардлагатай.",
|
||||
"devices": "Төхөөрөмжүүд",
|
||||
"followMe": "Бүгд намайг дагаж байна",
|
||||
"framesPerSecond": "frames-per-second",
|
||||
"framesPerSecond": "fps",
|
||||
"incomingMessage": "Ирсэн мессэж",
|
||||
"language": "Хэл",
|
||||
"loggedIn": "{{name}} нэвтэрсэн",
|
||||
"maxStageParticipants": "Үндсэн тайз руу гарах оролцогчийн хамгийн их тоо(Туршилтынх)",
|
||||
"microphones": "Микрофон",
|
||||
"moderator": "Удирдагч",
|
||||
"moderatorOptions": "Удирдагчийн сонголт",
|
||||
"moderator": "Зохицуулагч",
|
||||
"moderatorOptions": "Зохицуулагчийн сонголт",
|
||||
"more": "Цааш",
|
||||
"name": "Нэр",
|
||||
"noDevice": "Байхгүй",
|
||||
@@ -1006,9 +1006,9 @@
|
||||
"participantJoined": "Оролцогч нэгдсэн",
|
||||
"participantKnocking": "Оролцогчийн орсон лобби",
|
||||
"participantLeft": "Оролцогч гарсан",
|
||||
"playSounds": "Play sound on",
|
||||
"playSounds": "Дууг нээх",
|
||||
"reactions": "Уулзалтын реакциуд",
|
||||
"sameAsSystem": "Same as system ({{label}})",
|
||||
"sameAsSystem": "Системтэй адил({{label}})",
|
||||
"selectAudioOutput": "Дууны гаралт",
|
||||
"selectCamera": "Камер",
|
||||
"selectMic": "Микрофон",
|
||||
@@ -1018,7 +1018,7 @@
|
||||
"startAudioMuted": "Бүгд дуугүй эхлэх",
|
||||
"startReactionsMuted": "Бүх хүн рүү Чимээгүй эмоцийг илгээх",
|
||||
"startVideoMuted": "Бүгдийн дүрс хаах",
|
||||
"talkWhileMuted": "Бусад нь дуугүй үзTalk while muted",
|
||||
"talkWhileMuted": "Нэг нь ярихад бусдын дууг хаах",
|
||||
"title": "Тохиргоо",
|
||||
"video": "Видео"
|
||||
},
|
||||
@@ -1038,7 +1038,7 @@
|
||||
"displayNamePlaceholderText": "Жиш: Б.Болд",
|
||||
"email": "Имэйл",
|
||||
"emailPlaceholderText": "email@example.com",
|
||||
"goTo": "Go to",
|
||||
"goTo": "Шилжих",
|
||||
"header": "Тохиргоо",
|
||||
"help": "Тусламж",
|
||||
"links": "Холбоос",
|
||||
@@ -1070,8 +1070,8 @@
|
||||
"sad": "Баргар",
|
||||
"search": "Хайх",
|
||||
"seconds": "{{count}}сек",
|
||||
"speakerStats": "Яригчийн статистик",
|
||||
"speakerTime": "Яригчийн цаг",
|
||||
"speakerStats": "Оролцогчийн статистик",
|
||||
"speakerTime": "Оролцогчийн ярьсан цаг",
|
||||
"surprised": "Гайхсан"
|
||||
},
|
||||
"startupoverlay": {
|
||||
@@ -1081,13 +1081,13 @@
|
||||
},
|
||||
"suspendedoverlay": {
|
||||
"rejoinKeyTitle": "Дахин нэгдэх",
|
||||
"text": "Дахин холбохын тулд <i>Rejoin</i> товчийг дарна уу.",
|
||||
"text": "Дахин холбохын тулд <i>Дахин нэгдэх</i> товчийг дарна уу.",
|
||||
"title": "Энэ компьютер унтарсан учир таны видео дуудлага тасарлаа."
|
||||
},
|
||||
"termsView": {
|
||||
"title": "Нөхцөл"
|
||||
},
|
||||
"toggleTopPanelLabel": "Toggle top panel",
|
||||
"toggleTopPanelLabel": "Дээд панел идэвхжүүлэх",
|
||||
"toolbar": {
|
||||
"Settings": "Тохиргоо",
|
||||
"accessibilityLabel": {
|
||||
@@ -1109,7 +1109,7 @@
|
||||
"documentClose": "Хуваалцсан баримт хаах",
|
||||
"documentOpen": "Хуваалцсан баримт нээх",
|
||||
"download": "Манай програмуудыг татах",
|
||||
"embedMeeting": "Embed meeting",
|
||||
"embedMeeting": "Уулзалт нэгтгэх",
|
||||
"endConference": "Уулзалтыг нийтээр нь хаах",
|
||||
"enterFullScreen": "Бүтэн дэлгэцээр харах",
|
||||
"enterTileView": "Нүдэн харагдац сонгох",
|
||||
@@ -1118,10 +1118,10 @@
|
||||
"expand": "Сунгах",
|
||||
"feedback": "Санал хүсэлтээ үлдээх",
|
||||
"fullScreen": "Бүтэн дэлгэц",
|
||||
"giphy": "Toggle GIPHY menu",
|
||||
"giphy": "GIPHY цэс идэвхжүүлэх",
|
||||
"grantModerator": "Удирдагчийн эрх баталгаажуулах",
|
||||
"hangup": "Салгах",
|
||||
"heading": "Toolbar",
|
||||
"heading": "Багаж",
|
||||
"help": "Тусламж",
|
||||
"hideWhiteboard": "Самбар нуух",
|
||||
"invite": "Хүмүүсийг урих",
|
||||
@@ -1155,7 +1155,7 @@
|
||||
"remoteVideoMute": "Оролцогчийн камерийг хаах",
|
||||
"security": "Нууцлалын тохиргоо",
|
||||
"selectBackground": "Арын зураг сонгох",
|
||||
"selfView": "Toggle self view",
|
||||
"selfView": "Өөрийн харагдах идэвхжүүлэх",
|
||||
"shareRoom": "Хүн урих",
|
||||
"shareYourScreen": "Дэлгэц хуваалцах",
|
||||
"shareaudio": "Дуугаа хуваалцах",
|
||||
@@ -1190,12 +1190,12 @@
|
||||
"closeParticipantsPane": "Оролцогчийн цонх хаах",
|
||||
"closeReactionsMenu": "Реакци цэс хаах",
|
||||
"disableNoiseSuppression": "Шуугиан дарахыг болиулах",
|
||||
"disableReactionSounds": "Уулзалтын үеэр реакци чимээг хаах болно",
|
||||
"disableReactionSounds": "Уулзалтын үеэр реакцийн чимээг хаах болно",
|
||||
"documentClose": "Хуваалцсан бичиг баримт хаах",
|
||||
"documentOpen": "Хуваалцсан бичиг баримт нээх",
|
||||
"download": "Манай програмуудыг татах",
|
||||
"e2ee": "Бүтэн нууцлал",
|
||||
"embedMeeting": "Embed meeting",
|
||||
"embedMeeting": "Уулзалтыг нэгтгэх",
|
||||
"enableNoiseSuppression": "Шуугиан дарахыг идэвхижүүлэх",
|
||||
"endConference": "Уулзалтыг нийтээр нь хаах",
|
||||
"enterFullScreen": "Бүтэн дэлгэцээр харах",
|
||||
@@ -1218,7 +1218,7 @@
|
||||
"lobbyButtonEnable": "Лобби горим нээх",
|
||||
"login": "Нэвтрэх",
|
||||
"logout": "Гарах",
|
||||
"lowerYourHand": "Гараа болих",
|
||||
"lowerYourHand": "Гараа буулгах",
|
||||
"moreActions": "Бусад үйлдэл",
|
||||
"moreOptions": "Бусад тохиргоо",
|
||||
"mute": "Дуу хаах/нээх",
|
||||
@@ -1238,14 +1238,14 @@
|
||||
"pip": "Зураг-зураг горим оруулах",
|
||||
"privateMessage": "Хувийн зурвас илгээх",
|
||||
"profile": "Профайлаа засна уу",
|
||||
"raiseHand": "Гараа өргөх/болих",
|
||||
"raiseYourHand": "Гараа өргө",
|
||||
"reactionBoo": "Boo reaction",
|
||||
"reactionClap": "Send clap reaction",
|
||||
"reactionLaugh": "Send laugh reaction",
|
||||
"reactionLike": "Send thumbs up reaction",
|
||||
"reactionSilence": "Send silence reaction",
|
||||
"reactionSurprised": "Send surprised reaction",
|
||||
"raiseHand": "Гараа өргөх/буулгах",
|
||||
"raiseYourHand": "Гараа өргөх",
|
||||
"reactionBoo": "Boo реакци илгээх",
|
||||
"reactionClap": "Алга таших реакци илгээх",
|
||||
"reactionLaugh": "Инээх реакци илгээх",
|
||||
"reactionLike": "Таалагдсан реакци илгээх",
|
||||
"reactionSilence": "Чимээгүй реакци илгээх",
|
||||
"reactionSurprised": "Гайхсан реакци илгээх",
|
||||
"security": "Нууцлалын тохиргоо",
|
||||
"selectBackground": "Арын зураг сонгох",
|
||||
"shareRoom": "Хэн нэгнийг урих",
|
||||
@@ -1349,7 +1349,7 @@
|
||||
"remoteControl": "Алсын удирдлагыг эхлүүлэх / зогсоох",
|
||||
"screenSharing": "Оролцогч дэлгэцээ хуваалцаж байна",
|
||||
"show": "Үзүүлэх",
|
||||
"showSelfView": "Show self view",
|
||||
"showSelfView": "Өөрийн харагдац харуулах",
|
||||
"unpinFromStage": "Онцлохоо болих",
|
||||
"verify": "Оролцогчийг баталгаажуулах",
|
||||
"videoMuted": "Камер идэвхигүй болсон",
|
||||
@@ -1361,8 +1361,8 @@
|
||||
"backgroundEffectError": "Арын зургийг идэвхижүүлэхэд алдаа гарлаа.",
|
||||
"blur": "Бүдгэрүүлэх",
|
||||
"deleteImage": "Зураг устгах",
|
||||
"desktopShare": "Desktop share",
|
||||
"desktopShareError": "Could not create desktop share",
|
||||
"desktopShare": "Дэлгэцээ хуваалцах",
|
||||
"desktopShareError": "Дэлгэц хуваалцахад алдаа гарлаа",
|
||||
"image1": "Beach",
|
||||
"image2": "White neutral wall",
|
||||
"image3": "White empty room",
|
||||
@@ -1377,7 +1377,7 @@
|
||||
"title": "Виртуал бүдгэрүүлэлт",
|
||||
"uploadedImage": "Оруулсан зураг {{index}}",
|
||||
"webAssemblyWarning": "WebAssembly-г дэмждэггүй",
|
||||
"webAssemblyWarningDescription": "WebAssembly disabled or not supported by this browser"
|
||||
"webAssemblyWarningDescription": "Энэ хөтөч WebAssembly-г дэмждэггүй"
|
||||
},
|
||||
"visitors": {
|
||||
"chatIndicator": "(visitor)",
|
||||
@@ -1406,13 +1406,13 @@
|
||||
"getHelp": "Тусламж авах",
|
||||
"go": "OK",
|
||||
"goSmall": "OK",
|
||||
"headerSubtitle": "Secure and high quality meetings",
|
||||
"headerSubtitle": "Найдвартай, чанартай цахим уулзалт",
|
||||
"headerTitle": "Jitsi Meet",
|
||||
"info": "Мэдээлэл",
|
||||
"jitsiOnMobile": "Jitsi on mobile – download our apps and start a meeting from anywhere",
|
||||
"jitsiOnMobile": "Jitsi on mobile – бидний аппыг татаад уулзалтанд хаанаас ч оролцоорой.",
|
||||
"join": "ҮҮСГЭХ / НЭГДЭХ",
|
||||
"logo": {
|
||||
"calendar": "Calendar лого",
|
||||
"calendar": "Хуанли лого",
|
||||
"desktopPreviewThumbnail": "Desktop preview thumbnail",
|
||||
"googleLogo": "Google лого",
|
||||
"logoDeepLinking": "Jitsi meet лого",
|
||||
@@ -1423,7 +1423,7 @@
|
||||
"mobileDownLoadLinkAndroid": "Android апп татах",
|
||||
"mobileDownLoadLinkFDroid": "F-Droid апп татах",
|
||||
"mobileDownLoadLinkIos": "iOS апп татах",
|
||||
"moderatedMessage": "Or <a href=\"{{url}}\" rel=\"noopener noreferrer\" target=\"_blank\">book a meeting URL</a> in advance where you are the only moderator.",
|
||||
"moderatedMessage": "Эсвэл та энэ уулзалтын ганц зохицуулагч бол <a href=\"{{url}}\" rel=\"noopener noreferrer\" target=\"_blank\"> уулзалтын URL-г</a> хадгалаарай.",
|
||||
"privacy": "Нууцлал",
|
||||
"recentList": "Онцлох",
|
||||
"recentListDelete": "Устгах",
|
||||
@@ -1436,7 +1436,7 @@
|
||||
"sendFeedback": "Санал илгээх",
|
||||
"settings": "Тохиргоо",
|
||||
"startMeeting": "Уулзалт эхлүүлэх",
|
||||
"terms": "Нөхцөлүүд",
|
||||
"terms": "Нөхцлүүд",
|
||||
"title": "Аюулгүй, үнэгүй видео уулзалт хийх боломжтой",
|
||||
"upcomingMeetings": "Таны дараагийн уулзалтууд"
|
||||
},
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -115,7 +115,11 @@ import { muteAllParticipants } from '../../react/features/video-menu/actions';
|
||||
import { setVideoQuality } from '../../react/features/video-quality/actions';
|
||||
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);
|
||||
|
||||
@@ -310,6 +314,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');
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
1
modules/API/external/external_api.js
vendored
1
modules/API/external/external_api.js
vendored
@@ -59,6 +59,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',
|
||||
|
||||
@@ -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,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;
|
||||
79
package-lock.json
generated
79
package-lock.json
generated
@@ -60,7 +60,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/v1620.0.0+7f0012f7/lib-jitsi-meet.tgz",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1626.0.0+a41aa571/lib-jitsi-meet.tgz",
|
||||
"lodash": "4.17.21",
|
||||
"moment": "2.29.4",
|
||||
"moment-duration-format": "2.2.2",
|
||||
@@ -130,10 +130,12 @@
|
||||
"@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-video": "5.0.14",
|
||||
"@types/react-redux": "7.1.24",
|
||||
"@types/react-window": "1.8.5",
|
||||
"@types/resemblejs": "^4.1.0",
|
||||
@@ -5761,6 +5763,12 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
|
||||
},
|
||||
"node_modules/@types/punycode": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/punycode/-/punycode-2.1.0.tgz",
|
||||
"integrity": "sha512-PG5aLpW6PJOeV2fHRslP4IOMWn+G+Uq8CfnyJ+PDS8ndCbU+soO+fB3NKCKo0p/Jh2Y4aPaiQZsrOXFdzpcA6g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/qs": {
|
||||
"version": "6.9.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
|
||||
@@ -5818,6 +5826,16 @@
|
||||
"@types/react": "^17"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-native-video": {
|
||||
"version": "5.0.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-native-video/-/react-native-video-5.0.14.tgz",
|
||||
"integrity": "sha512-KdcyY4HY/Q1l6f5qQA337BNVN+GsdZy836j9CXbWHZ008VVNzSlnJypJQPsnUgI0EPBw/uG/lyJk6cg9Jj1syg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-redux": {
|
||||
"version": "7.1.24",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.24.tgz",
|
||||
@@ -12721,8 +12739,8 @@
|
||||
},
|
||||
"node_modules/lib-jitsi-meet": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1620.0.0+7f0012f7/lib-jitsi-meet.tgz",
|
||||
"integrity": "sha512-F3vOUwD/ys5dGtswR3C5IK8JPDOG+71J+nhkEDLotkni/Zws8KHzf8Ye332UuetUjCTGJP3CbRFe9yJdYERe7g==",
|
||||
"resolved": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1626.0.0+a41aa571/lib-jitsi-meet.tgz",
|
||||
"integrity": "sha512-0LK5EMCvtsAEQkjkrWzyniTl8BKtshAZxI3e9hGnA/RVDuULLXre7GEWd2zCP3tCfdxclkhqt7skQpfNhCTdqg==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
@@ -12740,7 +12758,7 @@
|
||||
"patch-package": "6.5.1",
|
||||
"promise.allsettled": "1.0.4",
|
||||
"sdp-transform": "2.3.0",
|
||||
"strophe.js": "1.6.0",
|
||||
"strophe.js": "1.5.0",
|
||||
"strophejs-plugin-disco": "0.0.2",
|
||||
"strophejs-plugin-stream-management": "git+https://github.com/jitsi/strophejs-plugin-stream-management#679be5902097ed612fb5062b5549f3f32b6f5f47",
|
||||
"uuid": "8.1.0",
|
||||
@@ -17597,18 +17615,27 @@
|
||||
}
|
||||
},
|
||||
"node_modules/strophe.js": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/strophe.js/-/strophe.js-1.6.0.tgz",
|
||||
"integrity": "sha512-LE2B6nEJNUbF2Cl/p1tLIsXVJ9l86B/Z12HYYiO3n92VwYkhJ/5vJ+1ZMdwP9eN9GP8a3nbqfS5zE9umcK0FdA==",
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/strophe.js/-/strophe.js-1.5.0.tgz",
|
||||
"integrity": "sha512-H5tE/tZxPR5xP3jhXyQwsjnMSwQMf7vrn9r1OkufTApyGHYe8WjzhsfxtL3AFhVu7vFjXPPZBrmUOTm1ccYgOA==",
|
||||
"dependencies": {
|
||||
"abab": "^2.0.3",
|
||||
"karma-rollup-preprocessor": "^7.0.8"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@xmldom/xmldom": "0.8.3",
|
||||
"@xmldom/xmldom": "0.8.2",
|
||||
"ws": "^8.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/strophe.js/node_modules/@xmldom/xmldom": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.2.tgz",
|
||||
"integrity": "sha512-+R0juSseERyoPvnBQ/cZih6bpF7IpCXlWbHRoCRzYzqpz6gWHOgf8o4MOEf6KBVuOyqU+gCNLkCWVIJAro8XyQ==",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/strophe.js/node_modules/ws": {
|
||||
"version": "8.13.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
||||
@@ -23792,6 +23819,12 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
|
||||
},
|
||||
"@types/punycode": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/punycode/-/punycode-2.1.0.tgz",
|
||||
"integrity": "sha512-PG5aLpW6PJOeV2fHRslP4IOMWn+G+Uq8CfnyJ+PDS8ndCbU+soO+fB3NKCKo0p/Jh2Y4aPaiQZsrOXFdzpcA6g==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/qs": {
|
||||
"version": "6.9.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
|
||||
@@ -23849,6 +23882,16 @@
|
||||
"@types/react": "^17"
|
||||
}
|
||||
},
|
||||
"@types/react-native-video": {
|
||||
"version": "5.0.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-native-video/-/react-native-video-5.0.14.tgz",
|
||||
"integrity": "sha512-KdcyY4HY/Q1l6f5qQA337BNVN+GsdZy836j9CXbWHZ008VVNzSlnJypJQPsnUgI0EPBw/uG/lyJk6cg9Jj1syg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*",
|
||||
"@types/react-native": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-redux": {
|
||||
"version": "7.1.24",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.24.tgz",
|
||||
@@ -29074,8 +29117,8 @@
|
||||
}
|
||||
},
|
||||
"lib-jitsi-meet": {
|
||||
"version": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1620.0.0+7f0012f7/lib-jitsi-meet.tgz",
|
||||
"integrity": "sha512-F3vOUwD/ys5dGtswR3C5IK8JPDOG+71J+nhkEDLotkni/Zws8KHzf8Ye332UuetUjCTGJP3CbRFe9yJdYERe7g==",
|
||||
"version": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1626.0.0+a41aa571/lib-jitsi-meet.tgz",
|
||||
"integrity": "sha512-0LK5EMCvtsAEQkjkrWzyniTl8BKtshAZxI3e9hGnA/RVDuULLXre7GEWd2zCP3tCfdxclkhqt7skQpfNhCTdqg==",
|
||||
"requires": {
|
||||
"@jitsi/js-utils": "2.0.0",
|
||||
"@jitsi/logger": "2.0.0",
|
||||
@@ -29091,7 +29134,7 @@
|
||||
"patch-package": "6.5.1",
|
||||
"promise.allsettled": "1.0.4",
|
||||
"sdp-transform": "2.3.0",
|
||||
"strophe.js": "1.6.0",
|
||||
"strophe.js": "1.5.0",
|
||||
"strophejs-plugin-disco": "0.0.2",
|
||||
"strophejs-plugin-stream-management": "git+https://github.com/jitsi/strophejs-plugin-stream-management#679be5902097ed612fb5062b5549f3f32b6f5f47",
|
||||
"uuid": "8.1.0",
|
||||
@@ -32802,16 +32845,22 @@
|
||||
"dev": true
|
||||
},
|
||||
"strophe.js": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/strophe.js/-/strophe.js-1.6.0.tgz",
|
||||
"integrity": "sha512-LE2B6nEJNUbF2Cl/p1tLIsXVJ9l86B/Z12HYYiO3n92VwYkhJ/5vJ+1ZMdwP9eN9GP8a3nbqfS5zE9umcK0FdA==",
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/strophe.js/-/strophe.js-1.5.0.tgz",
|
||||
"integrity": "sha512-H5tE/tZxPR5xP3jhXyQwsjnMSwQMf7vrn9r1OkufTApyGHYe8WjzhsfxtL3AFhVu7vFjXPPZBrmUOTm1ccYgOA==",
|
||||
"requires": {
|
||||
"@xmldom/xmldom": "0.8.7",
|
||||
"@xmldom/xmldom": "0.8.2",
|
||||
"abab": "^2.0.3",
|
||||
"karma-rollup-preprocessor": "^7.0.8",
|
||||
"ws": "^8.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@xmldom/xmldom": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.2.tgz",
|
||||
"integrity": "sha512-+R0juSseERyoPvnBQ/cZih6bpF7IpCXlWbHRoCRzYzqpz6gWHOgf8o4MOEf6KBVuOyqU+gCNLkCWVIJAro8XyQ==",
|
||||
"optional": true
|
||||
},
|
||||
"ws": {
|
||||
"version": "8.13.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
||||
|
||||
@@ -65,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/v1620.0.0+7f0012f7/lib-jitsi-meet.tgz",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1626.0.0+a41aa571/lib-jitsi-meet.tgz",
|
||||
"lodash": "4.17.21",
|
||||
"moment": "2.29.4",
|
||||
"moment-duration-format": "2.2.2",
|
||||
@@ -135,10 +135,12 @@
|
||||
"@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-video": "5.0.14",
|
||||
"@types/react-redux": "7.1.24",
|
||||
"@types/react-window": "1.8.5",
|
||||
"@types/resemblejs": "^4.1.0",
|
||||
@@ -178,7 +180,7 @@
|
||||
},
|
||||
"overrides": {
|
||||
"strophe.js@1.6.0": {
|
||||
"@xmldom/xmldom": "0.8.7"
|
||||
"@xmldom/xmldom": "0.8.7"
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* The type of (redux) action which signals that local media duration has changed.
|
||||
*
|
||||
|
||||
@@ -129,14 +129,6 @@ export function appNavigate(uri?: string) {
|
||||
|
||||
dispatch(setLocationURL(locationURL));
|
||||
dispatch(setConfig(config));
|
||||
|
||||
if (inIframe() && getState()['features/base/config'].disableIframeAPI) {
|
||||
// in case iframeAPI is disabled redirect to the promotional page
|
||||
dispatch(redirectToStaticPage('static/close3.html', `#jitsi_meet_external_api_id=${API_ID}`));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(setRoom(room));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -3,6 +3,7 @@ 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';
|
||||
|
||||
@@ -43,6 +43,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';
|
||||
@@ -133,6 +134,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;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* The type of (redux) action which sets the audio-only flag for the current
|
||||
* conference.
|
||||
|
||||
@@ -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';
|
||||
@@ -450,11 +451,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);
|
||||
}
|
||||
|
||||
@@ -806,7 +808,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
|
||||
@@ -309,6 +308,7 @@ 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),
|
||||
websocket: config.oldConfig.websocket
|
||||
&& appendURLParam(config.oldConfig.websocket, 'customusername', username),
|
||||
@@ -339,6 +339,7 @@ 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),
|
||||
websocket: config.websocket && appendURLParam(config.websocket, 'vnode', vnode)
|
||||
};
|
||||
|
||||
@@ -104,6 +104,7 @@ export interface IJitsiConference {
|
||||
sendTextMessage: Function;
|
||||
sendTones: Function;
|
||||
sessionId: string;
|
||||
setAssumedBandwidthBps: (value: number) => void;
|
||||
setDesktopSharingFrameRate: Function;
|
||||
setDisplayName: Function;
|
||||
setLocalParticipantProperty: Function;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* The type of (redux) action which signals that a connection disconnected.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@ interface IProps extends AbstractProps, WithTranslation {
|
||||
/**
|
||||
* The i18n key of the text label for the cancel button.
|
||||
*/
|
||||
cancelLabel: string;
|
||||
cancelLabel?: string;
|
||||
|
||||
/**
|
||||
* The React {@code Component} children.
|
||||
@@ -29,7 +29,7 @@ interface IProps extends AbstractProps, WithTranslation {
|
||||
/**
|
||||
* The i18n key of the text label for the confirm button.
|
||||
*/
|
||||
confirmLabel: string;
|
||||
confirmLabel?: string;
|
||||
|
||||
/**
|
||||
* Dialog description key for translations.
|
||||
|
||||
@@ -30,12 +30,12 @@ export type DialogProps = {
|
||||
/**
|
||||
* The handler for onCancel event.
|
||||
*/
|
||||
onCancel: Function;
|
||||
onCancel?: Function;
|
||||
|
||||
/**
|
||||
* The handler for the event when submitting the dialog.
|
||||
*/
|
||||
onSubmit: Function;
|
||||
onSubmit?: Function;
|
||||
|
||||
/**
|
||||
* Additional style to be applied on the dialog.
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* Flag indicating if add-people functionality should be enabled.
|
||||
* Default: enabled (true).
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* The type of (redux) action which signals that i18next has been initialized.
|
||||
*/
|
||||
|
||||
@@ -90,7 +90,7 @@ interface IProps extends IIconProps {
|
||||
/**
|
||||
* Style object to be applied.
|
||||
*/
|
||||
style?: StyleType;
|
||||
style?: StyleType | StyleType[];
|
||||
|
||||
/**
|
||||
* TabIndex for the Icon.
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* The type of (redux) action to add known domains to the list of domains known
|
||||
* to the feature base/known-domains.
|
||||
|
||||
@@ -29,7 +29,7 @@ interface IState {
|
||||
* A react {@code Component} that implements an expanded label as tooltip-like
|
||||
* component to explain the meaning of the {@code Label}.
|
||||
*/
|
||||
export default class ExpandedLabel<P extends IProps> extends Component<P, IState> {
|
||||
export default abstract class ExpandedLabel<P extends IProps> extends Component<P, IState> {
|
||||
/**
|
||||
* Instantiates a new {@code ExpandedLabel} instance.
|
||||
*
|
||||
@@ -85,7 +85,7 @@ export default class ExpandedLabel<P extends IProps> extends Component<P, IState
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
_getLabel: () => string;
|
||||
abstract _getLabel(): string;
|
||||
|
||||
/**
|
||||
* Defines the color of the expanded label. This function returns a default
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* The type of (redux) action which sets the last-n for the conference.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useHeaderHeight } from '@react-navigation/elements';
|
||||
import React, { ReactElement, useCallback, useEffect, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import {
|
||||
Keyboard,
|
||||
KeyboardAvoidingView,
|
||||
@@ -8,44 +8,44 @@ import {
|
||||
} from 'react-native';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
|
||||
import { StyleType } from '../../styles';
|
||||
import { StyleType } from '../../styles/functions.any';
|
||||
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* Adds bottom padding.
|
||||
*/
|
||||
addBottomPadding?: boolean,
|
||||
addBottomPadding?: boolean;
|
||||
|
||||
/**
|
||||
* The children component(s) of the Modal, to be rendered.
|
||||
*/
|
||||
children: ReactElement,
|
||||
children: React.ReactNode;
|
||||
|
||||
/**
|
||||
* Additional style to be appended to the KeyboardAvoidingView content container.
|
||||
*/
|
||||
contentContainerStyle?: StyleType,
|
||||
contentContainerStyle?: StyleType;
|
||||
|
||||
/**
|
||||
* Disable forced keyboard dismiss?
|
||||
*/
|
||||
disableForcedKeyboardDismiss?: boolean,
|
||||
disableForcedKeyboardDismiss?: boolean;
|
||||
|
||||
/**
|
||||
* Is a text input rendered at the bottom of the screen?
|
||||
*/
|
||||
hasBottomTextInput: boolean,
|
||||
hasBottomTextInput: boolean;
|
||||
|
||||
/**
|
||||
* Is the screen rendering a tab navigator?
|
||||
*/
|
||||
hasTabNavigator: boolean,
|
||||
hasTabNavigator: boolean;
|
||||
|
||||
/**
|
||||
* Additional style to be appended to the KeyboardAvoidingView.
|
||||
*/
|
||||
style?: StyleType
|
||||
style?: StyleType;
|
||||
}
|
||||
|
||||
const JitsiKeyboardAvoidingView = (
|
||||
@@ -57,7 +57,7 @@ const JitsiKeyboardAvoidingView = (
|
||||
hasTabNavigator,
|
||||
hasBottomTextInput,
|
||||
style
|
||||
}: Props) => {
|
||||
}: IProps) => {
|
||||
const headerHeight = useHeaderHeight();
|
||||
const insets = useSafeAreaInsets();
|
||||
const [ bottomPadding, setBottomPadding ] = useState(insets.bottom);
|
||||
@@ -77,11 +77,11 @@ const JitsiKeyboardAvoidingView = (
|
||||
const iosVerticalOffset
|
||||
= headerHeight + noNotchDevicePadding + tabNavigatorPadding;
|
||||
const androidVerticalOffset = hasBottomTextInput
|
||||
? headerHeight + StatusBar.currentHeight : headerHeight;
|
||||
? headerHeight + Number(StatusBar.currentHeight) : headerHeight;
|
||||
|
||||
// Tells the view what to do with taps
|
||||
const shouldSetResponse = useCallback(() => !disableForcedKeyboardDismiss);
|
||||
const onRelease = useCallback(() => Keyboard.dismiss());
|
||||
const shouldSetResponse = useCallback(() => !disableForcedKeyboardDismiss, []);
|
||||
const onRelease = useCallback(() => Keyboard.dismiss(), []);
|
||||
|
||||
return (
|
||||
<KeyboardAvoidingView
|
||||
@@ -1,59 +1,58 @@
|
||||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { Edge, SafeAreaView } from 'react-native-safe-area-context';
|
||||
|
||||
import { StyleType } from '../../styles';
|
||||
import { StyleType } from '../../styles/functions.any';
|
||||
|
||||
import JitsiKeyboardAvoidingView from './JitsiKeyboardAvoidingView';
|
||||
import styles from './styles';
|
||||
|
||||
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* Adds bottom padding.
|
||||
*/
|
||||
addBottomPadding?: boolean,
|
||||
|
||||
/**
|
||||
* Additional style to be appended to the KeyboardAvoidingView content container.
|
||||
*/
|
||||
contentContainerStyle?: StyleType,
|
||||
addBottomPadding?: boolean;
|
||||
|
||||
/**
|
||||
* The children component(s) of the Modal, to be rendered.
|
||||
*/
|
||||
children: React.ReactNode,
|
||||
children: React.ReactNode;
|
||||
|
||||
/**
|
||||
* Additional style to be appended to the KeyboardAvoidingView content container.
|
||||
*/
|
||||
contentContainerStyle?: StyleType;
|
||||
|
||||
/**
|
||||
* Disabled forced keyboard dismiss?
|
||||
*/
|
||||
disableForcedKeyboardDismiss?: boolean,
|
||||
disableForcedKeyboardDismiss?: boolean;
|
||||
|
||||
/**
|
||||
* Optional function that renders a footer component, if needed.
|
||||
*/
|
||||
footerComponent?: Function,
|
||||
footerComponent?: Function;
|
||||
|
||||
/**
|
||||
* Is a text input rendered at the bottom of the screen?
|
||||
*/
|
||||
hasBottomTextInput?: boolean,
|
||||
hasBottomTextInput?: boolean;
|
||||
|
||||
/**
|
||||
* Is the screen rendering a tab navigator?
|
||||
*/
|
||||
hasTabNavigator?: boolean,
|
||||
hasTabNavigator?: boolean;
|
||||
|
||||
/**
|
||||
* Insets for the SafeAreaView.
|
||||
*/
|
||||
safeAreaInsets?: Array,
|
||||
safeAreaInsets?: Edge[];
|
||||
|
||||
/**
|
||||
* Additional style to be appended to the KeyboardAvoidingView containing the content of the modal.
|
||||
*/
|
||||
style?: StyleType
|
||||
style?: StyleType;
|
||||
}
|
||||
|
||||
const JitsiScreen = ({
|
||||
@@ -66,7 +65,7 @@ const JitsiScreen = ({
|
||||
hasBottomTextInput = false,
|
||||
safeAreaInsets = [ 'left', 'right' ],
|
||||
style
|
||||
}: Props) => {
|
||||
}: IProps) => {
|
||||
const renderContent = () => (
|
||||
<JitsiKeyboardAvoidingView
|
||||
addBottomPadding = { addBottomPadding }
|
||||
@@ -80,7 +79,7 @@ const JitsiScreen = ({
|
||||
style = { styles.safeArea }>
|
||||
{ children }
|
||||
</SafeAreaView>
|
||||
{ footerComponent && footerComponent() }
|
||||
{ footerComponent?.() }
|
||||
</JitsiKeyboardAvoidingView>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// @flow
|
||||
|
||||
import { IStateful } from '../../app/types';
|
||||
import { toState } from '../../redux/functions';
|
||||
|
||||
/**
|
||||
@@ -11,7 +10,7 @@ import { toState } from '../../redux/functions';
|
||||
* features/base/config.
|
||||
* @returns {number}.
|
||||
*/
|
||||
export function getClientWidth(stateful: Object) {
|
||||
export function getClientWidth(stateful: IStateful) {
|
||||
const state = toState(stateful)['features/base/responsive-ui'];
|
||||
|
||||
return state.clientWidth;
|
||||
@@ -26,7 +25,7 @@ export function getClientWidth(stateful: Object) {
|
||||
* features/base/config.
|
||||
* @returns {number}.
|
||||
*/
|
||||
export function getClientHeight(stateful: Object) {
|
||||
export function getClientHeight(stateful: IStateful) {
|
||||
const state = toState(stateful)['features/base/responsive-ui'];
|
||||
|
||||
return state.clientHeight;
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* Create an action for when dominant speaker changes.
|
||||
*
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
import { GestureResponderEvent, Text, TextStyle, View, ViewStyle } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import {
|
||||
isTrackStreamingStatusActive,
|
||||
isTrackStreamingStatusInactive
|
||||
} from '../../../connection-indicator/functions';
|
||||
import SharedVideo from '../../../shared-video/components/native/SharedVideo';
|
||||
import { IStateful } from '../../app/types';
|
||||
import Avatar from '../../avatar/components/Avatar';
|
||||
import { translate } from '../../i18n/functions';
|
||||
import VideoTrack from '../../media/components/native/VideoTrack';
|
||||
import { shouldRenderVideoTrack } from '../../media/functions';
|
||||
import Container from '../../react/components/native/Container';
|
||||
import { toState } from '../../redux/functions';
|
||||
import { StyleType } from '../../styles/functions.any';
|
||||
import TestHint from '../../testing/components/TestHint';
|
||||
import { getVideoTrackByParticipant } from '../../tracks/functions';
|
||||
import { ITrack } from '../../tracks/types';
|
||||
import { getParticipantById, getParticipantDisplayName, isSharedVideoParticipant } from '../functions';
|
||||
|
||||
import styles from './styles';
|
||||
@@ -22,69 +26,69 @@ import styles from './styles';
|
||||
/**
|
||||
* The type of the React {@link Component} props of {@link ParticipantView}.
|
||||
*/
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* Whether the connection is inactive or not.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_isConnectionInactive: boolean,
|
||||
_isConnectionInactive: boolean;
|
||||
|
||||
/**
|
||||
* Whether the participant is a shared video participant.
|
||||
*/
|
||||
_isSharedVideoParticipant: boolean,
|
||||
_isSharedVideoParticipant: boolean;
|
||||
|
||||
/**
|
||||
* The name of the participant which this component represents.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_participantName: string,
|
||||
_participantName: string;
|
||||
|
||||
/**
|
||||
* True if the video should be rendered, false otherwise.
|
||||
*/
|
||||
_renderVideo: boolean,
|
||||
_renderVideo: boolean;
|
||||
|
||||
/**
|
||||
* The video Track of the participant with {@link #participantId}.
|
||||
*/
|
||||
_videoTrack: Object,
|
||||
_videoTrack?: ITrack;
|
||||
|
||||
/**
|
||||
* The avatar size.
|
||||
*/
|
||||
avatarSize: number,
|
||||
avatarSize: number;
|
||||
|
||||
/**
|
||||
* Whether video should be disabled for his view.
|
||||
*/
|
||||
disableVideo: ?boolean,
|
||||
disableVideo?: boolean;
|
||||
|
||||
/**
|
||||
* Callback to invoke when the {@code ParticipantView} is clicked/pressed.
|
||||
*/
|
||||
onPress: Function,
|
||||
onPress: (e?: GestureResponderEvent) => void;
|
||||
|
||||
/**
|
||||
* The ID of the participant (to be) depicted by {@link ParticipantView}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
participantId: string,
|
||||
participantId: string;
|
||||
|
||||
/**
|
||||
* The style, if any, to apply to {@link ParticipantView} in addition to its
|
||||
* default style.
|
||||
*/
|
||||
style: Object,
|
||||
style: StyleType;
|
||||
|
||||
/**
|
||||
* The function to translate human-readable text.
|
||||
*/
|
||||
t: Function,
|
||||
t: Function;
|
||||
|
||||
/**
|
||||
* The test hint id which can be used to locate the {@code ParticipantView}
|
||||
@@ -92,26 +96,26 @@ type Props = {
|
||||
* {@code participantId} with the following format will be used:
|
||||
* {@code `org.jitsi.meet.Participant#${participantId}`}.
|
||||
*/
|
||||
testHintId: ?string,
|
||||
testHintId?: string;
|
||||
|
||||
/**
|
||||
* Indicates if the connectivity info label should be shown, if appropriate.
|
||||
* It will be shown in case the connection is interrupted.
|
||||
*/
|
||||
useConnectivityInfoLabel: boolean,
|
||||
useConnectivityInfoLabel: boolean;
|
||||
|
||||
/**
|
||||
* The z-order of the {@link Video} of {@link ParticipantView} in the
|
||||
* stacking space of all {@code Video}s. For more details, refer to the
|
||||
* {@code zOrder} property of the {@code Video} class for React Native.
|
||||
*/
|
||||
zOrder: number,
|
||||
zOrder: number;
|
||||
|
||||
/**
|
||||
* Indicates whether zooming (pinch to zoom and/or drag) is enabled.
|
||||
*/
|
||||
zoomEnabled: boolean
|
||||
};
|
||||
zoomEnabled: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a React Component which depicts a specific participant's avatar
|
||||
@@ -119,7 +123,7 @@ type Props = {
|
||||
*
|
||||
* @augments Component
|
||||
*/
|
||||
class ParticipantView extends Component<Props> {
|
||||
class ParticipantView extends Component<IProps> {
|
||||
|
||||
/**
|
||||
* Renders the inactive connection status label.
|
||||
@@ -144,8 +148,8 @@ class ParticipantView extends Component<Props> {
|
||||
return (
|
||||
<View
|
||||
pointerEvents = 'box-none'
|
||||
style = { containerStyle }>
|
||||
<Text style = { styles.connectionInfoText }>
|
||||
style = { containerStyle as ViewStyle }>
|
||||
<Text style = { styles.connectionInfoText as TextStyle }>
|
||||
{ t('connection.LOW_BANDWIDTH', { displayName }) }
|
||||
</Text>
|
||||
</View>
|
||||
@@ -200,7 +204,7 @@ class ParticipantView extends Component<Props> {
|
||||
zoomEnabled = { this.props.zoomEnabled } /> }
|
||||
|
||||
{ !renderSharedVideo && !renderVideo
|
||||
&& <View style = { styles.avatarContainer }>
|
||||
&& <View style = { styles.avatarContainer as ViewStyle }>
|
||||
<Avatar
|
||||
participantId = { this.props.participantId }
|
||||
size = { this.props.avatarSize } />
|
||||
@@ -221,9 +225,9 @@ class ParticipantView extends Component<Props> {
|
||||
* @param {Object} ownProps - The React {@code Component} props passed to the
|
||||
* associated (instance of) {@code ParticipantView}.
|
||||
* @private
|
||||
* @returns {Props}
|
||||
* @returns {IProps}
|
||||
*/
|
||||
function _mapStateToProps(state, ownProps) {
|
||||
function _mapStateToProps(state: IReduxState, ownProps: any) {
|
||||
const { disableVideo, participantId } = ownProps;
|
||||
const participant = getParticipantById(state, participantId);
|
||||
const videoTrack = getVideoTrackByParticipant(state, participant);
|
||||
@@ -245,7 +249,7 @@ function _mapStateToProps(state, ownProps) {
|
||||
* @param {string} id - The ID of the participant.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function shouldRenderParticipantVideo(stateful, id) {
|
||||
function shouldRenderParticipantVideo(stateful: IStateful, id: string) {
|
||||
const state = toState(stateful);
|
||||
const participant = getParticipantById(state, id);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import { BoxModel } from '../../styles/components/styles/BoxModel';
|
||||
import { ColorPalette } from '../../styles/components/styles/ColorPalette';
|
||||
|
||||
@@ -48,7 +48,7 @@ export interface IProps {
|
||||
* The style (as in stylesheet) to be applied to this
|
||||
* {@code AbstractContainer}.
|
||||
*/
|
||||
style?: StyleType;
|
||||
style?: StyleType | StyleType[];
|
||||
|
||||
tabIndex?: number;
|
||||
|
||||
@@ -58,7 +58,7 @@ export interface IProps {
|
||||
* undefined and {@link onClick} is defined, {@code touchFeedback} is
|
||||
* considered defined as {@code true}.
|
||||
*/
|
||||
touchFeedback?: Function;
|
||||
touchFeedback?: boolean;
|
||||
|
||||
/**
|
||||
* Color to display when clicked.
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { View } from 'react-native';
|
||||
import { View, ViewStyle } from 'react-native';
|
||||
|
||||
import Icon from '../../../icons/components/Icon';
|
||||
import { type StyleType } from '../../../styles';
|
||||
import { StyleType } from '../../../styles/functions.any';
|
||||
|
||||
import styles from './indicatorstyles';
|
||||
import styles from './indicatorStyles';
|
||||
import { BASE_INDICATOR } from './styles';
|
||||
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* Overwritten background color when indicator is highlighted.
|
||||
@@ -19,24 +17,24 @@ type Props = {
|
||||
/**
|
||||
* True if a highlighted background has to be applied.
|
||||
*/
|
||||
highlight: boolean,
|
||||
highlight?: boolean;
|
||||
|
||||
/**
|
||||
* The name of the icon to be used as the indicator.
|
||||
*/
|
||||
icon: string,
|
||||
icon: Function;
|
||||
|
||||
/**
|
||||
* Additional style to be applied to the icon element.
|
||||
*/
|
||||
iconStyle: StyleType
|
||||
};
|
||||
iconStyle?: StyleType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a base indicator to be reused across all native indicators on
|
||||
* the filmstrip.
|
||||
*/
|
||||
export default class BaseIndicator extends Component<Props> {
|
||||
export default class BaseIndicator extends Component<IProps> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
@@ -47,12 +45,12 @@ export default class BaseIndicator extends Component<Props> {
|
||||
|
||||
return (
|
||||
<View
|
||||
style = { BASE_INDICATOR }>
|
||||
style = { BASE_INDICATOR as ViewStyle }>
|
||||
<Icon
|
||||
src = { icon }
|
||||
style = { [
|
||||
styles.indicator,
|
||||
iconStyle
|
||||
iconStyle ?? {}
|
||||
] } />
|
||||
</View>
|
||||
);
|
||||
@@ -1,30 +1,28 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { Image } from 'react-native';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link Image}.
|
||||
*/
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* The ImageSource to be rendered as image.
|
||||
*/
|
||||
src: Object,
|
||||
src: Object;
|
||||
|
||||
/**
|
||||
* The component's external style.
|
||||
*/
|
||||
style: Object
|
||||
};
|
||||
style: Object;
|
||||
}
|
||||
|
||||
/**
|
||||
* A component rendering aN IMAGE.
|
||||
*
|
||||
* @augments Component
|
||||
*/
|
||||
export default class ImageImpl extends Component<Props> {
|
||||
export default class ImageImpl extends Component<IProps> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
@@ -1,5 +1,3 @@
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { Linking } from 'react-native';
|
||||
|
||||
@@ -8,40 +6,40 @@ import Text from './Text';
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link Link}.
|
||||
*/
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* The children to be displayed within this Link.
|
||||
*/
|
||||
children: React$Node,
|
||||
children: React.ReactNode;
|
||||
|
||||
/**
|
||||
* Notifies that this Link failed to open the URL associated with it.
|
||||
*/
|
||||
onLinkingOpenURLRejected?: Function,
|
||||
onLinkingOpenURLRejected?: Function;
|
||||
|
||||
/**
|
||||
* The CSS style to be applied to this Link for the purposes of display.
|
||||
*/
|
||||
style?: Object,
|
||||
style?: Object;
|
||||
|
||||
/**
|
||||
* The URL to be opened when this Link is clicked/pressed.
|
||||
*/
|
||||
url: string
|
||||
};
|
||||
url: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a (hyper)link to a URL in the fashion of the HTML anchor element
|
||||
* and its href attribute.
|
||||
*/
|
||||
export default class Link extends Component<Props> {
|
||||
export default class Link extends Component<IProps> {
|
||||
/**
|
||||
* Initializes a new Link instance.
|
||||
*
|
||||
* @param {Object} props - Component properties.
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
// Bind event handlers so they are only bound once for every instance.
|
||||
@@ -71,14 +69,12 @@ export default class Link extends Component<Props> {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onLinkingOpenURLRejected(reason) {
|
||||
_onLinkingOpenURLRejected(reason: Error) {
|
||||
const onRejected = this.props.onLinkingOpenURLRejected;
|
||||
|
||||
onRejected && onRejected(reason);
|
||||
onRejected?.(reason);
|
||||
}
|
||||
|
||||
_onPress: () => void;
|
||||
|
||||
/**
|
||||
* Handles press on this Link. Opens the URL associated with this Link.
|
||||
*
|
||||
@@ -1,42 +1,40 @@
|
||||
// @flow
|
||||
|
||||
import punycode from 'punycode';
|
||||
import React, { Component } from 'react';
|
||||
import ReactLinkify from 'react-linkify';
|
||||
import { Text } from 'react-native';
|
||||
|
||||
import { type StyleType } from '../../../styles';
|
||||
import { StyleType } from '../../../styles/functions.any';
|
||||
|
||||
import Link from './Link';
|
||||
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* The children of the component.
|
||||
*/
|
||||
children: React$Node,
|
||||
children: React.ReactNode;
|
||||
|
||||
/**
|
||||
* The extra styles to be applied to links.
|
||||
*/
|
||||
linkStyle: StyleType,
|
||||
linkStyle: StyleType;
|
||||
|
||||
/**
|
||||
* The extra styles to be applied to text.
|
||||
*/
|
||||
style?: StyleType
|
||||
};
|
||||
style?: StyleType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a react native wrapper for the react-linkify component.
|
||||
*/
|
||||
export default class Linkify extends Component<Props> {
|
||||
export default class Linkify extends Component<IProps> {
|
||||
/**
|
||||
* Initiates a new {@code Component}.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this._componentDecorator = this._componentDecorator.bind(this);
|
||||
@@ -60,8 +58,6 @@ export default class Linkify extends Component<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
_componentDecorator: (string, string, number) => React$Node;
|
||||
|
||||
/**
|
||||
* Implements a component decorator for react-linkify.
|
||||
*
|
||||
@@ -15,6 +15,8 @@ interface IProps {
|
||||
* prop of the native component.
|
||||
*/
|
||||
size?: 'large' | 'small' | 'medium';
|
||||
|
||||
style?: any;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
import { StyleSheet, View, ViewStyle } from 'react-native';
|
||||
|
||||
import { TINTED_VIEW_DEFAULT } from './styles';
|
||||
|
||||
@@ -17,24 +15,24 @@ const BASE_STYLE = {
|
||||
/**
|
||||
* {@code TintedView}'s React {@code Component} prop types.
|
||||
*/
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* The children components of this component.
|
||||
*/
|
||||
children?: React$Node,
|
||||
children?: React.ReactNode;
|
||||
|
||||
/**
|
||||
* Style to override the base style.
|
||||
*/
|
||||
style: Object
|
||||
};
|
||||
style?: Object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a component aimed at covering another view and tinting it with
|
||||
* the given color and opacity.
|
||||
*/
|
||||
export default class TintedView extends Component<Props> {
|
||||
export default class TintedView extends Component<IProps> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
@@ -48,7 +46,7 @@ export default class TintedView extends Component<Props> {
|
||||
return (
|
||||
<View
|
||||
pointerEvents = 'box-none'
|
||||
style = { BASE_STYLE }>
|
||||
style = { BASE_STYLE as ViewStyle }>
|
||||
<View
|
||||
pointerEvents = 'none'
|
||||
style = { [
|
||||
@@ -58,7 +56,7 @@ export default class TintedView extends Component<Props> {
|
||||
] } />
|
||||
<View
|
||||
pointerEvents = 'box-none'
|
||||
style = { BASE_STYLE }>
|
||||
style = { BASE_STYLE as ViewStyle }>
|
||||
{ children }
|
||||
</View>
|
||||
</View>
|
||||
@@ -1,9 +1,8 @@
|
||||
// @flex
|
||||
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import { ColorSchemeRegistry, schemeColor } from '../../../color-scheme';
|
||||
import { BoxModel } from '../../../styles';
|
||||
import ColorSchemeRegistry from '../../../color-scheme/ColorSchemeRegistry';
|
||||
import { schemeColor } from '../../../color-scheme/functions';
|
||||
import { BoxModel } from '../../../styles/components/styles/BoxModel';
|
||||
|
||||
const HEADER_FONT_SIZE = 18;
|
||||
const HEADER_HEIGHT = 48;
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import { ColorPalette } from '../../../styles/components/styles/ColorPalette';
|
||||
|
||||
export default {
|
||||
@@ -163,7 +163,7 @@ class MultiSelectAutocomplete extends Component<IProps, IState> {
|
||||
const autoFocus = this.props.shouldFocus || false;
|
||||
const disabled = this.props.isDisabled || false;
|
||||
const placeholder = this.props.placeholder || '';
|
||||
const noMatchesFound = this.props.noMatchesFound || '';
|
||||
const noMatchesFound = this.state.loading ? this.props.loadingMessage : this.props.noMatchesFound || '';
|
||||
const errorDialog = this._renderError();
|
||||
|
||||
return (
|
||||
@@ -200,7 +200,7 @@ class MultiSelectAutocomplete extends Component<IProps, IState> {
|
||||
error: this.state.error && Boolean(filterValue),
|
||||
filterValue,
|
||||
isOpen: Boolean(this.state.items.length) && Boolean(filterValue),
|
||||
items: filterValue ? this.state.items : [],
|
||||
items: [],
|
||||
loading: Boolean(filterValue)
|
||||
});
|
||||
if (filterValue) {
|
||||
|
||||
@@ -46,7 +46,7 @@ const _WELL_KNOWN_NUMBER_PROPERTIES = [ 'height', 'width' ];
|
||||
* @param {Styletype} st - The complex style type.
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function styleTypeToObject(st: StyleType) {
|
||||
export function styleTypeToObject(st: StyleType | StyleType[]) {
|
||||
if (!st) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ export * from './functions.any';
|
||||
* @param {StyleType} style - The passed style prop to the component.
|
||||
* @returns {StyleType}
|
||||
*/
|
||||
export function getFixedPlatformStyle(style?: StyleType): StyleType {
|
||||
export function getFixedPlatformStyle(style?: StyleType | StyleType[]) {
|
||||
// There is nothing to do on mobile - yet.
|
||||
|
||||
return style ?? {};
|
||||
|
||||
@@ -9,7 +9,7 @@ export * from './functions.any';
|
||||
* @param {StyleType} style - The passed style prop to the component.
|
||||
* @returns {StyleType}
|
||||
*/
|
||||
export function getFixedPlatformStyle(style?: StyleType) {
|
||||
export function getFixedPlatformStyle(style?: StyleType | StyleType[]) {
|
||||
if (Array.isArray(style)) {
|
||||
const _style = {};
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* @flow */
|
||||
|
||||
import { SET_CONNECTION_STATE } from './actionTypes';
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description-complete-sentence
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { GestureResponderEvent } from 'react-native';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { isTestModeEnabled } from '../functions';
|
||||
|
||||
@@ -28,7 +30,7 @@ export type TestHintProps = {
|
||||
* The optional "on press" handler which can be used to bind a click handler
|
||||
* to a {@link TestHint}.
|
||||
*/
|
||||
onPress?: Function;
|
||||
onPress?: (e?: GestureResponderEvent) => void;
|
||||
|
||||
/**
|
||||
* The test hint's (text) value which is to be consumed by the tests.
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { Text } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import type { TestHintProps } from './AbstractTestHint';
|
||||
import { _mapStateToProps } from './AbstractTestHint';
|
||||
import { TestHintProps, _mapStateToProps } from './AbstractTestHint';
|
||||
|
||||
/**
|
||||
* The Android version of <code>TestHint</code>. It will put the identifier,
|
||||
@@ -1,11 +1,8 @@
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { Text } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import type { TestHintProps } from './AbstractTestHint';
|
||||
import { _mapStateToProps } from './AbstractTestHint';
|
||||
import { TestHintProps, _mapStateToProps } from './AbstractTestHint';
|
||||
|
||||
/**
|
||||
* This is the iOS version of the TestHint.
|
||||
@@ -1,16 +1,14 @@
|
||||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import { Provider as PaperProvider } from 'react-native-paper';
|
||||
|
||||
import BaseTheme from './BaseTheme.native';
|
||||
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
/**
|
||||
* The children of the component.
|
||||
*/
|
||||
children: React.ChildrenArray<any>
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -19,6 +17,6 @@ type Props = {
|
||||
* @param {Object} props - The props of the component.
|
||||
* @returns {React.ReactNode}
|
||||
*/
|
||||
export default function JitsiThemePaperProvider(props: Props) {
|
||||
export default function JitsiThemePaperProvider(props: IProps) {
|
||||
return <PaperProvider theme = { BaseTheme }>{ props.children }</PaperProvider>;
|
||||
}
|
||||
@@ -24,6 +24,8 @@ interface IProps {
|
||||
selectedItems?: MultiSelectItem[];
|
||||
}
|
||||
|
||||
const MULTI_SELECT_HEIGHT = 200;
|
||||
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
container: {
|
||||
@@ -41,7 +43,7 @@ const useStyles = makeStyles()(theme => {
|
||||
borderRadius: `${Number(theme.shape.borderRadius)}px`,
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
zIndex: 2,
|
||||
maxHeight: '400px',
|
||||
maxHeight: `${MULTI_SELECT_HEIGHT}px`,
|
||||
overflowY: 'auto',
|
||||
padding: '0'
|
||||
},
|
||||
@@ -128,7 +130,7 @@ const MultiSelect = ({
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
: <div>{noMatchesText}</div>
|
||||
: <div className = { classes.listItem }>{noMatchesText}</div>
|
||||
}
|
||||
</div>
|
||||
), [ items ]);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* The type of (redux) action to reset the breakout rooms data.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* Resets the state of calendar integration so stored events and selected
|
||||
* calendar type are cleared.
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import { Component } from 'react';
|
||||
|
||||
/**
|
||||
@@ -7,7 +5,7 @@ import { Component } from 'react';
|
||||
*
|
||||
* @augments Component
|
||||
*/
|
||||
class AddMeetingUrlButton extends Component<*> {
|
||||
class AddMeetingUrlButton extends Component<void> {
|
||||
/**
|
||||
* Implements React's {@link Component#render}.
|
||||
*
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import { Component } from 'react';
|
||||
|
||||
/**
|
||||
@@ -7,7 +5,7 @@ import { Component } from 'react';
|
||||
*
|
||||
* @augments Component
|
||||
*/
|
||||
class JoinButton extends Component<*> {
|
||||
class JoinButton extends Component<void> {
|
||||
/**
|
||||
* Implements React's {@link Component#render}.
|
||||
*
|
||||
@@ -1,35 +1,35 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { IStore } from '../../app/types';
|
||||
import ConfirmDialog from '../../base/dialog/components/native/ConfirmDialog';
|
||||
import { translate } from '../../base/i18n/functions';
|
||||
import { updateCalendarEvent } from '../actions';
|
||||
|
||||
type Props = {
|
||||
interface IProps extends WithTranslation {
|
||||
|
||||
/**
|
||||
* The Redux dispatch function.
|
||||
*/
|
||||
dispatch: Function,
|
||||
dispatch: IStore['dispatch'];
|
||||
|
||||
/**
|
||||
* The ID of the event to be updated.
|
||||
*/
|
||||
eventId: string
|
||||
};
|
||||
eventId: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component for the add Jitsi link confirm dialog.
|
||||
*/
|
||||
class UpdateCalendarEventDialog extends Component<Props> {
|
||||
class UpdateCalendarEventDialog extends Component<IProps> {
|
||||
/**
|
||||
* Initializes a new {@code UpdateCalendarEventDialog} instance.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this._onSubmit = this._onSubmit.bind(this);
|
||||
@@ -49,8 +49,6 @@ class UpdateCalendarEventDialog extends Component<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
_onSubmit: () => boolean;
|
||||
|
||||
/**
|
||||
* Callback for the confirm button.
|
||||
*
|
||||
@@ -58,7 +56,7 @@ class UpdateCalendarEventDialog extends Component<Props> {
|
||||
* @returns {boolean} - True (to note that the modal should be closed).
|
||||
*/
|
||||
_onSubmit() {
|
||||
this.props.dispatch(updateCalendarEvent(this.props.eventId, ''));
|
||||
this.props.dispatch(updateCalendarEvent(this.props.eventId));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* The type of the action which signals to add a new chat message.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* eslint-disable lines-around-comment, max-len */
|
||||
|
||||
import { IParticipant } from '../base/participants/types';
|
||||
import { navigate }
|
||||
// @ts-ignore
|
||||
from '../mobile/navigation/components/conference/ConferenceNavigationContainerRef';
|
||||
@@ -21,7 +22,7 @@ export * from './actions.any';
|
||||
* type: OPEN_CHAT
|
||||
* }}
|
||||
*/
|
||||
export function openChat(participant: Object, disablePolls?: boolean) {
|
||||
export function openChat(participant: IParticipant | undefined | Object, disablePolls?: boolean) {
|
||||
if (disablePolls) {
|
||||
navigate(screen.conference.chat);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Platform } from 'react-native';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
import { Platform, ViewStyle } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
@@ -10,47 +11,42 @@ import { BUTTON_TYPES } from '../../../base/ui/constants.native';
|
||||
|
||||
import styles from './styles';
|
||||
|
||||
type Props = {
|
||||
interface IProps extends WithTranslation {
|
||||
|
||||
/**
|
||||
* Callback to invoke on message send.
|
||||
*/
|
||||
onSend: Function,
|
||||
onSend: Function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to be used to translate i18n labels.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
type State = {
|
||||
interface IState {
|
||||
|
||||
/**
|
||||
* Boolean to show if an extra padding needs to be added to the bar.
|
||||
*/
|
||||
addPadding: boolean,
|
||||
addPadding: boolean;
|
||||
|
||||
/**
|
||||
* The value of the input field.
|
||||
*/
|
||||
message: string,
|
||||
message: string;
|
||||
|
||||
/**
|
||||
* Boolean to show or hide the send button.
|
||||
*/
|
||||
showSend: boolean
|
||||
};
|
||||
showSend: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the chat input bar with text field and action(s).
|
||||
*/
|
||||
class ChatInputBar extends Component<Props, State> {
|
||||
class ChatInputBar extends Component<IProps, IState> {
|
||||
/**
|
||||
* Instantiates a new instance of the component.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
@@ -76,7 +72,7 @@ class ChatInputBar extends Component<Props, State> {
|
||||
style = { [
|
||||
styles.inputBar,
|
||||
this.state.addPadding ? styles.extraBarPadding : null
|
||||
] }>
|
||||
] as ViewStyle[] }>
|
||||
<Input
|
||||
blurOnSubmit = { false }
|
||||
customStyles = {{ container: styles.customInputContainer }}
|
||||
@@ -98,30 +94,26 @@ class ChatInputBar extends Component<Props, State> {
|
||||
);
|
||||
}
|
||||
|
||||
_onChangeText: string => void;
|
||||
|
||||
/**
|
||||
* Callback to handle the change of the value of the text field.
|
||||
*
|
||||
* @param {string} text - The current value of the field.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onChangeText(text) {
|
||||
_onChangeText(text: string) {
|
||||
this.setState({
|
||||
message: text,
|
||||
showSend: Boolean(text)
|
||||
});
|
||||
}
|
||||
|
||||
_onFocused: boolean => Function;
|
||||
|
||||
/**
|
||||
* Constructs a callback to be used to update the padding of the field if necessary.
|
||||
*
|
||||
* @param {boolean} focused - True of the field is focused.
|
||||
* @returns {Function}
|
||||
*/
|
||||
_onFocused(focused) {
|
||||
_onFocused(focused: boolean) {
|
||||
return () => {
|
||||
Platform.OS === 'android' && this.setState({
|
||||
addPadding: focused
|
||||
@@ -129,8 +121,6 @@ class ChatInputBar extends Component<Props, State> {
|
||||
};
|
||||
}
|
||||
|
||||
_onSubmit: () => void;
|
||||
|
||||
/**
|
||||
* Callback to handle the submit event of the text field.
|
||||
*
|
||||
@@ -1,14 +1,15 @@
|
||||
import React from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
import { Text, View, ViewStyle } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import Avatar from '../../../base/avatar/components/Avatar';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import Linkify from '../../../base/react/components/native/Linkify';
|
||||
import { isGifMessage } from '../../../gifs/functions';
|
||||
import { isGifMessage } from '../../../gifs/functions.native';
|
||||
import { MESSAGE_TYPE_ERROR, MESSAGE_TYPE_LOCAL } from '../../constants';
|
||||
import { replaceNonUnicodeEmojis } from '../../functions';
|
||||
import AbstractChatMessage, { type Props } from '../AbstractChatMessage';
|
||||
import AbstractChatMessage, { IProps } from '../AbstractChatMessage';
|
||||
|
||||
import GifMessage from './GifMessage';
|
||||
import PrivateMessageButton from './PrivateMessageButton';
|
||||
@@ -18,7 +19,7 @@ import styles from './styles';
|
||||
/**
|
||||
* Renders a single chat message.
|
||||
*/
|
||||
class ChatMessage extends AbstractChatMessage<Props> {
|
||||
class ChatMessage extends AbstractChatMessage<IProps> {
|
||||
/**
|
||||
* Implements {@code Component#render}.
|
||||
*
|
||||
@@ -31,18 +32,18 @@ class ChatMessage extends AbstractChatMessage<Props> {
|
||||
|
||||
// Style arrays that need to be updated in various scenarios, such as
|
||||
// error messages or others.
|
||||
const detailsWrapperStyle = [
|
||||
styles.detailsWrapper
|
||||
const detailsWrapperStyle: ViewStyle[] = [
|
||||
styles.detailsWrapper as ViewStyle
|
||||
];
|
||||
const messageBubbleStyle = [
|
||||
styles.messageBubble
|
||||
const messageBubbleStyle: ViewStyle[] = [
|
||||
styles.messageBubble as ViewStyle
|
||||
];
|
||||
|
||||
if (localMessage) {
|
||||
// This is a message sent by the local participant.
|
||||
|
||||
// The wrapper needs to be aligned to the right.
|
||||
detailsWrapperStyle.push(styles.ownMessageDetailsWrapper);
|
||||
detailsWrapperStyle.push(styles.ownMessageDetailsWrapper as ViewStyle);
|
||||
|
||||
// The bubble needs some additional styling
|
||||
messageBubbleStyle.push(styles.localMessageBubble);
|
||||
@@ -69,11 +70,11 @@ class ChatMessage extends AbstractChatMessage<Props> {
|
||||
const messageText = replaceNonUnicodeEmojis(this._getMessageText());
|
||||
|
||||
return (
|
||||
<View style = { styles.messageWrapper } >
|
||||
<View style = { styles.messageWrapper as ViewStyle } >
|
||||
{ this._renderAvatar() }
|
||||
<View style = { detailsWrapperStyle }>
|
||||
<View style = { messageBubbleStyle }>
|
||||
<View style = { styles.textWrapper } >
|
||||
<View style = { styles.textWrapper as ViewStyle } >
|
||||
{ this._renderDisplayName() }
|
||||
{ isGifMessage(messageText)
|
||||
? <GifMessage message = { messageText } />
|
||||
@@ -94,12 +95,6 @@ class ChatMessage extends AbstractChatMessage<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
_getFormattedTimestamp: () => string;
|
||||
|
||||
_getMessageText: () => string;
|
||||
|
||||
_getPrivateNoticeMessage: () => string;
|
||||
|
||||
/**
|
||||
* Renders the avatar of the sender.
|
||||
*
|
||||
@@ -171,7 +166,7 @@ class ChatMessage extends AbstractChatMessage<Props> {
|
||||
}
|
||||
|
||||
return (
|
||||
<View style = { styles.replyContainer }>
|
||||
<View style = { styles.replyContainer as ViewStyle }>
|
||||
<PrivateMessageButton
|
||||
isLobbyMessage = { lobbyChat }
|
||||
participantID = { message.id }
|
||||
@@ -204,9 +199,9 @@ class ChatMessage extends AbstractChatMessage<Props> {
|
||||
* Maps part of the redux state to the props of this component.
|
||||
*
|
||||
* @param {Object} state - The Redux state.
|
||||
* @returns {Props}
|
||||
* @returns {IProps}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
function _mapStateToProps(state: IReduxState) {
|
||||
return {
|
||||
knocking: state['features/lobby'].knocking
|
||||
};
|
||||
@@ -1,28 +1,29 @@
|
||||
import React, { Component, ReactElement } from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import { FlatList } from 'react-native';
|
||||
|
||||
import { MESSAGE_TYPE_LOCAL, MESSAGE_TYPE_REMOTE } from '../../constants';
|
||||
import { IMessage } from '../../reducer';
|
||||
|
||||
import ChatMessage from './ChatMessage';
|
||||
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* The messages array to render.
|
||||
*/
|
||||
messages: Array<Object>
|
||||
/**
|
||||
* The messages array to render.
|
||||
*/
|
||||
messages: Array<IMessage>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a container to render all the chat messages in a conference.
|
||||
*/
|
||||
export default class ChatMessageGroup extends Component<Props> {
|
||||
export default class ChatMessageGroup extends Component<IProps> {
|
||||
/**
|
||||
* Instantiates a new instance of the component.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this._keyExtractor = this._keyExtractor.bind(this);
|
||||
@@ -44,29 +45,25 @@ export default class ChatMessageGroup extends Component<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
_keyExtractor: Object => string;
|
||||
|
||||
/**
|
||||
* Key extractor for the flatlist.
|
||||
*
|
||||
* @param {Object} item - The flatlist item that we need the key to be
|
||||
* @param {Object} _item - The flatlist item that we need the key to be
|
||||
* generated for.
|
||||
* @param {number} index - The index of the element.
|
||||
* @returns {string}
|
||||
*/
|
||||
_keyExtractor(item, index) {
|
||||
_keyExtractor(_item: Object, index: number) {
|
||||
return `key_${index}`;
|
||||
}
|
||||
|
||||
_renderMessage: Object => ReactElement;
|
||||
|
||||
/**
|
||||
* Renders a single chat message.
|
||||
*
|
||||
* @param {Object} message - The chat message to render.
|
||||
* @returns {React$Element<*>}
|
||||
*/
|
||||
_renderMessage({ index, item: message }) {
|
||||
_renderMessage({ index, item: message }: { index: number; item: IMessage; }) {
|
||||
return (
|
||||
<ChatMessage
|
||||
message = { message }
|
||||
@@ -1,26 +1,26 @@
|
||||
import React from 'react';
|
||||
import { Image, View } from 'react-native';
|
||||
import { Image, ImageStyle, View } from 'react-native';
|
||||
|
||||
import { GIF_PREFIX } from '../../../gifs/constants';
|
||||
|
||||
import styles from './styles';
|
||||
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* The formatted gif message.
|
||||
*/
|
||||
message: string
|
||||
message: string;
|
||||
}
|
||||
|
||||
const GifMessage = ({ message }: Props) => {
|
||||
const GifMessage = ({ message }: IProps) => {
|
||||
const url = message.substring(GIF_PREFIX.length, message.length - 1);
|
||||
|
||||
return (<View
|
||||
style = { styles.gifContainer }>
|
||||
<Image
|
||||
source = {{ uri: url }}
|
||||
style = { styles.gifImage } />
|
||||
style = { styles.gifImage as ImageStyle } />
|
||||
</View>);
|
||||
};
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
import React, { ReactElement } from 'react';
|
||||
import { FlatList, Text, View } from 'react-native';
|
||||
import React from 'react';
|
||||
import { FlatList, Text, TextStyle, View, ViewStyle } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import AbstractMessageContainer, { type Props as AbstractProps }
|
||||
from '../AbstractMessageContainer';
|
||||
import { IMessage } from '../../reducer';
|
||||
import AbstractMessageContainer, { IProps as AbstractProps } from '../AbstractMessageContainer';
|
||||
|
||||
import ChatMessageGroup from './ChatMessageGroup';
|
||||
import styles from './styles';
|
||||
|
||||
type Props = AbstractProps & {
|
||||
interface IProps extends AbstractProps {
|
||||
|
||||
/**
|
||||
* Function to be used to translate i18n labels.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
t: Function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a container to render all the chat messages in a conference.
|
||||
*/
|
||||
class MessageContainer extends AbstractMessageContainer<Props> {
|
||||
class MessageContainer extends AbstractMessageContainer<IProps, any> {
|
||||
/**
|
||||
* Instantiates a new instance of the component.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this._keyExtractor = this._keyExtractor.bind(this);
|
||||
@@ -57,24 +57,18 @@ class MessageContainer extends AbstractMessageContainer<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
_getMessagesGroupedBySender: () => Array<Array<Object>>;
|
||||
|
||||
_keyExtractor: Object => string;
|
||||
|
||||
/**
|
||||
* Key extractor for the flatlist.
|
||||
*
|
||||
* @param {Object} item - The flatlist item that we need the key to be
|
||||
* @param {Object} _item - The flatlist item that we need the key to be
|
||||
* generated for.
|
||||
* @param {number} index - The index of the element.
|
||||
* @returns {string}
|
||||
*/
|
||||
_keyExtractor(item, index) {
|
||||
_keyExtractor(_item: Object, index: number) {
|
||||
return `key_${index}`;
|
||||
}
|
||||
|
||||
_renderListEmptyComponent: () => ReactElement;
|
||||
|
||||
/**
|
||||
* Renders a message when there are no messages in the chat yet.
|
||||
*
|
||||
@@ -84,23 +78,21 @@ class MessageContainer extends AbstractMessageContainer<Props> {
|
||||
const { t } = this.props;
|
||||
|
||||
return (
|
||||
<View style = { styles.emptyComponentWrapper }>
|
||||
<Text style = { styles.emptyComponentText }>
|
||||
<View style = { styles.emptyComponentWrapper as ViewStyle }>
|
||||
<Text style = { styles.emptyComponentText as TextStyle }>
|
||||
{ t('chat.noMessagesMessage') }
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_renderMessageGroup: Object => ReactElement;
|
||||
|
||||
/**
|
||||
* Renders a single chat message.
|
||||
*
|
||||
* @param {Array<Object>} messages - The chat message to render.
|
||||
* @returns {React$Element<*>}
|
||||
*/
|
||||
_renderMessageGroup({ item: messages }) {
|
||||
_renderMessageGroup({ item: messages }: { item: IMessage[]; }) {
|
||||
return <ChatMessageGroup messages = { messages } />;
|
||||
}
|
||||
}
|
||||
@@ -1,57 +1,49 @@
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { CHAT_ENABLED } from '../../../base/flags/constants';
|
||||
import { getFeatureFlag } from '../../../base/flags/functions';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import { IconMessage, IconReply } from '../../../base/icons/svg';
|
||||
import { getParticipantById } from '../../../base/participants/functions';
|
||||
import { IParticipant } from '../../../base/participants/types';
|
||||
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
|
||||
import { handleLobbyChatInitialized, openChat } from '../../../chat/actions.native';
|
||||
import { navigate } from '../../../mobile/navigation/components/conference/ConferenceNavigationContainerRef';
|
||||
import { screen } from '../../../mobile/navigation/routes';
|
||||
import { handleLobbyChatInitialized, openChat } from '../../actions.native';
|
||||
|
||||
export type Props = AbstractButtonProps & {
|
||||
|
||||
/**
|
||||
* The Redux Dispatch function.
|
||||
*/
|
||||
dispatch: Function,
|
||||
|
||||
/**
|
||||
* The ID of the participant that the message is to be sent.
|
||||
*/
|
||||
participantID: string,
|
||||
|
||||
/**
|
||||
* True if the button is rendered as a reply button.
|
||||
*/
|
||||
reply: boolean,
|
||||
|
||||
/**
|
||||
* Function to be used to translate i18n labels.
|
||||
*/
|
||||
t: Function,
|
||||
|
||||
/**
|
||||
* True if the polls feature is disabled.
|
||||
*/
|
||||
_isPollsDisabled: boolean,
|
||||
export interface IProps extends AbstractButtonProps {
|
||||
|
||||
/**
|
||||
* True if message is a lobby chat message.
|
||||
*/
|
||||
_isLobbyMessage: boolean,
|
||||
_isLobbyMessage: boolean;
|
||||
|
||||
/**
|
||||
* True if the polls feature is disabled.
|
||||
*/
|
||||
_isPollsDisabled?: boolean;
|
||||
|
||||
/**
|
||||
* The participant object retrieved from Redux.
|
||||
*/
|
||||
_participant: Object,
|
||||
};
|
||||
_participant?: IParticipant;
|
||||
|
||||
/**
|
||||
* The ID of the participant that the message is to be sent.
|
||||
*/
|
||||
participantID: string;
|
||||
|
||||
/**
|
||||
* True if the button is rendered as a reply button.
|
||||
*/
|
||||
reply: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class to render a button that initiates the sending of a private message through chet.
|
||||
* Class to render a button that initiates the sending of a private message through chat.
|
||||
*/
|
||||
class PrivateMessageButton extends AbstractButton<Props, any> {
|
||||
class PrivateMessageButton extends AbstractButton<IProps, any> {
|
||||
accessibilityLabel = 'toolbar.accessibilityLabel.privateMessage';
|
||||
icon = IconMessage;
|
||||
label = 'toolbar.privateMessage';
|
||||
@@ -99,10 +91,10 @@ class PrivateMessageButton extends AbstractButton<Props, any> {
|
||||
* Maps part of the Redux store to the props of this component.
|
||||
*
|
||||
* @param {Object} state - The Redux state.
|
||||
* @param {Props} ownProps - The own props of the component.
|
||||
* @returns {Props}
|
||||
* @param {IProps} ownProps - The own props of the component.
|
||||
* @returns {IProps}
|
||||
*/
|
||||
export function _mapStateToProps(state: Object, ownProps: Props) {
|
||||
export function _mapStateToProps(state: IReduxState, ownProps: any) {
|
||||
const enabled = getFeatureFlag(state, CHAT_ENABLED, true);
|
||||
const { disablePolls } = state['features/base/config'];
|
||||
const { visible = enabled, isLobbyMessage, participantID } = ownProps;
|
||||
@@ -90,6 +90,8 @@ class ChatInput extends Component<IProps, IState> {
|
||||
if (isMobileBrowser()) {
|
||||
// Ensure textarea is not focused when opening chat on mobile browser.
|
||||
this._textArea?.current && this._textArea.current.blur();
|
||||
} else {
|
||||
this._focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,9 +29,9 @@ const styles = (theme: Theme) => {
|
||||
chatMessage: {
|
||||
display: 'inline-flex',
|
||||
padding: '12px',
|
||||
marginRight: '12px',
|
||||
backgroundColor: theme.palette.ui02,
|
||||
borderRadius: '4px 12px 12px 12px',
|
||||
boxSizing: 'border-box' as const,
|
||||
maxWidth: '100%',
|
||||
marginTop: '4px',
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* The size of the chat.
|
||||
*/
|
||||
|
||||
12
react/features/conference/constants.ts
Normal file
12
react/features/conference/constants.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { IFRAME_EMBED_ALLOWED_LOCATIONS as ADDITIONAL_LOCATIONS } from './extraConstants';
|
||||
|
||||
/**
|
||||
* Timeout of the conference when iframe is disabled in minutes.
|
||||
*/
|
||||
export const IFRAME_DISABLED_TIMEOUT_MINUTES = 5;
|
||||
|
||||
/**
|
||||
* A list of allowed location to embed iframe.
|
||||
*/
|
||||
/* eslint-disable-next-line no-extra-parens*/
|
||||
export const IFRAME_EMBED_ALLOWED_LOCATIONS = ([] as string[]).concat(ADDITIONAL_LOCATIONS);
|
||||
5
react/features/conference/extraConstants.ts
Normal file
5
react/features/conference/extraConstants.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Deploy-specific configuration constants.
|
||||
*/
|
||||
|
||||
export const IFRAME_EMBED_ALLOWED_LOCATIONS = [];
|
||||
@@ -1,8 +1,11 @@
|
||||
import i18n from 'i18next';
|
||||
import { batch } from 'react-redux';
|
||||
|
||||
// @ts-expect-error
|
||||
import { API_ID } from '../../../modules/API/constants';
|
||||
import { appNavigate } from '../app/actions';
|
||||
import { IStore } from '../app/types';
|
||||
import { redirectToStaticPage } from '../app/actions.any';
|
||||
import { IReduxState, IStore } from '../app/types';
|
||||
import {
|
||||
CONFERENCE_FAILED,
|
||||
CONFERENCE_JOINED,
|
||||
@@ -15,17 +18,22 @@ import { getURLWithoutParamsNormalized } from '../base/connection/utils';
|
||||
import { hideDialog } from '../base/dialog/actions';
|
||||
import { isDialogOpen } from '../base/dialog/functions';
|
||||
import { getLocalizedDateFormatter } from '../base/i18n/dateUtil';
|
||||
import { translateToHTML } from '../base/i18n/functions';
|
||||
import i18next from '../base/i18n/i18next';
|
||||
import { browser } from '../base/lib-jitsi-meet';
|
||||
import { pinParticipant } from '../base/participants/actions';
|
||||
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
|
||||
import StateListenerRegistry from '../base/redux/StateListenerRegistry';
|
||||
import { SET_REDUCED_UI } from '../base/responsive-ui/actionTypes';
|
||||
import { BUTTON_TYPES } from '../base/ui/constants.any';
|
||||
import { inIframe } from '../base/util/iframeUtils';
|
||||
import { isCalendarEnabled } from '../calendar-sync/functions';
|
||||
// eslint-disable-next-line lines-around-comment
|
||||
// @ts-ignore
|
||||
import FeedbackDialog from '../feedback/components/FeedbackDialog';
|
||||
import { setFilmstripEnabled } from '../filmstrip/actions.any';
|
||||
import { hideNotification, showNotification } from '../notifications/actions';
|
||||
import { isVpaasMeeting } from '../jaas/functions';
|
||||
import { hideNotification, showNotification, showWarningNotification } from '../notifications/actions';
|
||||
import {
|
||||
CALENDAR_NOTIFICATION_ID,
|
||||
NOTIFICATION_ICON,
|
||||
@@ -36,6 +44,7 @@ import { setToolboxEnabled } from '../toolbox/actions.any';
|
||||
|
||||
import { DISMISS_CALENDAR_NOTIFICATION } from './actionTypes';
|
||||
import { dismissCalendarNotification, notifyKickedOut } from './actions';
|
||||
import { IFRAME_DISABLED_TIMEOUT_MINUTES, IFRAME_EMBED_ALLOWED_LOCATIONS } from './constants';
|
||||
|
||||
|
||||
let intervalID: any;
|
||||
@@ -155,6 +164,49 @@ function _conferenceJoined({ dispatch, getState }: IStore) {
|
||||
}
|
||||
|
||||
dispatch(showSalesforceNotification());
|
||||
_checkIframe(getState(), dispatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional checks for embedding in iframe.
|
||||
*
|
||||
* @param {IReduxState} state - The current state of the app.
|
||||
* @param {Function} dispatch - The Redux dispatch function.
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _checkIframe(state: IReduxState, dispatch: IStore['dispatch']) {
|
||||
let allowIframe = false;
|
||||
|
||||
if (document.referrer === '') {
|
||||
// no iframe
|
||||
allowIframe = true;
|
||||
} else {
|
||||
try {
|
||||
allowIframe = IFRAME_EMBED_ALLOWED_LOCATIONS.includes(new URL(document.referrer).hostname);
|
||||
} catch (e) {
|
||||
// wrong URL in referrer
|
||||
}
|
||||
}
|
||||
|
||||
if (inIframe() && state['features/base/config'].disableIframeAPI && !browser.isElectron()
|
||||
&& !isVpaasMeeting(state) && !allowIframe) {
|
||||
// show sticky notification and redirect in 5 minutes
|
||||
dispatch(showWarningNotification({
|
||||
description: translateToHTML(
|
||||
i18next.t.bind(i18next),
|
||||
'notify.disabledIframe',
|
||||
{
|
||||
timeout: IFRAME_DISABLED_TIMEOUT_MINUTES
|
||||
}
|
||||
)
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.STICKY));
|
||||
|
||||
setTimeout(() => {
|
||||
// redirect to the promotional page
|
||||
dispatch(redirectToStaticPage('static/close3.html', `#jitsi_meet_external_api_id=${API_ID}`));
|
||||
}, IFRAME_DISABLED_TIMEOUT_MINUTES * 60 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* eslint-disable lines-around-comment */
|
||||
|
||||
import React from 'react';
|
||||
import { StyleProp, View, ViewStyle } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
@@ -12,12 +10,10 @@ import {
|
||||
getParticipantById,
|
||||
isScreenShareParticipant
|
||||
} from '../../../base/participants/functions';
|
||||
// @ts-ignore
|
||||
import BaseIndicator from '../../../base/react/components/native/BaseIndicator';
|
||||
import {
|
||||
getTrackByMediaTypeAndParticipant
|
||||
} from '../../../base/tracks/functions.native';
|
||||
// @ts-ignore
|
||||
import indicatorStyles from '../../../filmstrip/components/native/styles';
|
||||
import {
|
||||
isTrackStreamingStatusInactive,
|
||||
@@ -50,12 +46,12 @@ type IProps = AbstractProps & {
|
||||
/**
|
||||
* Whether the connection is inactive or not.
|
||||
*/
|
||||
_isConnectionStatusInactive: boolean;
|
||||
_isConnectionStatusInactive?: boolean;
|
||||
|
||||
/**
|
||||
* Whether the connection is interrupted or not.
|
||||
*/
|
||||
_isConnectionStatusInterrupted: boolean;
|
||||
_isConnectionStatusInterrupted?: boolean;
|
||||
|
||||
/**
|
||||
* Whether the current participant is a virtual screenshare.
|
||||
@@ -70,7 +66,7 @@ type IProps = AbstractProps & {
|
||||
/**
|
||||
* Icon style override.
|
||||
*/
|
||||
iconStyle: any;
|
||||
iconStyle?: any;
|
||||
};
|
||||
|
||||
type IState = {
|
||||
@@ -127,12 +123,10 @@ class ConnectionIndicator extends AbstractConnectionIndicator<IProps, IState> {
|
||||
_isVirtualScreenshareParticipant,
|
||||
_isConnectionStatusInactive,
|
||||
_isConnectionStatusInterrupted
|
||||
// @ts-ignore
|
||||
} = this.props;
|
||||
const {
|
||||
showIndicator,
|
||||
stats
|
||||
// @ts-ignore
|
||||
} = this.state;
|
||||
const { percent } = stats;
|
||||
|
||||
@@ -167,10 +161,8 @@ class ConnectionIndicator extends AbstractConnectionIndicator<IProps, IState> {
|
||||
indicatorStyles.indicatorContainer as StyleProp<ViewStyle>,
|
||||
{ backgroundColor: indicatorColor }
|
||||
] }>
|
||||
{/* @ts-ignore */}
|
||||
<BaseIndicator
|
||||
icon = { IconConnection }
|
||||
// @ts-ignore
|
||||
iconStyle = { this.props.iconStyle || iconStyle } />
|
||||
</View>
|
||||
);
|
||||
@@ -185,7 +177,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<IProps, IState> {
|
||||
* @param {IProps} ownProps - The own props of the component.
|
||||
* @returns {IProps}
|
||||
*/
|
||||
export function _mapStateToProps(state: IReduxState, ownProps: IProps) {
|
||||
export function _mapStateToProps(state: IReduxState, ownProps: any) {
|
||||
const { participantId } = ownProps;
|
||||
const tracks = state['features/base/tracks'];
|
||||
const participant = participantId ? getParticipantById(state, participantId) : getLocalParticipant(state);
|
||||
@@ -212,5 +204,4 @@ export function _mapStateToProps(state: IReduxState, ownProps: IProps) {
|
||||
};
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
export default connect(_mapStateToProps)(ConnectionIndicator);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* @flow */
|
||||
|
||||
/**
|
||||
* The type of the action which signals to open the conference in the desktop
|
||||
* app.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user