Compare commits

..

2 Commits

Author SHA1 Message Date
Alex Bumbu
95ccc2cbe1 fix methods naming for swift 2022-09-14 16:17:42 +03:00
Alex Bumbu
468d77c3d6 feat(iOS): callkit objc implementation 2022-09-14 16:17:42 +03:00
400 changed files with 2395 additions and 2759 deletions

View File

@@ -1,6 +1,5 @@
module.exports = {
'extends': [
'@jitsi/eslint-config'
],
'ignorePatterns': [ '*.d.ts' ]
]
};

View File

@@ -1,11 +0,0 @@
#!/bin/bash
PKG_NAME=${1:-org.jitsi.meet}
APP_PID=$(adb shell ps | grep $PKG_NAME | awk '{print $2}')
if [[ -z "$APP_PID" ]]; then
echo "App is not running"
exit 1
fi
exec adb logcat --pid=$APP_PID

View File

@@ -77,7 +77,6 @@ dependencies {
implementation project(':react-native-immersive')
implementation project(':react-native-keep-awake')
implementation project(':react-native-masked-view_masked-view')
implementation project(':react-native-orientation-locker')
implementation project(':react-native-pager-view')
implementation project(':react-native-performance')
implementation project(':react-native-safe-area-context')

View File

@@ -21,7 +21,6 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
@@ -31,7 +30,6 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.facebook.react.modules.core.PermissionListener;
import org.wonday.orientation.OrientationActivityLifecycle;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.HashMap;
@@ -88,14 +86,6 @@ public class JitsiMeetActivity extends AppCompatActivity
// Overrides
//
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Intent intent = new Intent("onConfigurationChanged");
intent.putExtra("newConfig", newConfig);
this.sendBroadcast(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -104,7 +94,6 @@ public class JitsiMeetActivity extends AppCompatActivity
this.jitsiView = findViewById(R.id.jitsiView);
registerForBroadcastMessages();
registerActivityLifecycleCallbacks(OrientationActivityLifecycle.getInstance());
if (!extraInitialize()) {
initialize();

View File

@@ -85,7 +85,6 @@ class ReactInstanceManagerHolder {
WebRTCModule.Options options = new WebRTCModule.Options();
AudioDeviceModule adm = JavaAudioDeviceModule.builder(reactContext)
.setEnableVolumeLogger(false)
.createAudioDeviceModule();
options.setAudioDeviceModule(adm);
@@ -129,7 +128,6 @@ class ReactInstanceManagerHolder {
new com.zmxv.RNSound.RNSoundPackage(),
new com.th3rdwave.safeareacontext.SafeAreaContextPackage(),
new com.horcrux.svg.SvgPackage(),
new org.wonday.orientation.OrientationPackage(),
new ReactPackageAdapter() {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {

View File

@@ -33,8 +33,6 @@ include ':react-native-keep-awake'
project(':react-native-keep-awake').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-keep-awake/android')
include ':react-native-masked-view_masked-view'
project(':react-native-masked-view_masked-view').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-masked-view/masked-view/android')
include ':react-native-orientation-locker'
project(':react-native-orientation-locker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-orientation-locker/android')
include ':react-native-pager-view'
project(':react-native-pager-view').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-pager-view/android')
include ':react-native-performance'

View File

@@ -15,8 +15,8 @@ import Recorder from './modules/recorder/Recorder';
import { createTaskQueue } from './modules/util/helpers';
import {
createDeviceChangedEvent,
createScreenSharingEvent,
createStartSilentEvent,
createScreenSharingEvent,
createTrackMutedEvent,
sendAnalytics
} from './react/features/analytics';
@@ -30,15 +30,14 @@ import { shouldShowModeratedNotification } from './react/features/av-moderation/
import { setAudioOnly } from './react/features/base/audio-only';
import {
AVATAR_URL_COMMAND,
CONFERENCE_LEAVE_REASONS,
EMAIL_COMMAND,
_conferenceWillJoin,
authStatusChanged,
commonUserJoinedHandling,
commonUserLeftHandling,
conferenceFailed,
conferenceJoinInProgress,
conferenceJoined,
conferenceJoinInProgress,
conferenceLeft,
conferenceSubjectChanged,
conferenceTimestampChanged,
@@ -50,14 +49,15 @@ import {
getConferenceOptions,
kickedOut,
lockStateChanged,
nonParticipantMessageReceived,
onStartMutedPolicyChanged,
p2pStatusChanged,
sendLocalParticipant
sendLocalParticipant,
nonParticipantMessageReceived,
CONFERENCE_LEAVE_REASONS
} from './react/features/base/conference';
import {
getMultipleVideoSendingSupportFeatureFlag,
getReplaceParticipant
getReplaceParticipant,
getMultipleVideoSendingSupportFeatureFlag
} from './react/features/base/config/functions';
import {
checkAndNotifyForNewDevice,
@@ -69,6 +69,7 @@ import {
updateDeviceList
} from './react/features/base/devices';
import {
browser,
JitsiConferenceErrors,
JitsiConferenceEvents,
JitsiConnectionErrors,
@@ -77,15 +78,14 @@ import {
JitsiMediaDevicesEvents,
JitsiParticipantConnectionStatus,
JitsiTrackErrors,
JitsiTrackEvents,
browser
JitsiTrackEvents
} from './react/features/base/lib-jitsi-meet';
import { isFatalJitsiConnectionError } from './react/features/base/lib-jitsi-meet/functions';
import {
MEDIA_TYPE,
getStartWithAudioMuted,
getStartWithVideoMuted,
isVideoMutedByUser,
MEDIA_TYPE,
setAudioAvailable,
setAudioMuted,
setAudioUnmutePermissions,
@@ -140,9 +140,9 @@ import {
import { maybeSetLobbyChatMessageListener } from './react/features/lobby/actions.any';
import { setNoiseSuppressionEnabled } from './react/features/noise-suppression/actions';
import {
NOTIFICATION_TIMEOUT_TYPE,
isModerationNotificationDisplayed,
showNotification
showNotification,
NOTIFICATION_TIMEOUT_TYPE
} from './react/features/notifications';
import { mediaPermissionPromptVisibilityChanged, toggleSlowGUMOverlay } from './react/features/overlay';
import { suspendDetected } from './react/features/power-monitor';
@@ -153,7 +153,7 @@ import {
setJoiningInProgress
} from './react/features/prejoin';
import { disableReceiver, stopReceiver } from './react/features/remote-control';
import { isScreenAudioShared, setScreenAudioShareState } from './react/features/screen-share/';
import { setScreenAudioShareState, isScreenAudioShared } from './react/features/screen-share/';
import { toggleScreenshotCaptureSummary } from './react/features/screenshot-capture';
import { isScreenshotCaptureEnabled } from './react/features/screenshot-capture/functions';
import { AudioMixerEffect } from './react/features/stream-effects/audio-mixer/AudioMixerEffect';
@@ -2291,9 +2291,7 @@ export default {
room.on(
JitsiConferenceEvents.DOMINANT_SPEAKER_CHANGED,
(dominant, previous, silence) => {
APP.store.dispatch(dominantSpeakerChanged(dominant, previous, Boolean(silence), room));
});
(dominant, previous) => APP.store.dispatch(dominantSpeakerChanged(dominant, previous, room)));
room.on(
JitsiConferenceEvents.CONFERENCE_CREATED_TIMESTAMP,
@@ -2985,6 +2983,7 @@ export default {
const available = audioDeviceCount > 0 || Boolean(localAudio);
APP.store.dispatch(setAudioAvailable(available));
APP.API.notifyAudioAvailabilityChanged(available);
},
/**
@@ -3248,6 +3247,7 @@ export default {
*/
setAudioMuteStatus(muted) {
APP.UI.setAudioMuted(this.getMyUserId(), muted);
APP.API.notifyAudioMutedStatusChanged(muted);
},
/**

View File

@@ -114,7 +114,7 @@ var config = {
// Signal that this client supports receiving multiple video streams. Without this flag jicofo will enable
// multi-stream backward compatibility.
// receiveMultipleVideoStreams: true,
receiveMultipleVideoStreams: true,
},
// Disables moderator indicators.
@@ -824,7 +824,7 @@ var config = {
// Application ID and Secret.
// callStatsID: '',
// callStatsSecret: '',
// callStatsApplicationLogsDisabled: false,
// callstatsStoreLogs: true,
// The callstats initialize config params as described in the API:
// https://docs.callstats.io/docs/javascript#callstatsinitialize-with-app-secret
@@ -1441,10 +1441,6 @@ var config = {
// // (displaying multiple participants on stage besides the vertical filmstrip)
// disableStageFilmstrip: false,
// // Default number of participants that can be displayed on stage.
// // The user can change this in settings. Number must be between 1 and 6.
// stageFilmstripParticipants: 1,
// // Disables the top panel (only shown when a user is sharing their screen).
// disableTopPanel: false,

View File

@@ -19,7 +19,7 @@ import {
} from './react/features/base/lib-jitsi-meet';
import { isFatalJitsiConnectionError } from './react/features/base/lib-jitsi-meet/functions';
import { getCustomerDetails } from './react/features/jaas/actions.any';
import { getJaasJWT, isVpaasMeeting } from './react/features/jaas/functions';
import { isVpaasMeeting, getJaasJWT } from './react/features/jaas/functions';
import {
setPrejoinDisplayNameRequired
} from './react/features/prejoin/actions';

View File

@@ -22,7 +22,7 @@
display: flex;
flex-direction: column;
// extract header + tabs height
height: calc(100% - 119px);
height: calc(100% - 102px);
}
.chat-panel-no-tabs {
@@ -531,3 +531,41 @@
background: #36383C;
border-radius: 3px;
}
.chat-tabs-container {
width: 100%;
border-bottom: thin solid #292929;
display: flex;
justify-content: space-around;
}
.chat-tab {
font-size: 1.2em;
padding-bottom: 0.5em;
width: 50%;
text-align: center;
color: #8B8B8B;
cursor: pointer;
}
.chat-tab-focus {
border-bottom-style: solid;
color: #FFF;
}
.chat-tab-title {
margin-right: 8px;
}
.chat-tab-badge {
background-color: #165ecc;
border-radius: 50%;
box-sizing: border-box;
font-weight: 700;
overflow: hidden;
text-align: center;
text-overflow: ellipsis;
vertical-align: middle;
padding: 0 4px;
color: #FFF;
}

View File

@@ -310,7 +310,7 @@ ol.poll-result-list {
}
#polls-panel {
height: calc(100% - 119px);
height: calc(100% - 102px);
}
.poll-container {

View File

@@ -83,28 +83,16 @@ case "$1" in
TURN_SECRET="$RET"
fi
db_get jitsi-meet/jaas-choice
JAAS_INPUT="$RET"
# In the case of updating from an older version the configure of -prosody package may happen before the -config
# one, so if JAAS_INPUT is empty (the question is not asked), let's ask it now.
db_get jitsi-meet/cert-choice
CERT_CHOICE="$RET"
if [ -z "$CERT_CHOICE" ] ; then
db_input critical jitsi-meet/cert-choice || true
if [ -z "$JAAS_INPUT" ] ; then
db_subst jitsi-meet/jaas-choice domain "${JVB_HOSTNAME}"
db_input critical jitsi-meet/jaas-choice || true
db_go
db_get jitsi-meet/cert-choice
CERT_CHOICE="$RET"
fi
SELF_SIGNED_CHOICE="Generate a new self-signed certificate"
if [ "$CERT_CHOICE" != "$SELF_SIGNED_CHOICE" ]; then
db_get jitsi-meet/jaas-choice
JAAS_INPUT="$RET"
if [ -z "$JAAS_INPUT" ] ; then
db_subst jitsi-meet/jaas-choice domain "${JVB_HOSTNAME}"
db_set jitsi-meet/jaas-choice false
db_input critical jitsi-meet/jaas-choice || true
db_go
db_get jitsi-meet/jaas-choice
JAAS_INPUT="$RET"
fi
fi
# and we're done with debconf

View File

@@ -68,6 +68,12 @@ case "$1" in
FORCE_NGINX="false"
fi
db_subst jitsi-meet/jaas-choice domain "${JVB_HOSTNAME}"
db_input critical jitsi-meet/jaas-choice || true
db_go
db_get jitsi-meet/jaas-choice
JAAS_INPUT="$RET"
UPLOADED_CERT_CHOICE="I want to use my own certificate"
LE_CERT_CHOICE="Let's Encrypt certificates"
# if first time config ask for certs, or if we are reconfiguring
@@ -136,20 +142,6 @@ case "$1" in
sed -i "s/jitsi-meet.example.com/$JVB_HOSTNAME/g" $JITSI_MEET_CONFIG
fi
if [ "$CERT_CHOICE" = "$LE_CERT_CHOICE" ] || [ "$CERT_CHOICE" = "$UPLOADED_CERT_CHOICE" ]; then
# Make sure jaas-choice is not answered already
db_get jitsi-meet/jaas-choice
JAAS_INPUT="$RET"
if [ -z "$JAAS_INPUT" ] ; then
db_subst jitsi-meet/jaas-choice domain "${JVB_HOSTNAME}"
db_set jitsi-meet/jaas-choice false
db_input critical jitsi-meet/jaas-choice || true
db_go
db_get jitsi-meet/jaas-choice
JAAS_INPUT="$RET"
fi
fi
if [ "${JAAS_INPUT}" = "true" ] && ! grep -q "^var enableJaaS = true;$" $JITSI_MEET_CONFIG; then
if grep -q "^var enableJaaS = false;$" $JITSI_MEET_CONFIG; then
sed -i "s/^var enableJaaS = false;$/var enableJaaS = true;/g" $JITSI_MEET_CONFIG
@@ -228,15 +220,8 @@ case "$1" in
invoke-rc.d apache2 reload || true
fi
# If scripts fail they will print suggestions for next steps, do not fail install
# those can be re-run later
# run the scripts only on new install or when re-configuring
if [[ "$ISSUE_LE_CERT" = "true" && ( -z "$JVB_HOSTNAME_OLD" || "$RECONFIGURING" = "true" ) ]] ; then
/usr/share/jitsi-meet/scripts/install-letsencrypt-cert.sh $EMAIL $JVB_HOSTNAME || true
fi
JAAS_REG_ERROR=0
if [[ "${JAAS_INPUT}" = "true" && ( -z "$JVB_HOSTNAME_OLD" || "$RECONFIGURING" = "true" ) ]] ; then
/usr/share/jitsi-meet/scripts/register-jaas-account.sh $EMAIL $JVB_HOSTNAME || JAAS_REG_ERROR=$?
if [ "$ISSUE_LE_CERT" = "true" ] ; then
/usr/share/jitsi-meet/scripts/install-letsencrypt-cert.sh $EMAIL $JVB_HOSTNAME
fi
echo ""
@@ -247,16 +232,16 @@ case "$1" in
echo " .xMMMMNxkNc"
echo " dMMMMMkxXc"
echo " cNMMMNl.."
if [ "${JAAS_INPUT}" != "true" ] || [ ${JAAS_REG_ERROR} -ne 0 ]; then
if [ "${JAAS_INPUT}" != "true" ]; then
echo " .kMMMX; Interested in adding telephony to your Jitsi meetings?"
echo " ;XMMMO'"
echo " lNMMWO' Sign up on https://jaas.8x8.vc/components?host=${JVB_HOSTNAME}"
echo " lNMMM0, and follow the guide in the dev console."
else
echo " .kMMMX;"
echo " ;XMMMO' Congratulations! Now you can use telephony in your Jitsi meetings!"
echo " lNMMWO' We have created a free JaaS (Jitsi as a Service) account for you. "
echo " lNMMM0, You can login to https://jaas.8x8.vc/components to check our developer console and your account details."
echo " ;XMMMO' Don't forget to sign up on"
echo " lNMMWO' https://jaas.8x8.vc/components?host=${JVB_HOSTNAME}"
echo " lNMMM0, in order to add telephony to your Jitsi meetings!"
fi
echo " lXMMMK:."
echo " ;KMMMNKd. 'oo,"

View File

@@ -1,13 +1,16 @@
Template: jitsi-meet/cert-choice
Type: select
__Choices: Let's Encrypt certificates, I want to use my own certificate, Generate a new self-signed certificate
_Description: SSL certificate
__Choices: Generate a new self-signed certificate, Let's Encrypt certificates, I want to use my own certificate
_Description: SSL certificate for the Jitsi Meet instance
.
Jitsi Meet requires an SSL certificate. This installer can generate one automatically for your using "Lets Encrypt". This is the recommended and simplest option for most installations.
Jitsi Meet is best to be set up with an SSL certificate.
.
In the event you need to use a certificate of your own, you can configure its location which defaults to /etc/ssl/--domain.name--.key for the key and /etc/ssl/--domain.name--.crt for the certificate.
Having no certificate, a self-signed one will be generated.
In the case of using a self-signed certificate, only the web app will be available with some warnings, the mobile app will not connect.
Self-signed certificates are not supported by JaaS (Jitsi as a Service).
.
If you are a developer and are only looking for a quick way to test basic Jitsi Meet functionality then this installer can also generate a self-signed certificate.
Having a certificate signed by a recognised CA, it can be uploaded on the server and point its location.
The default filenames will be /etc/ssl/--domain.name--.key for the key and /etc/ssl/--domain.name--.crt for the certificate.
Template: jitsi-meet/cert-path-key
Type: string
@@ -34,7 +37,10 @@ _Description: Hostname:
Template: jitsi-meet/jaas-choice
Type: boolean
_Description: Interested in adding telephony to your Jitsi meetings?
You can easily add dialing in support to your meetings. You need to give us the permission to create a free JaaS (Jitsi as a Service) account for you.
You can easily add dialing in support to your meetings using JaaS (Jitsi as a Service).
You need to:
- have a certificate signed by a recognised CA or Lets Encrypt on your deployment
- sign in for JaaS at https://jaas.8x8.vc/components?host=${domain}
Template: jitsi-meet/email
Type: string
@@ -44,6 +50,4 @@ _Description: Enter your email:
You need a working DNS record pointing to this machine(for hostname ${domain})"
.
You need to agree to the ACME server's Subscriber Agreement (https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf)
by providing an email address for important account notifications.
.
We will use the email for creating your JaaS (Jitsi as a Service) account if that option was selected.
by providing an email address for important account notifications

18
globals.d.ts vendored
View File

@@ -1,18 +0,0 @@
import { IStore } from "./react/features/app/types";
import { IConfig } from "./react/features/base/config/configType";
export {};
declare global {
const APP: {
store: IStore;
UI: any;
API: any;
conference: any;
};
const interfaceConfig: any;
interface Window {
config?: IConfig;
}
}

View File

@@ -72,13 +72,8 @@ post_install do |installer|
react_native_post_install(installer)
__apply_Xcode_12_5_M1_post_install_workaround(installer)
installer.pods_project.targets.each do |target|
# https://github.com/CocoaPods/CocoaPods/issues/11402
if target.respond_to?(:product_type) and target.product_type == "com.apple.product-type.bundle"
target.build_configurations.each do |config|
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
end
end
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'YES'
config.build_settings['SUPPORTS_MACCATALYST'] = 'NO'
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'
end

View File

@@ -366,8 +366,6 @@ PODS:
- React
- react-native-netinfo (7.1.7):
- React-Core
- react-native-orientation-locker (1.5.0):
- React-Core
- react-native-pager-view (5.4.9):
- React-Core
- react-native-performance (2.1.0):
@@ -384,7 +382,7 @@ PODS:
- react-native-video/Video (6.0.0-alpha.1):
- PromisesSwift
- React-Core
- react-native-webrtc (1.106.0):
- react-native-webrtc (1.100.1):
- React-Core
- react-native-webview (11.15.1):
- React-Core
@@ -516,7 +514,6 @@ DEPENDENCIES:
- react-native-get-random-values (from `../node_modules/react-native-get-random-values`)
- react-native-keep-awake (from `../node_modules/react-native-keep-awake`)
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
- react-native-orientation-locker (from `../node_modules/react-native-orientation-locker`)
- react-native-pager-view (from `../node_modules/react-native-pager-view`)
- react-native-performance (from `../node_modules/react-native-performance/ios`)
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
@@ -626,8 +623,6 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-keep-awake"
react-native-netinfo:
:path: "../node_modules/@react-native-community/netinfo"
react-native-orientation-locker:
:path: "../node_modules/react-native-orientation-locker"
react-native-pager-view:
:path: "../node_modules/react-native-pager-view"
react-native-performance:
@@ -743,14 +738,13 @@ SPEC CHECKSUMS:
react-native-get-random-values: 30b3f74ca34e30e2e480de48e4add2706a40ac8f
react-native-keep-awake: afad8a51dfef9fe9655a6344771be32c8596d774
react-native-netinfo: 27f287f2d191693f3b9d01a4273137fcf91c3b5d
react-native-orientation-locker: 851f6510d8046ea2f14aa169b1e01fcd309a94ba
react-native-pager-view: 3ee7d4c7697fb3ef788346e834a60cca97ed8540
react-native-performance: f4b6604a9d5a8a7407e34a82fab6c641d9a3ec12
react-native-safe-area-context: 584dc04881deb49474363f3be89e4ca0e854c057
react-native-slider: 6e9b86e76cce4b9e35b3403193a6432ed07e0c81
react-native-splash-screen: 4312f786b13a81b5169ef346d76d33bc0c6dc457
react-native-video: bb6f12a7198db53b261fefb5d609dc77417acc8b
react-native-webrtc: ae0a19dd7de9889f7596989f33db67c58632323c
react-native-webrtc: 206a0ac12a5633d2ec4605174d7c9f12f0d674b2
react-native-webview: ea4899a1056c782afa96dd082179a66cbebf5504
React-perflogger: 30ab8d6db10e175626069e742eead3ebe8f24fd5
React-RCTActionSheet: 4b45da334a175b24dabe75f856b98fed3dfd6201
@@ -778,6 +772,6 @@ SPEC CHECKSUMS:
RNWatch: dae6c858a2051dbdcfb00b9a86cf4d90400263b4
Yoga: 17cd9a50243093b547c1e539c749928dd68152da
PODFILE CHECKSUM: 55f1a79792dd5f74b7510fc84068abcb79ddd518
PODFILE CHECKSUM: a437875b597d999a137c671b1da54153fe31d23f
COCOAPODS: 1.11.3

View File

@@ -854,6 +854,7 @@
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = NO;
DEVELOPMENT_TEAM = FC967L3QRG;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
INFOPLIST_FILE = src/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
@@ -884,6 +885,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = FC967L3QRG;
ENABLE_BITCODE = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
INFOPLIST_FILE = src/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
@@ -1001,6 +1003,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_BITCODE = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
@@ -1061,6 +1064,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
ENABLE_BITCODE = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";

View File

@@ -124,10 +124,4 @@
options:options];
}
- (UIInterfaceOrientationMask)application:(UIApplication *)application
supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return [[JitsiMeet sharedInstance] application:application
supportedInterfaceOrientationsForWindow:window];
}
@end

View File

@@ -78,6 +78,7 @@ platform :ios do
# Actually build the app
build_app(
scheme: "JitsiMeet",
include_bitcode: true,
include_symbols: true,
export_xcargs: "-allowProvisioningUpdates"
)

View File

@@ -35,6 +35,7 @@ xcodebuild archive \
-sdk iphonesimulator \
-destination='generic/platform=iOS Simulator' \
-archivePath ios/sdk/out/ios-simulator \
ENABLE_BITCODE=NO \
SKIP_INSTALL=NO \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
xcodebuild archive \
@@ -44,6 +45,7 @@ xcodebuild archive \
-sdk iphoneos \
-destination='generic/platform=iOS' \
-archivePath ios/sdk/out/ios-device \
ENABLE_BITCODE=NO \
SKIP_INSTALL=NO \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
xcodebuild -create-xcframework \

View File

@@ -12,6 +12,8 @@ DO_GIT_TAG=${GIT_TAG:-0}
echo "Releasing Jitsi Meet SDK ${SDK_VERSION}"
${THIS_DIR}/../../node_modules/react-native-webrtc/tools/downloadBitcode.sh
pushd ${RELEASE_REPO}
# Generate podspec file
@@ -35,6 +37,7 @@ xcodebuild archive \
-sdk iphonesimulator \
-destination='generic/platform=iOS Simulator' \
-archivePath ios/sdk/out/ios-simulator \
ENABLE_BITCODE=YES \
SKIP_INSTALL=NO \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
xcodebuild archive \
@@ -44,6 +47,7 @@ xcodebuild archive \
-sdk iphoneos \
-destination='generic/platform=iOS' \
-archivePath ios/sdk/out/ios-device \
ENABLE_BITCODE=YES \
SKIP_INSTALL=NO \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
xcodebuild -create-xcframework \

View File

@@ -43,7 +43,7 @@
4ED4FFF42721B9B90074E620 /* JitsiAudioSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 4ED4FFF22721B9B90074E620 /* JitsiAudioSession.m */; };
4EEC9630286C73A2008705FA /* JitsiMeetView+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4EEC962E286C73A2008705FA /* JitsiMeetView+Private.h */; };
4EEC9631286C73A2008705FA /* JitsiMeetView+Private.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EEC962F286C73A2008705FA /* JitsiMeetView+Private.m */; };
6F08DF7D4458EE3CF3F36F6D /* BuildFile in Frameworks */ = {isa = PBXBuildFile; };
6F08DF7D4458EE3CF3F36F6D /* (null) in Frameworks */ = {isa = PBXBuildFile; };
9A8EE79C77C17743BB66E8BD /* libPods-JitsiMeetSDKLite.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B46497DE9A95BDF5E312AF48 /* libPods-JitsiMeetSDKLite.a */; };
A4A934E9212F3ADB001E9388 /* Dropbox.m in Sources */ = {isa = PBXBuildFile; fileRef = A4A934E8212F3ADB001E9388 /* Dropbox.m */; };
C6245F5D2053091D0040BE68 /* image-resize@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C6245F5B2053091D0040BE68 /* image-resize@2x.png */; };
@@ -206,7 +206,7 @@
files = (
0BB9AD791F5EC6D7001C08DB /* Intents.framework in Frameworks */,
0BB9AD771F5EC6CE001C08DB /* CallKit.framework in Frameworks */,
6F08DF7D4458EE3CF3F36F6D /* BuildFile in Frameworks */,
6F08DF7D4458EE3CF3F36F6D /* (null) in Frameworks */,
3453F4A32680898C4A40E821 /* libPods-JitsiMeetSDK.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -788,6 +788,7 @@
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_BITCODE = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
@@ -850,6 +851,7 @@
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_BITCODE = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
@@ -886,6 +888,7 @@
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
INFOPLIST_FILE = src/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -915,6 +918,7 @@
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_BITCODE = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
INFOPLIST_FILE = src/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -943,6 +947,7 @@
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
@@ -977,6 +982,7 @@
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_BITCODE = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",

View File

@@ -57,9 +57,6 @@
openURL:(NSURL *_Nonnull)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *_Nonnull)options;
- (UIInterfaceOrientationMask)application:(UIApplication *)application
supportedInterfaceOrientationsForWindow:(UIWindow *)window;
#pragma mark - Utility methods
/**

View File

@@ -16,7 +16,6 @@
#import <Intents/Intents.h>
#import <WebRTC/RTCLogging.h>
#import "Orientation.h"
#import "JitsiMeet+Private.h"
#import "JitsiMeetConferenceOptions+Private.h"
@@ -128,10 +127,6 @@
return true;
}
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return [Orientation getOrientation];
}
#pragma mark - Utility methods
- (void)instantiateReactNativeBridge {

34
lang/languages-fy.json Normal file
View File

@@ -0,0 +1,34 @@
{
"af": "",
"bg": "",
"ca": "",
"cs": "",
"da": "",
"de": "",
"el": "",
"en": "",
"enGB": "",
"eo": "",
"es": "",
"esUS": "",
"et": "",
"fi": "",
"fr": "",
"frCA": "",
"hr": "",
"hu": "",
"hy": "",
"it": "",
"ja": "",
"ko": "",
"nl": "",
"oc": "",
"pl": "",
"ptBR": "",
"ru": "",
"sv": "",
"tr": "",
"vi": "",
"zhCN": "",
"zhTW": ""
}

36
lang/languages-ka.json Normal file
View File

@@ -0,0 +1,36 @@
{
"af": "აფრიკული",
"bg": "ბულგარული",
"ca": "კატალონიური",
"cs": "ჩეხური",
"da": "დანიური",
"de": "გერმანული",
"el": "ბერძნული",
"en": "ინგლისური",
"enGB": "ინგლისური (დიდი ბრიტანეთი)",
"eo": "ესტონური",
"es": "ესპანური",
"esUS": "ესპანური (ლათინური ამერიკა)",
"et": "ესტონური",
"fi": "ფინური",
"fr": "ფრანგული",
"frCA": "ფრანგული (კანადური)",
"hr": "ხორვატიული",
"hu": "უნგრული",
"hy": "სომხური",
"it": "იტალიური",
"ja": "იაპონური",
"ka": "ქართული",
"ko": "კორეული",
"nl": "ჰოლანდიური",
"oc": "ოქსიტანური",
"pl": "პოლონური",
"ptBR": "პორტუგალიური (ბრაზილია)",
"ru": "რუსული",
"sr": "სერბული",
"sv": "შვედური",
"tr": "თურქული",
"vi": "ვიეტნამური",
"zhCN": "ჩინური (ჩინეთი)",
"zhTW": "ჩინური (ტაივანი)"
}

27
lang/languages-km.json Normal file
View File

@@ -0,0 +1,27 @@
{
"af": "អាហ្វ្រិច",
"az": "Azerbaijani",
"bg": "ប៊ុលហ្គារី",
"cs": "ឆេក",
"de": "អាល្លឺម៉ង់",
"el": "ក្រិក",
"en": "អង់គ្លេស",
"eo": "Esperanto",
"es": "អេស្ប៉ាញ",
"fr": "បារាំង",
"hy": "ភាសាអាមេនី",
"it": "អ៊ីតាលី",
"ja": "ជប៉ុន",
"ko": "កូរ៉េ",
"nb": "ន័រវេបាំម៉ាល",
"oc": "អុកស៊ីត",
"pl": "ប៉ូឡូញ",
"ptBR": "ព័រទុយហ្គាល់",
"ru": "រុស្ស៊ី",
"sk": "ស្លូវ៉ាគី",
"sl": "ស្លូវ៉ានី",
"sv": "ស៊ុយអែត",
"tr": "ទួរគី",
"vi": "វៀតណាម",
"zhCN": "ចិន (ចិន)"
}

View File

@@ -239,7 +239,7 @@
"cameraNotSendingData": "Não podemos aceder à sua câmara. Verifique se outra aplicação está a utilizar este dispositivo, seleccione outro dispositivo do menu de definições ou tente recarregar a aplicação.",
"cameraNotSendingDataTitle": "Não é possível aceder à câmara",
"cameraPermissionDeniedError": "Não concedeu autorização para utilizar a sua câmara. Ainda pode participar na conferência, mas outros não o verão. Use o botão da câmara na barra de endereço para corrigir isto.",
"cameraTimeoutError": "Não foi possível iniciar a fonte de vídeo. Tempo limite expirado!",
"cameraTimeoutError": "Não foi possível iniciar a fonte de vídeo. Tempo limite esgotado!",
"cameraUnknownError": "Não é possível utilizar a câmara por uma razão desconhecida.",
"cameraUnsupportedResolutionError": "A sua câmara não suporta a resolução de vídeo necessária.",
"close": "Fechar",
@@ -298,7 +298,7 @@
"micNotSendingData": "Vá às definições do seu computador para desligar o seu microfone e ajustar o seu nível",
"micNotSendingDataTitle": "O seu microfone está silenciado pelas definições do seu sistema",
"micPermissionDeniedError": "Não concedeu autorização para utilizar o seu microfone. Ainda pode participar na conferência, mas outros não o ouvirão. Use o botão da câmara na barra de endereço para corrigir isto.",
"micTimeoutError": "Não foi possível iniciar a fonte de áudio. Tempo limite expirado!",
"micTimeoutError": "Não foi possível iniciar a fonte de áudio. Tempo limite esgotado!",
"micUnknownError": "Não pode usar microfone por uma razão desconhecida.",
"moderationAudioLabel": "Permitir aos participantes reativar o som",
"moderationVideoLabel": "Permitir aos participantes reativar o vídeo",
@@ -965,7 +965,7 @@
"participantKnocking": "Entrar um participante na sala de espera",
"participantLeft": "Sair um participante",
"playSounds": "Reproduzir som quando",
"reactions": "Há uma reação na reunião",
"reactions": "Expressarem uma reação",
"sameAsSystem": "O mesmo que o sistema ({{label}})",
"screenTitle": "Definições",
"selectAudioOutput": "Saída de áudio",
@@ -1193,7 +1193,7 @@
"silence": "Silêncio",
"speakerStats": "Estatísticas dos participantes",
"startScreenSharing": "Iniciar partilha de ecrã",
"startSubtitles": "Legendas • {{language}}",
"startSubtitles": "Iniciar legendas",
"stopAudioSharing": "Parar partilha de áudio",
"stopScreenSharing": "Parar partilha de ecrã",
"stopSharedVideo": "Parar vídeo",
@@ -1216,8 +1216,6 @@
"pending": "Preparando a transcrição da reunião...",
"start": "Exibir legendas",
"stop": "Não exibir legendas",
"subtitles": "Legendas",
"subtitlesOff": "Desligado",
"tr": "TR"
},
"userMedia": {

View File

@@ -25,24 +25,24 @@ import {
setPassword,
setSubject
} from '../../react/features/base/conference';
import { getWhitelistedJSON, overwriteConfig } from '../../react/features/base/config';
import { overwriteConfig, getWhitelistedJSON } from '../../react/features/base/config';
import { toggleDialog } from '../../react/features/base/dialog/actions';
import { isSupportedBrowser } from '../../react/features/base/environment';
import { parseJWTFromURLParams } from '../../react/features/base/jwt';
import JitsiMeetJS, { JitsiRecordingConstants } from '../../react/features/base/lib-jitsi-meet';
import { MEDIA_TYPE } from '../../react/features/base/media';
import {
LOCAL_PARTICIPANT_DEFAULT_ID,
getLocalParticipant,
getParticipantById,
grantModerator,
hasRaisedHand,
isLocalParticipantModerator,
isParticipantModerator,
kickParticipant,
overwriteParticipantsNames,
pinParticipant,
raiseHand
kickParticipant,
raiseHand,
isParticipantModerator,
isLocalParticipantModerator,
hasRaisedHand,
grantModerator,
overwriteParticipantsNames,
LOCAL_PARTICIPANT_DEFAULT_ID
} from '../../react/features/base/participants';
import { updateSettings } from '../../react/features/base/settings';
import { getDisplayName } from '../../react/features/base/settings/functions.web';
@@ -68,8 +68,7 @@ import {
import { appendSuffix } from '../../react/features/display-name';
import { isEnabled as isDropboxEnabled } from '../../react/features/dropbox';
import { setMediaEncryptionKey, toggleE2EE } from '../../react/features/e2ee/actions';
import { addStageParticipant, resizeFilmStrip, setVolume } from '../../react/features/filmstrip/actions.web';
import { isStageFilmstripAvailable } from '../../react/features/filmstrip/functions.web';
import { resizeFilmStrip, setVolume } from '../../react/features/filmstrip/actions.web';
import { invite } from '../../react/features/invite';
import {
selectParticipantInLargeVideo
@@ -78,12 +77,12 @@ import {
captureLargeVideoScreenshot,
resizeLargeVideo
} from '../../react/features/large-video/actions.web';
import { answerKnockingParticipant, toggleLobbyMode } from '../../react/features/lobby/actions';
import { toggleLobbyMode, answerKnockingParticipant } from '../../react/features/lobby/actions';
import { setNoiseSuppressionEnabled } from '../../react/features/noise-suppression/actions';
import {
hideNotification,
NOTIFICATION_TIMEOUT_TYPE,
NOTIFICATION_TYPE,
hideNotification,
showNotification
} from '../../react/features/notifications';
import {
@@ -91,18 +90,17 @@ import {
open as openParticipantsPane
} from '../../react/features/participants-pane/actions';
import { getParticipantsPaneOpen, isForceMuted } from '../../react/features/participants-pane/functions';
import { startLocalVideoRecording, stopLocalVideoRecording } from '../../react/features/recording';
import { RECORDING_TYPES } from '../../react/features/recording/constants';
import { getActiveSession, supportsLocalRecording } from '../../react/features/recording/functions';
import { getActiveSession } from '../../react/features/recording/functions';
import { isScreenAudioSupported } from '../../react/features/screen-share';
import { startAudioScreenShareFlow, startScreenShareFlow } from '../../react/features/screen-share/actions';
import { startScreenShareFlow, startAudioScreenShareFlow } from '../../react/features/screen-share/actions';
import { toggleScreenshotCaptureSummary } from '../../react/features/screenshot-capture';
import { isScreenshotCaptureEnabled } from '../../react/features/screenshot-capture/functions';
import { playSharedVideo, stopSharedVideo } from '../../react/features/shared-video/actions.any';
import { extractYoutubeIdOrURL } from '../../react/features/shared-video/functions';
import { setRequestingSubtitles, toggleRequestingSubtitles } from '../../react/features/subtitles/actions';
import { toggleRequestingSubtitles, setRequestingSubtitles } from '../../react/features/subtitles/actions';
import { isAudioMuteButtonDisabled } from '../../react/features/toolbox/functions';
import { setTileView, toggleTileView } from '../../react/features/video-layout';
import { toggleTileView, setTileView } from '../../react/features/video-layout';
import { muteAllParticipants } from '../../react/features/video-menu/actions';
import { setVideoQuality } from '../../react/features/video-quality';
import VirtualBackgroundDialog from '../../react/features/virtual-background/components/VirtualBackgroundDialog';
@@ -237,11 +235,7 @@ function initCommands() {
'pin-participant': id => {
logger.debug('Pin participant command received');
sendAnalytics(createApiEvent('participant.pinned'));
if (isStageFilmstripAvailable(APP.store.getState())) {
APP.store.dispatch(addStageParticipant(id, true));
} else {
APP.store.dispatch(pinParticipant(id));
}
APP.store.dispatch(pinParticipant(id));
},
'proxy-connection-event': event => {
APP.conference.onProxyConnectionEvent(event);
@@ -550,12 +544,10 @@ function initCommands() {
* For youtube streams, `youtubeStreamKey` must be passed on. `youtubeBroadcastID` is optional.
* For dropbox recording, recording `mode` should be `file` and a dropbox oauth2 token must be provided.
* For file recording, recording `mode` should be `file` and optionally `shouldShare` could be passed on.
* For local recording, recording `mode` should be `local` and optionally `onlySelf` could be passed on.
* No other params should be passed.
*
* @param { string } arg.mode - Recording mode, either `local`, `file` or `stream`.
* @param { string } arg.mode - Recording mode, either `file` or `stream`.
* @param { string } arg.dropboxToken - Dropbox oauth2 token.
* @param { boolean } arg.onlySelf - Whether to only record the local streams.
* @param { string } arg.rtmpStreamKey - The RTMP stream key.
* @param { string } arg.rtmpBroadcastID - The RTMP broadcast ID.
* @param { boolean } arg.shouldShare - Whether the recording should be shared with the participants or not.
@@ -567,7 +559,6 @@ function initCommands() {
'start-recording': ({
mode,
dropboxToken,
onlySelf,
shouldShare,
rtmpStreamKey,
rtmpBroadcastID,
@@ -595,26 +586,7 @@ function initCommands() {
return;
}
if (mode === 'local') {
const { localRecording } = state['features/base/config'];
if (!localRecording?.disable && supportsLocalRecording()) {
APP.store.dispatch(startLocalVideoRecording(onlySelf));
} else {
logger.error('Failed starting recording: local recording is either disabled or not supported');
}
return;
}
let recordingConfig;
const { recordingService } = state['features/base/config'];
if (!recordingService.enabled && !dropboxToken) {
logger.error('Failed starting recording: the recording service is not enabled');
return;
}
if (mode === JitsiRecordingConstants.mode.FILE) {
if (dropboxToken) {
@@ -660,7 +632,7 @@ function initCommands() {
/**
* Stops a recording or streaming in progress.
*
* @param {string} mode - `local`, `file` or `stream`.
* @param {string} mode - `file` or `stream`.
* @returns {void}
*/
'stop-recording': mode => {
@@ -673,12 +645,6 @@ function initCommands() {
return;
}
if (mode === 'local') {
APP.store.dispatch(stopLocalVideoRecording());
return;
}
if (![ JitsiRecordingConstants.mode.FILE, JitsiRecordingConstants.mode.STREAM ].includes(mode)) {
logger.error('Invalid recording mode provided!');

View File

@@ -553,7 +553,6 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
this._myUserID = userID;
this._participants[userID] = {
email: data.email,
avatarURL: data.avatarURL
};
}

View File

@@ -12,10 +12,10 @@ import { setColorAlpha } from '../../react/features/base/util';
import { setDocumentUrl } from '../../react/features/etherpad';
import { setFilmstripVisible } from '../../react/features/filmstrip';
import {
NOTIFICATION_TIMEOUT_TYPE,
joinLeaveNotificationsDisabled,
setNotificationsEnabled,
showNotification
showNotification,
NOTIFICATION_TIMEOUT_TYPE
} from '../../react/features/notifications';
import {
dockToolbox,

View File

@@ -11,8 +11,8 @@ import {
WaitForOwnerDialog
} from '../../../react/features/authentication/components';
import {
getTokenAuthUrl,
isTokenAuthEnabled
isTokenAuthEnabled,
getTokenAuthUrl
} from '../../../react/features/authentication/functions';
import { getReplaceParticipant } from '../../../react/features/base/config/functions';
import { isDialogOpen } from '../../../react/features/base/dialog';

View File

@@ -34,7 +34,7 @@ import {
isTrackStreamingStatusInactive,
isTrackStreamingStatusInterrupted
} from '../../../react/features/connection-indicator/functions';
import { FILMSTRIP_BREAKPOINT, getVerticalViewMaxWidth, isFilmstripResizable } from '../../../react/features/filmstrip';
import { FILMSTRIP_BREAKPOINT, isFilmstripResizable, getVerticalViewMaxWidth } from '../../../react/features/filmstrip';
import {
updateKnownLargeVideoResolution
} from '../../../react/features/large-video/actions';
@@ -45,7 +45,7 @@ import { shouldDisplayTileView } from '../../../react/features/video-layout';
import { createDeferred } from '../../util/helpers';
import AudioLevels from '../audio_levels/AudioLevels';
import { VIDEO_CONTAINER_TYPE, VideoContainer } from './VideoContainer';
import { VideoContainer, VIDEO_CONTAINER_TYPE } from './VideoContainer';
const logger = Logger.getLogger(__filename);

View File

@@ -8,7 +8,7 @@ import ReactDOM from 'react-dom';
import { browser } from '../../../react/features/base/lib-jitsi-meet';
import { isTestModeEnabled } from '../../../react/features/base/testing';
import { FILMSTRIP_BREAKPOINT } from '../../../react/features/filmstrip';
import { LargeVideoBackground, ORIENTATION, updateLastLargeVideoMediaEvent } from '../../../react/features/large-video';
import { ORIENTATION, LargeVideoBackground, updateLastLargeVideoMediaEvent } from '../../../react/features/large-video';
import { setLargeVideoDimensions } from '../../../react/features/large-video/actions.any';
import { LAYOUTS, getCurrentLayout } from '../../../react/features/video-layout';
/* eslint-enable no-unused-vars */

View File

@@ -5,8 +5,8 @@ import Logger from '@jitsi/logger';
import { getMultipleVideoSupportFeatureFlag } from '../../../react/features/base/config';
import { MEDIA_TYPE, VIDEO_TYPE } from '../../../react/features/base/media';
import {
getParticipantById,
getPinnedParticipant
getPinnedParticipant,
getParticipantById
} from '../../../react/features/base/participants';
import {
getTrackByMediaTypeAndParticipant,

120
package-lock.json generated
View File

@@ -11,6 +11,7 @@
"license": "Apache-2.0",
"dependencies": {
"@amplitude/react-native": "2.7.0",
"@atlaskit/dropdown-menu": "10.1.2",
"@atlaskit/field-text-area": "8.0.4",
"@atlaskit/flag": "14.1.0",
"@atlaskit/icon": "21.2.0",
@@ -73,7 +74,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/v1506.0.0+3fc03265/lib-jitsi-meet.tgz",
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1498.0.0+bc3aae02/lib-jitsi-meet.tgz",
"lodash": "4.17.21",
"moment": "2.29.4",
"moment-duration-format": "2.2.2",
@@ -99,7 +100,6 @@
"react-native-get-random-values": "1.7.2",
"react-native-immersive": "2.0.0",
"react-native-keep-awake": "4.0.0",
"react-native-orientation-locker": "^1.5.0",
"react-native-pager-view": "5.4.9",
"react-native-paper": "4.11.1",
"react-native-performance": "2.1.0",
@@ -113,7 +113,7 @@
"react-native-url-polyfill": "1.3.0",
"react-native-video": "https://git@github.com/react-native-video/react-native-video#7c48ae7c8544b2b537fb60194e9620b9fcceae52",
"react-native-watch-connectivity": "1.0.11",
"react-native-webrtc": "https://git@github.com/react-native-webrtc/react-native-webrtc#ed07969a85c159953d3004cfd04d44792b95e8db",
"react-native-webrtc": "1.100.1",
"react-native-webview": "11.15.1",
"react-native-youtube-iframe": "2.2.1",
"react-redux": "7.1.0",
@@ -142,7 +142,7 @@
"@babel/preset-flow": "7.16.0",
"@babel/preset-react": "7.16.0",
"@babel/runtime": "7.16.0",
"@jitsi/eslint-config": "4.1.3",
"@jitsi/eslint-config": "4.1.2",
"@types/js-md5": "0.4.3",
"@types/lodash": "4.14.182",
"@types/react": "17.0.14",
@@ -372,6 +372,28 @@
"@babel/runtime": "^7.0.0"
}
},
"node_modules/@atlaskit/dropdown-menu": {
"version": "10.1.2",
"resolved": "https://registry.npmjs.org/@atlaskit/dropdown-menu/-/dropdown-menu-10.1.2.tgz",
"integrity": "sha512-1E03eM0aoXxwzTzRamnRrBsC9OX1mU2YATfDb45RZRmz+kOx0bw1q5xGXLQsHpUPZFgfK8rdFy8h94qvrucKsQ==",
"dependencies": {
"@atlaskit/analytics-next": "^8.0.0",
"@atlaskit/button": "^15.1.0",
"@atlaskit/droplist": "^11.0.0",
"@atlaskit/icon": "^21.1.0",
"@atlaskit/item": "^12.0.0",
"@atlaskit/theme": "^11.0.0",
"@babel/runtime": "^7.0.0",
"array-find": "^1.0.0",
"prop-types": "^15.5.10",
"react-uid": "^2.2.0"
},
"peerDependencies": {
"react": "^16.8.0",
"react-dom": "^16.8.0",
"styled-components": "^3.2.6"
}
},
"node_modules/@atlaskit/droplist": {
"version": "11.0.9",
"resolved": "https://registry.npmjs.org/@atlaskit/droplist/-/droplist-11.0.9.tgz",
@@ -3723,9 +3745,9 @@
}
},
"node_modules/@jitsi/eslint-config": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/@jitsi/eslint-config/-/eslint-config-4.1.3.tgz",
"integrity": "sha512-Fl3bvasAOREemcCdKXpBJDayuNl2CFIHkvNjUCqCs8uorHAMdagjbqBvg4ow7GnMamQdCrcdpIpZfeOmf+FTJQ==",
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/@jitsi/eslint-config/-/eslint-config-4.1.2.tgz",
"integrity": "sha512-kAkCLEKSWdwqj8L026T/5+FttvPLmNkPPETfgzG4SxWdkIVsW8wqFN/RypUZp2H7NmL5AgVL+QkXQXoEoQgW8A==",
"dev": true,
"peerDependencies": {
"@babel/eslint-parser": ">= 7",
@@ -7023,14 +7045,6 @@
"node": ">=0.4.0"
}
},
"node_modules/adm-zip": {
"version": "0.5.9",
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.9.tgz",
"integrity": "sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg==",
"engines": {
"node": ">=6.0"
}
},
"node_modules/agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@@ -7301,6 +7315,11 @@
"node": ">=0.10.0"
}
},
"node_modules/array-find": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/array-find/-/array-find-1.0.0.tgz",
"integrity": "sha1-bI4obRHtdoMn+OYuzuhzU8o+eLg="
},
"node_modules/array-flatten": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
@@ -13050,8 +13069,8 @@
},
"node_modules/lib-jitsi-meet": {
"version": "0.0.0",
"resolved": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1506.0.0+3fc03265/lib-jitsi-meet.tgz",
"integrity": "sha512-Dga5fB3eJwCnKlpxr4jQYoyfcL0si78tI+NOYGCn3Mc97FFmzxdjux0WLv6+/XFUqRnxTN/P57ECDXMCdyxysw==",
"resolved": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1498.0.0+bc3aae02/lib-jitsi-meet.tgz",
"integrity": "sha512-x796ul9mZXK+AaxxKL0FLmhUR23YibExkoBCsQr9LoSeN5mJskbRTQB8phTcnDbxFh4+0Xp+xzi7zOpuHsisWA==",
"license": "Apache-2.0",
"dependencies": {
"@jitsi/js-utils": "2.0.0",
@@ -15916,16 +15935,6 @@
"resolved": "https://registry.npmjs.org/react-native-keep-awake/-/react-native-keep-awake-4.0.0.tgz",
"integrity": "sha512-0Fotox+eLXQooeibVs3P60yASYUWjtRw9MZNmbuHt5UZQrgUrAKsE4jm7gTr4tPU1m1RkwGzcgUFpcOkh/ec7g=="
},
"node_modules/react-native-orientation-locker": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/react-native-orientation-locker/-/react-native-orientation-locker-1.5.0.tgz",
"integrity": "sha512-4XOCGmNN4BXg5JUFjUuXpsfhPJmbA3LkQilJO1ed+6vL97teTdG2w5IEevKiqL9/hPjeWE8YYtX/YW+yp53hkg==",
"peerDependencies": {
"react": ">=16.13.1",
"react-native": ">=0.63.2",
"react-native-windows": ">=0.63.3"
}
},
"node_modules/react-native-pager-view": {
"version": "5.4.9",
"resolved": "https://registry.npmjs.org/react-native-pager-view/-/react-native-pager-view-5.4.9.tgz",
@@ -16578,13 +16587,11 @@
}
},
"node_modules/react-native-webrtc": {
"version": "1.106.0",
"resolved": "git+https://git@github.com/react-native-webrtc/react-native-webrtc.git#ed07969a85c159953d3004cfd04d44792b95e8db",
"integrity": "sha512-hpYt1DuN0QCBuZOXoqR51AxIU2n0lKcGS2YGsww1wYXBCwVzKi6mhVyDVPNH7bU93UBXXnMCzLI4VJzv70GoYg==",
"version": "1.100.1",
"resolved": "https://registry.npmjs.org/react-native-webrtc/-/react-native-webrtc-1.100.1.tgz",
"integrity": "sha512-2dF8HrZWdfrbm1NLso424xgNeGFf4WK5Jlqs7ecVDvCMWHTYVHVwyNt52zx1yiOMEqQWk4edOd4xhWJfUiOvMg==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"adm-zip": "0.5.9",
"base64-js": "1.5.1",
"event-target-shim": "6.0.2",
"tar": "6.1.11"
@@ -20759,6 +20766,23 @@
"@babel/runtime": "^7.0.0"
}
},
"@atlaskit/dropdown-menu": {
"version": "10.1.2",
"resolved": "https://registry.npmjs.org/@atlaskit/dropdown-menu/-/dropdown-menu-10.1.2.tgz",
"integrity": "sha512-1E03eM0aoXxwzTzRamnRrBsC9OX1mU2YATfDb45RZRmz+kOx0bw1q5xGXLQsHpUPZFgfK8rdFy8h94qvrucKsQ==",
"requires": {
"@atlaskit/analytics-next": "^8.0.0",
"@atlaskit/button": "^15.1.0",
"@atlaskit/droplist": "^11.0.0",
"@atlaskit/icon": "^21.1.0",
"@atlaskit/item": "^12.0.0",
"@atlaskit/theme": "^11.0.0",
"@babel/runtime": "^7.0.0",
"array-find": "^1.0.0",
"prop-types": "^15.5.10",
"react-uid": "^2.2.0"
}
},
"@atlaskit/droplist": {
"version": "11.0.9",
"resolved": "https://registry.npmjs.org/@atlaskit/droplist/-/droplist-11.0.9.tgz",
@@ -23210,9 +23234,9 @@
}
},
"@jitsi/eslint-config": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/@jitsi/eslint-config/-/eslint-config-4.1.3.tgz",
"integrity": "sha512-Fl3bvasAOREemcCdKXpBJDayuNl2CFIHkvNjUCqCs8uorHAMdagjbqBvg4ow7GnMamQdCrcdpIpZfeOmf+FTJQ==",
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/@jitsi/eslint-config/-/eslint-config-4.1.2.tgz",
"integrity": "sha512-kAkCLEKSWdwqj8L026T/5+FttvPLmNkPPETfgzG4SxWdkIVsW8wqFN/RypUZp2H7NmL5AgVL+QkXQXoEoQgW8A==",
"dev": true
},
"@jitsi/js-utils": {
@@ -25656,11 +25680,6 @@
"integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
"dev": true
},
"adm-zip": {
"version": "0.5.9",
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.9.tgz",
"integrity": "sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg=="
},
"agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@@ -25869,6 +25888,11 @@
"resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
"integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ="
},
"array-find": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/array-find/-/array-find-1.0.0.tgz",
"integrity": "sha1-bI4obRHtdoMn+OYuzuhzU8o+eLg="
},
"array-flatten": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
@@ -30309,8 +30333,8 @@
}
},
"lib-jitsi-meet": {
"version": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1506.0.0+3fc03265/lib-jitsi-meet.tgz",
"integrity": "sha512-Dga5fB3eJwCnKlpxr4jQYoyfcL0si78tI+NOYGCn3Mc97FFmzxdjux0WLv6+/XFUqRnxTN/P57ECDXMCdyxysw==",
"version": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1498.0.0+bc3aae02/lib-jitsi-meet.tgz",
"integrity": "sha512-x796ul9mZXK+AaxxKL0FLmhUR23YibExkoBCsQr9LoSeN5mJskbRTQB8phTcnDbxFh4+0Xp+xzi7zOpuHsisWA==",
"requires": {
"@jitsi/js-utils": "2.0.0",
"@jitsi/logger": "2.0.0",
@@ -32514,11 +32538,6 @@
"resolved": "https://registry.npmjs.org/react-native-keep-awake/-/react-native-keep-awake-4.0.0.tgz",
"integrity": "sha512-0Fotox+eLXQooeibVs3P60yASYUWjtRw9MZNmbuHt5UZQrgUrAKsE4jm7gTr4tPU1m1RkwGzcgUFpcOkh/ec7g=="
},
"react-native-orientation-locker": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/react-native-orientation-locker/-/react-native-orientation-locker-1.5.0.tgz",
"integrity": "sha512-4XOCGmNN4BXg5JUFjUuXpsfhPJmbA3LkQilJO1ed+6vL97teTdG2w5IEevKiqL9/hPjeWE8YYtX/YW+yp53hkg=="
},
"react-native-pager-view": {
"version": "5.4.9",
"resolved": "https://registry.npmjs.org/react-native-pager-view/-/react-native-pager-view-5.4.9.tgz",
@@ -32904,11 +32923,10 @@
}
},
"react-native-webrtc": {
"version": "git+https://git@github.com/react-native-webrtc/react-native-webrtc.git#ed07969a85c159953d3004cfd04d44792b95e8db",
"integrity": "sha512-hpYt1DuN0QCBuZOXoqR51AxIU2n0lKcGS2YGsww1wYXBCwVzKi6mhVyDVPNH7bU93UBXXnMCzLI4VJzv70GoYg==",
"from": "react-native-webrtc@https://git@github.com/react-native-webrtc/react-native-webrtc#ed07969a85c159953d3004cfd04d44792b95e8db",
"version": "1.100.1",
"resolved": "https://registry.npmjs.org/react-native-webrtc/-/react-native-webrtc-1.100.1.tgz",
"integrity": "sha512-2dF8HrZWdfrbm1NLso424xgNeGFf4WK5Jlqs7ecVDvCMWHTYVHVwyNt52zx1yiOMEqQWk4edOd4xhWJfUiOvMg==",
"requires": {
"adm-zip": "0.5.9",
"base64-js": "1.5.1",
"event-target-shim": "6.0.2",
"tar": "6.1.11"

View File

@@ -16,6 +16,7 @@
"readmeFilename": "README.md",
"dependencies": {
"@amplitude/react-native": "2.7.0",
"@atlaskit/dropdown-menu": "10.1.2",
"@atlaskit/field-text-area": "8.0.4",
"@atlaskit/flag": "14.1.0",
"@atlaskit/icon": "21.2.0",
@@ -78,7 +79,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/v1506.0.0+3fc03265/lib-jitsi-meet.tgz",
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1498.0.0+bc3aae02/lib-jitsi-meet.tgz",
"lodash": "4.17.21",
"moment": "2.29.4",
"moment-duration-format": "2.2.2",
@@ -104,7 +105,6 @@
"react-native-get-random-values": "1.7.2",
"react-native-immersive": "2.0.0",
"react-native-keep-awake": "4.0.0",
"react-native-orientation-locker": "^1.5.0",
"react-native-pager-view": "5.4.9",
"react-native-paper": "4.11.1",
"react-native-performance": "2.1.0",
@@ -118,7 +118,7 @@
"react-native-url-polyfill": "1.3.0",
"react-native-video": "https://git@github.com/react-native-video/react-native-video#7c48ae7c8544b2b537fb60194e9620b9fcceae52",
"react-native-watch-connectivity": "1.0.11",
"react-native-webrtc": "https://git@github.com/react-native-webrtc/react-native-webrtc#ed07969a85c159953d3004cfd04d44792b95e8db",
"react-native-webrtc": "1.100.1",
"react-native-webview": "11.15.1",
"react-native-youtube-iframe": "2.2.1",
"react-redux": "7.1.0",
@@ -147,7 +147,7 @@
"@babel/preset-flow": "7.16.0",
"@babel/preset-react": "7.16.0",
"@babel/runtime": "7.16.0",
"@jitsi/eslint-config": "4.1.3",
"@jitsi/eslint-config": "4.1.2",
"@types/js-md5": "0.4.3",
"@types/lodash": "4.14.182",
"@types/react": "17.0.14",

View File

@@ -22,8 +22,8 @@ import {
} from '../base/util';
import { isVpaasMeeting } from '../jaas/functions';
import {
NOTIFICATION_TIMEOUT_TYPE,
clearNotifications,
NOTIFICATION_TIMEOUT_TYPE,
showNotification
} from '../notifications';
import { setFatalError } from '../overlay';

View File

@@ -6,7 +6,7 @@ import { hideDialog, openDialog } from '../base/dialog/actions';
import {
CANCEL_LOGIN
} from './actionTypes';
import { LoginDialog, WaitForOwnerDialog } from './components';
import { WaitForOwnerDialog, LoginDialog } from './components';
export * from './actions.any';

View File

@@ -4,7 +4,7 @@ import type { Dispatch } from 'redux';
import { ConfirmDialog } from '../../../base/dialog';
import { translate } from '../../../base/i18n';
import { connect } from '../../../base/redux';
import { cancelWaitForOwner, openLoginDialog } from '../../actions.native';
import { openLoginDialog, cancelWaitForOwner } from '../../actions.native';
/**
* The type of the React {@code Component} props of {@link WaitForOwnerDialog}.

View File

@@ -8,19 +8,19 @@ import { Participant } from '../base/participants/types';
import { isForceMuted } from '../participants-pane/functions';
import {
DISABLE_MODERATION,
DISMISS_PENDING_PARTICIPANT,
DISABLE_MODERATION,
ENABLE_MODERATION,
LOCAL_PARTICIPANT_APPROVED,
LOCAL_PARTICIPANT_MODERATION_NOTIFICATION,
LOCAL_PARTICIPANT_REJECTED,
PARTICIPANT_APPROVED,
PARTICIPANT_PENDING_AUDIO,
PARTICIPANT_REJECTED,
REQUEST_DISABLE_AUDIO_MODERATION,
REQUEST_DISABLE_VIDEO_MODERATION,
REQUEST_ENABLE_AUDIO_MODERATION,
REQUEST_ENABLE_VIDEO_MODERATION
REQUEST_DISABLE_VIDEO_MODERATION,
REQUEST_ENABLE_VIDEO_MODERATION,
LOCAL_PARTICIPANT_REJECTED,
PARTICIPANT_REJECTED
} from './actionTypes';
import { isEnabledFromState } from './functions';

View File

@@ -4,7 +4,7 @@ import { isLocalParticipantModerator } from '../base/participants/functions';
import { Participant } from '../base/participants/types';
import { isInBreakoutRoom } from '../breakout-rooms/functions';
import { MEDIA_TYPE_TO_PENDING_STORE_KEY, MEDIA_TYPE_TO_WHITELIST_STORE_KEY } from './constants';
import { MEDIA_TYPE_TO_WHITELIST_STORE_KEY, MEDIA_TYPE_TO_PENDING_STORE_KEY } from './constants';
/**
* Returns this feature's root state.

View File

@@ -5,7 +5,7 @@ import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app/actionTypes';
// @ts-ignore
import { getConferenceState } from '../base/conference';
import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
import { MEDIA_TYPE, MediaType } from '../base/media/constants';
import { MediaType, MEDIA_TYPE } from '../base/media/constants';
import { PARTICIPANT_UPDATED } from '../base/participants/actionTypes';
import { raiseHand } from '../base/participants/actions';
import {
@@ -40,13 +40,13 @@ import {
} from './actionTypes';
import {
disableModeration,
dismissPendingAudioParticipant,
dismissPendingParticipant,
dismissPendingAudioParticipant,
enableModeration,
localParticipantApproved,
localParticipantRejected,
participantApproved,
participantPendingAudio,
localParticipantRejected,
participantRejected
} from './actions';
import {

View File

@@ -1,7 +1,11 @@
import { IStore } from '../../app/types';
// @flow
import type { Dispatch } from 'redux';
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from './actionTypes';
declare var APP;
/**
* Signals that a specific App will mount (in the terms of React).
*
@@ -12,7 +16,7 @@ import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from './actionTypes';
* }}
*/
export function appWillMount(app: Object) {
return (dispatch: IStore['dispatch']) => {
return (dispatch: Dispatch<any>) => {
// TODO There was a redux action creator appInit which I did not like
// because we already had the redux action creator appWillMount and,
// respectively, the redux action APP_WILL_MOUNT. So I set out to remove

View File

@@ -1,19 +1,19 @@
import { toState } from '../redux/functions';
// @flow
import { IStateful } from './types';
import { toState } from '../redux';
/**
* Gets the value of a specific React {@code Component} prop of the currently
* mounted {@link App}.
*
* @param {IStateful} stateful - The redux store or {@code getState}
* @param {Function|Object} stateful - The redux store or {@code getState}
* function.
* @param {string} propName - The name of the React {@code Component} prop of
* the currently mounted {@code App} to get.
* @returns {*} The value of the specified React {@code Component} prop of the
* currently mounted {@code App}.
*/
export function getAppProp(stateful: IStateful, propName: string) {
export function getAppProp(stateful: Function | Object, propName: string) {
const state = toState(stateful)['features/base/app'];
if (state) {

View File

@@ -1,3 +1,5 @@
// @flow
import { getLogger } from '../logging/functions';
export default getLogger('features/base/app');

View File

@@ -3,7 +3,7 @@ import ReducerRegistry from '../redux/ReducerRegistry';
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from './actionTypes';
export interface IAppState {
app?: any;
app?: Object | undefined;
}
ReducerRegistry.register<IAppState>('features/base/app', (state = {}, action): IAppState => {

View File

@@ -7,7 +7,7 @@ import React, { useEffect, useState } from 'react';
import Icon from '../icons/components/Icon';
import { IconCheck, IconCopy } from '../icons/svg';
import { withPixelLineHeight } from '../styles/functions.web';
import { copyText } from '../util/copyText';
import { copyText } from '../util/helpers';
const styles = (theme: Theme) => {
return {

View File

@@ -41,8 +41,8 @@ import { getBackendSafeRoomName } from '../util';
import {
AUTH_STATUS_CHANGED,
CONFERENCE_FAILED,
CONFERENCE_JOINED,
CONFERENCE_JOIN_IN_PROGRESS,
CONFERENCE_JOINED,
CONFERENCE_LEFT,
CONFERENCE_LOCAL_SUBJECT_CHANGED,
CONFERENCE_SUBJECT_CHANGED,
@@ -61,8 +61,8 @@ import {
SET_OBFUSCATED_ROOM,
SET_PASSWORD,
SET_PASSWORD_FAILED,
SET_PENDING_SUBJECT_CHANGE,
SET_ROOM,
SET_PENDING_SUBJECT_CHANGE,
SET_START_MUTED_POLICY,
SET_START_REACTIONS_MUTED
} from './actionTypes';
@@ -76,8 +76,8 @@ import {
commonUserJoinedHandling,
commonUserLeftHandling,
getConferenceOptions,
getConferenceState,
getCurrentConference,
getConferenceState,
sendLocalParticipant
} from './functions';
import logger from './logger';
@@ -216,9 +216,7 @@ function _addConferenceListeners(conference, dispatch, state) {
conference.on(
JitsiConferenceEvents.DOMINANT_SPEAKER_CHANGED,
(dominant, previous, silence) => {
dispatch(dominantSpeakerChanged(dominant, previous, Boolean(silence), conference));
});
(dominant, previous) => dispatch(dominantSpeakerChanged(dominant, previous, conference)));
conference.on(
JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,

View File

@@ -1,24 +1,25 @@
// @flow
import { sha512_256 as sha512 } from 'js-sha512';
import _ from 'lodash';
// @ts-ignore
import { getName } from '../../app/functions';
import { IState, IStore } from '../../app/types';
import { determineTranscriptionLanguage } from '../../transcribing/functions';
import { IStateful } from '../app/types';
import { JitsiTrackErrors } from '../lib-jitsi-meet';
import {
getLocalParticipant,
hiddenParticipantJoined,
hiddenParticipantLeft,
participantJoined,
participantLeft
} from '../participants/actions';
import { getLocalParticipant } from '../participants/functions';
import { toState } from '../redux/functions';
import { getJitsiMeetGlobalNS } from '../util/helpers';
import { getBackendSafePath, safeDecodeURIComponent } from '../util/uri';
} from '../participants';
import { toState } from '../redux';
import {
getBackendSafePath,
getJitsiMeetGlobalNS,
safeDecodeURIComponent
} from '../util';
// @ts-ignore
import { setObfuscatedRoom } from './actions';
import {
AVATAR_URL_COMMAND,
@@ -26,23 +27,22 @@ import {
JITSI_CONFERENCE_URL_KEY
} from './constants';
import logger from './logger';
import { IJitsiConference } from './reducer';
/**
* Returns root conference state.
*
* @param {IState} state - Global state.
* @param {Object} state - Global state.
* @returns {Object} Conference state.
*/
export const getConferenceState = (state: IState) => state['features/base/conference'];
export const getConferenceState = (state: Object) => state['features/base/conference'];
/**
* Is the conference joined or not.
*
* @param {IState} state - Global state.
* @param {Object} state - Global state.
* @returns {boolean}
*/
export const getIsConferenceJoined = (state: IState) => Boolean(getConferenceState(state).conference);
export const getIsConferenceJoined = (state: Object) => Boolean(getConferenceState(state).conference);
/**
* Attach a set of local tracks to a conference.
@@ -53,7 +53,7 @@ export const getIsConferenceJoined = (state: IState) => Boolean(getConferenceSta
* @returns {Promise}
*/
export function _addLocalTracksToConference(
conference: IJitsiConference,
conference: { addTrack: Function, getLocalTracks: Function },
localTracks: Array<Object>) {
const conferenceLocalTracks = conference.getLocalTracks();
const promises = [];
@@ -63,7 +63,7 @@ export function _addLocalTracksToConference(
// adding one and the same video track multiple times.
if (conferenceLocalTracks.indexOf(track) === -1) {
promises.push(
conference.addTrack(track).catch((err: Error) => {
conference.addTrack(track).catch(err => {
_reportError(
'Failed to add local track to conference',
err);
@@ -86,16 +86,16 @@ export function _addLocalTracksToConference(
* @returns {void}
*/
export function commonUserJoinedHandling(
{ dispatch }: IStore,
conference: IJitsiConference,
user: any) {
{ dispatch }: Object,
conference: Object,
user: Object) {
const id = user.getId();
const displayName = user.getDisplayName();
if (user.isHidden()) {
dispatch(hiddenParticipantJoined(id, displayName));
} else {
const isReplacing = user?.isReplacing();
const isReplacing = user.isReplacing && user.isReplacing();
dispatch(participantJoined({
botType: user.getBotType(),
@@ -122,15 +122,15 @@ export function commonUserJoinedHandling(
* @returns {void}
*/
export function commonUserLeftHandling(
{ dispatch }: IStore,
conference: IJitsiConference,
user: any) {
{ dispatch }: Object,
conference: Object,
user: Object) {
const id = user.getId();
if (user.isHidden()) {
dispatch(hiddenParticipantLeft(id));
} else {
const isReplaced = user.isReplaced?.();
const isReplaced = user.isReplaced && user.isReplaced();
dispatch(participantLeft(id, conference, { isReplaced }));
}
@@ -140,7 +140,7 @@ export function commonUserLeftHandling(
* Evaluates a specific predicate for each {@link JitsiConference} known to the
* redux state features/base/conference while it returns {@code true}.
*
* @param {IStateful} stateful - The redux store, state, or
* @param {Function | Object} stateful - The redux store, state, or
* {@code getState} function.
* @param {Function} predicate - The predicate to evaluate for each
* {@code JitsiConference} know to the redux state features/base/conference
@@ -150,8 +150,8 @@ export function commonUserLeftHandling(
* features/base/conference.
*/
export function forEachConference(
stateful: IStateful,
predicate: (a: any, b: URL) => boolean) {
stateful: Function | Object,
predicate: (Object, URL) => boolean) {
const state = getConferenceState(toState(stateful));
for (const v of Object.values(state)) {
@@ -178,48 +178,48 @@ export function forEachConference(
/**
* Returns the display name of the conference.
*
* @param {IStateful} stateful - Reference that can be resolved to Redux
* @param {Function | Object} stateful - Reference that can be resolved to Redux
* state with the {@code toState} function.
* @returns {string}
*/
export function getConferenceName(stateful: IStateful): string {
export function getConferenceName(stateful: Function | Object): string {
const state = toState(stateful);
const { callee } = state['features/base/jwt'];
const { callDisplayName } = state['features/base/config'];
const { localSubject, room, subject } = getConferenceState(state);
return (localSubject
return localSubject
|| subject
|| callDisplayName
|| callee?.name
|| (room && safeStartCase(safeDecodeURIComponent(room)))) ?? '';
|| (callee && callee.name)
|| (room && safeStartCase(safeDecodeURIComponent(room)));
}
/**
* Returns the name of the conference formatted for the title.
*
* @param {IStateful} stateful - Reference that can be resolved to Redux state with the {@code toState}
* @param {Function | Object} stateful - Reference that can be resolved to Redux state with the {@code toState}
* function.
* @returns {string} - The name of the conference formatted for the title.
*/
export function getConferenceNameForTitle(stateful: IStateful) {
return safeStartCase(safeDecodeURIComponent(getConferenceState(toState(stateful)).room ?? ''));
export function getConferenceNameForTitle(stateful: Function | Object) {
return safeStartCase(safeDecodeURIComponent(getConferenceState(toState(stateful)).room));
}
/**
* Returns an object aggregating the conference options.
*
* @param {IStateful} stateful - The redux store state.
* @param {Object|Function} stateful - The redux store state.
* @returns {Object} - Options object.
*/
export function getConferenceOptions(stateful: IStateful) {
export function getConferenceOptions(stateful: Function | Object) {
const state = toState(stateful);
const config = state['features/base/config'];
const { locationURL } = state['features/base/connection'];
const { tenant } = state['features/base/jwt'];
const { email, name: nick } = getLocalParticipant(state) ?? {};
const options: any = { ...config };
const { email, name: nick } = getLocalParticipant(state);
const options = { ...config };
if (tenant) {
options.siteID = tenant;
@@ -257,11 +257,11 @@ export function getConferenceOptions(stateful: IStateful) {
/**
* Returns the UTC timestamp when the first participant joined the conference.
*
* @param {IStateful} stateful - Reference that can be resolved to Redux
* @param {Function | Object} stateful - Reference that can be resolved to Redux
* state with the {@code toState} function.
* @returns {number}
*/
export function getConferenceTimestamp(stateful: IStateful) {
export function getConferenceTimestamp(stateful: Function | Object): number {
const state = toState(stateful);
const { conferenceTimestamp } = getConferenceState(state);
@@ -274,11 +274,11 @@ export function getConferenceTimestamp(stateful: IStateful) {
* {@code conference} state of the feature base/conference which is not joining
* but may be leaving already.
*
* @param {IStateful} stateful - The redux store, state, or
* @param {Function|Object} stateful - The redux store, state, or
* {@code getState} function.
* @returns {JitsiConference|undefined}
*/
export function getCurrentConference(stateful: IStateful): any {
export function getCurrentConference(stateful: Function | Object) {
const { conference, joining, leaving, membersOnly, passwordRequired }
= getConferenceState(toState(stateful));
@@ -293,29 +293,25 @@ export function getCurrentConference(stateful: IStateful): any {
/**
* Returns the stored room name.
*
* @param {IState} state - The current state of the app.
* @param {Object} state - The current state of the app.
* @returns {string}
*/
export function getRoomName(state: IState) {
export function getRoomName(state: Object): string {
return getConferenceState(state).room;
}
/**
* Get an obfuscated room name or create and persist it if it doesn't exists.
*
* @param {IState} state - The current state of the app.
* @param {Object} state - The current state of the app.
* @param {Function} dispatch - The Redux dispatch function.
* @returns {string} - Obfuscated room name.
*/
export function getOrCreateObfuscatedRoomName(state: IState, dispatch: IStore['dispatch']) {
export function getOrCreateObfuscatedRoomName(state: Object, dispatch: Function) {
let { obfuscatedRoom } = getConferenceState(state);
const { obfuscatedRoomSource } = getConferenceState(state);
const room = getRoomName(state);
if (!room) {
return;
}
// On native mobile the store doesn't clear when joining a new conference so we might have the obfuscatedRoom
// stored even though a different room was joined.
// Check if the obfuscatedRoom was already computed for the current room.
@@ -331,11 +327,11 @@ export function getOrCreateObfuscatedRoomName(state: IState, dispatch: IStore['d
* Analytics may require an obfuscated room name, this functions decides based on a config if the normal or
* obfuscated room name should be returned.
*
* @param {IState} state - The current state of the app.
* @param {Object} state - The current state of the app.
* @param {Function} dispatch - The Redux dispatch function.
* @returns {string} - Analytics room name.
*/
export function getAnalyticsRoomName(state: IState, dispatch: IStore['dispatch']) {
export function getAnalyticsRoomName(state: Object, dispatch: Function) {
const { analysis: { obfuscateRoomName = false } = {} } = state['features/base/config'];
if (obfuscateRoomName) {
@@ -369,7 +365,7 @@ function getWiFiStatsMethod() {
* @protected
* @returns {void}
*/
export function _handleParticipantError(err: Error) {
export function _handleParticipantError(err: { message: ?string }) {
// XXX DataChannels are initialized at some later point when the conference
// has multiple participants, but code that pins or selects a participant
// might be executed before. So here we're swallowing a particular error.
@@ -388,7 +384,7 @@ export function _handleParticipantError(err: Error) {
* @returns {boolean} If the specified room name is valid, then true; otherwise,
* false.
*/
export function isRoomValid(room?: string) {
export function isRoomValid(room: ?string) {
return typeof room === 'string' && room !== '';
}
@@ -401,11 +397,11 @@ export function isRoomValid(room?: string) {
* @returns {Promise}
*/
export function _removeLocalTracksFromConference(
conference: IJitsiConference,
conference: { removeTrack: Function },
localTracks: Array<Object>) {
return Promise.all(localTracks.map(track =>
conference.removeTrack(track)
.catch((err: Error) => {
.catch(err => {
// Local track might be already disposed by direct
// JitsiTrack#dispose() call. So we should ignore this error
// here.
@@ -429,7 +425,7 @@ export function _removeLocalTracksFromConference(
* @private
* @returns {void}
*/
function _reportError(msg: string, err: Error) {
function _reportError(msg, err) {
// TODO This is a good point to call some global error handler when we have
// one.
logger.error(msg, err);
@@ -447,14 +443,17 @@ function _reportError(msg: string, err: Error) {
* @returns {void}
*/
export function sendLocalParticipant(
stateful: IStateful,
conference: IJitsiConference) {
stateful: Function | Object,
conference: {
sendCommand: Function,
setDisplayName: Function,
setLocalParticipantProperty: Function }) {
const {
avatarURL,
email,
features,
name
} = getLocalParticipant(stateful) ?? {};
} = getLocalParticipant(stateful);
avatarURL && conference.sendCommand(AVATAR_URL_COMMAND, {
value: avatarURL

View File

@@ -1,3 +1,5 @@
// @flow
import { getLogger } from '../logging/functions';
export default getLogger('features/base/conference');

View File

@@ -17,12 +17,12 @@ import { validateJwt } from '../jwt';
import { JitsiConferenceErrors } from '../lib-jitsi-meet';
import { MEDIA_TYPE } from '../media';
import {
PARTICIPANT_ROLE,
PARTICIPANT_UPDATED,
PIN_PARTICIPANT,
getLocalParticipant,
getParticipantById,
getPinnedParticipant
getPinnedParticipant,
PARTICIPANT_ROLE,
PARTICIPANT_UPDATED,
PIN_PARTICIPANT
} from '../participants';
import { MiddlewareRegistry } from '../redux';
import { TRACK_ADDED, TRACK_REMOVED } from '../tracks';

View File

@@ -6,9 +6,9 @@ import { showModeratedNotification } from '../../av-moderation/actions';
import { shouldShowModeratedNotification } from '../../av-moderation/functions';
import { setNoiseSuppressionEnabled } from '../../noise-suppression/actions';
import {
showNotification,
NOTIFICATION_TIMEOUT_TYPE,
isModerationNotificationDisplayed,
showNotification
isModerationNotificationDisplayed
} from '../../notifications';
import {
setPrejoinPageVisibility,
@@ -25,19 +25,19 @@ import { AudioMixerEffect } from '../../stream-effects/audio-mixer/AudioMixerEff
import { setAudioOnly } from '../audio-only';
import { getMultipleVideoSendingSupportFeatureFlag } from '../config/functions.any';
import { JitsiConferenceErrors, JitsiTrackErrors, JitsiTrackEvents } from '../lib-jitsi-meet';
import { MEDIA_TYPE, VIDEO_TYPE, setScreenshareMuted } from '../media';
import { MEDIA_TYPE, setScreenshareMuted, VIDEO_TYPE } from '../media';
import { MiddlewareRegistry } from '../redux';
import {
TOGGLE_SCREENSHARING,
addLocalTrack,
createLocalTracksF,
getLocalDesktopTrack,
getLocalJitsiAudioTrack,
replaceLocalTrack,
toggleScreensharing
toggleScreensharing,
TOGGLE_SCREENSHARING
} from '../tracks';
import { CONFERENCE_FAILED, CONFERENCE_JOINED, CONFERENCE_JOIN_IN_PROGRESS } from './actionTypes';
import { CONFERENCE_FAILED, CONFERENCE_JOIN_IN_PROGRESS, CONFERENCE_JOINED } from './actionTypes';
import { getCurrentConference } from './functions';
import './middleware.any';

View File

@@ -40,34 +40,11 @@ const DEFAULT_STATE = {
passwordRequired: undefined
};
export interface IJitsiConference {
addTrack: Function;
getBreakoutRooms: Function;
getLocalTracks: Function;
grantOwner: Function;
isAVModerationSupported: Function;
isEndConferenceSupported: Function;
isLobbySupported: Function;
kickParticipant: Function;
muteParticipant: Function;
myLobbyUserId: Function;
myUserId: Function;
on: Function;
removeTrack: Function;
replaceTrack: Function;
sendCommand: Function;
sendEndpointMessage: Function;
sendLobbyMessage: Function;
sessionId: string;
setDisplayName: Function;
setLocalParticipantProperty: Function;
}
export interface IConferenceState {
authEnabled?: boolean;
authLogin?: string;
authRequired?: Object;
conference?: IJitsiConference;
conference?: any;
conferenceTimestamp?: number;
e2eeSupported?: boolean;
error?: Error;

View File

@@ -8,9 +8,9 @@ import { parseURIString } from '../util/uri';
import {
CONFIG_WILL_LOAD,
LOAD_CONFIG_ERROR,
OVERWRITE_CONFIG,
SET_CONFIG,
UPDATE_CONFIG
UPDATE_CONFIG,
OVERWRITE_CONFIG
} from './actionTypes';
import { IConfig } from './configType';
import { _CONFIG_STORE_PREFIX } from './constants';

View File

@@ -67,7 +67,7 @@ type ButtonsWithNotifyClick = 'camera' |
'add-passcode' |
'__end';
export type Sounds = 'ASKED_TO_UNMUTE_SOUND' |
type Sounds = 'ASKED_TO_UNMUTE_SOUND' |
'E2EE_OFF_SOUND' |
'E2EE_ON_SOUND' |
'INCOMING_MSG_SOUND' |
@@ -125,7 +125,6 @@ export interface IConfig {
key: ButtonsWithNotifyClick;
preventExecution: boolean;
}>;
callDisplayName?: string;
callStatsConfigParams?: {
additionalIDs?: {
customerID?: string;
@@ -301,7 +300,6 @@ export interface IConfig {
disableTopPanel?: boolean;
minParticipantCountForTopPanel?: number;
};
firefox_fake_device?: string;
flags?: {
sendMultipleVideoStreams?: boolean;
sourceNameSignaling?: boolean;
@@ -426,7 +424,7 @@ export interface IConfig {
};
serviceUrl?: string;
speakerStatsOrder?: Array<'role' | 'name' | 'hasLeft'>;
startAudioMuted?: number;
startAudioMuted?: boolean;
startAudioOnly?: boolean;
startLastN?: number;
startScreenSharing?: boolean;

View File

@@ -11,7 +11,7 @@ import { parseURLParams } from '../util/parseURLParams';
import { IConfig } from './configType';
import CONFIG_WHITELIST from './configWhitelist';
import { FEATURE_FLAGS, _CONFIG_STORE_PREFIX } from './constants';
import { _CONFIG_STORE_PREFIX, FEATURE_FLAGS } from './constants';
import INTERFACE_CONFIG_WHITELIST from './interfaceConfigWhitelist';
import logger from './logger';
@@ -60,8 +60,8 @@ export function getMeetingRegion(state: IState) {
* @returns {boolean}
*/
export function getMultipleVideoSupportFeatureFlag(state: IState) {
return (getFeatureFlag(state, FEATURE_FLAGS.MULTIPLE_VIDEO_STREAMS_SUPPORT)
&& getSourceNameSignalingFeatureFlag(state)) ?? true;
return getFeatureFlag(state, FEATURE_FLAGS.MULTIPLE_VIDEO_STREAMS_SUPPORT)
&& getSourceNameSignalingFeatureFlag(state);
}
/**
@@ -72,7 +72,7 @@ export function getMultipleVideoSupportFeatureFlag(state: IState) {
*/
export function getMultipleVideoSendingSupportFeatureFlag(state: IState) {
return navigator.product !== 'ReactNative'
&& ((getMultipleVideoSupportFeatureFlag(state) ?? true) && isUnifiedPlanEnabled(state));
&& getMultipleVideoSupportFeatureFlag(state) && isUnifiedPlanEnabled(state);
}
/**
@@ -82,7 +82,7 @@ export function getMultipleVideoSendingSupportFeatureFlag(state: IState) {
* @returns {boolean}
*/
export function getSourceNameSignalingFeatureFlag(state: IState) {
return getFeatureFlag(state, FEATURE_FLAGS.SOURCE_NAME_SIGNALING) ?? true;
return getFeatureFlag(state, FEATURE_FLAGS.SOURCE_NAME_SIGNALING);
}
/**
@@ -95,7 +95,7 @@ export function getSourceNameSignalingFeatureFlag(state: IState) {
export function getFeatureFlag(state: IState, featureFlag: string) {
const featureFlags = state['features/base/config']?.flags || {};
return featureFlags[featureFlag as keyof typeof featureFlags];
return Boolean(featureFlags[featureFlag as keyof typeof featureFlags]);
}
/**

View File

@@ -5,7 +5,7 @@ import { getFeatureFlag } from '../flags/functions';
import MiddlewareRegistry from '../redux/MiddlewareRegistry';
import { updateSettings } from '../settings/actions';
import { OVERWRITE_CONFIG, SET_CONFIG } from './actionTypes';
import { SET_CONFIG, OVERWRITE_CONFIG } from './actionTypes';
import { updateConfig } from './actions';
import { IConfig } from './configType';
@@ -74,12 +74,6 @@ function _setConfig({ dispatch, getState }: IStore, next: Function, action: AnyA
}));
}
if (action.config.filmstrip?.stageFilmstripParticipants !== undefined) {
dispatch(updateSettings({
maxStageParticipants: action.config.filmstrip.stageFilmstripParticipants
}));
}
dispatch(updateConfig(config));
// FIXME On Web we rely on the global 'config' variable which gets altered

View File

@@ -5,11 +5,11 @@ import ReducerRegistry from '../redux/ReducerRegistry';
import { equals } from '../redux/functions';
import {
UPDATE_CONFIG,
CONFIG_WILL_LOAD,
LOAD_CONFIG_ERROR,
OVERWRITE_CONFIG,
SET_CONFIG,
UPDATE_CONFIG
OVERWRITE_CONFIG
} from './actionTypes';
import { IConfig } from './configType';
// eslint-disable-next-line lines-around-comment
@@ -71,9 +71,6 @@ const CONFERENCE_HEADER_MAPPING: any = {
};
export interface IConfigState extends IConfig {
analysis?: {
obfuscateRoomName?: boolean;
};
error?: Error;
}

View File

@@ -20,7 +20,6 @@ export interface IConnectionState {
connecting?: Object;
connection?: {
getJid: () => string;
getLogs: () => Object;
};
error?: ConnectionFailedError;
locationURL?: URL;

View File

@@ -1,21 +1,18 @@
import { AnyAction } from 'redux';
/* global APP */
/* eslint-disable lines-around-comment */
// @ts-ignore
import UIEvents from '../../../../service/UI/UIEvents';
import { IStore } from '../../app/types';
import { processExternalDeviceRequest } from '../../device-selection/functions';
import { showNotification, showWarningNotification } from '../../notifications/actions';
import { NOTIFICATION_TIMEOUT_TYPE } from '../../notifications/constants';
// @ts-ignore
import { processExternalDeviceRequest } from '../../device-selection';
import {
NOTIFICATION_TIMEOUT_TYPE,
showNotification,
showWarningNotification
} from '../../notifications';
import { replaceAudioTrackById, replaceVideoTrackById, setDeviceStatusWarning } from '../../prejoin/actions';
// @ts-ignore
import { isPrejoinPageVisible } from '../../prejoin/functions';
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app/actionTypes';
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app';
import JitsiMeetJS, { JitsiMediaDevicesEvents, JitsiTrackErrors } from '../lib-jitsi-meet';
import MiddlewareRegistry from '../redux/MiddlewareRegistry';
import { updateSettings } from '../settings/actions';
import { MiddlewareRegistry } from '../redux';
import { updateSettings } from '../settings';
import {
CHECK_AND_NOTIFY_FOR_NEW_DEVICE,
@@ -38,7 +35,6 @@ import {
setAudioOutputDeviceId
} from './functions';
import logger from './logger';
import { IDevicesState } from './reducer';
const JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP = {
microphone: {
@@ -61,7 +57,7 @@ const JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP = {
/**
* A listener for device permissions changed reported from lib-jitsi-meet.
*/
let permissionsListener: Function | undefined;
let permissionsListener;
/**
* Logs the current device list.
@@ -69,9 +65,8 @@ let permissionsListener: Function | undefined;
* @param {Object} deviceList - Whatever is returned by {@link groupDevicesByKind}.
* @returns {string}
*/
function logDeviceList(deviceList: IDevicesState['availableDevices']) {
const devicesToStr = (list?: MediaDeviceInfo[]) =>
list?.map(device => `\t\t${device.label}[${device.deviceId}]`).join('\n');
function logDeviceList(deviceList) {
const devicesToStr = list => list.map(device => `\t\t${device.label}[${device.deviceId}]`).join('\n');
const audioInputs = devicesToStr(deviceList.audioInput);
const audioOutputs = devicesToStr(deviceList.audioOutput);
const videoInputs = devicesToStr(deviceList.videoInput);
@@ -92,7 +87,7 @@ function logDeviceList(deviceList: IDevicesState['availableDevices']) {
MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
case APP_WILL_MOUNT: {
const _permissionsListener = (permissions: Object) => {
const _permissionsListener = permissions => {
store.dispatch(devicePermissionsChanged(permissions));
};
const { mediaDevices } = JitsiMeetJS;
@@ -219,7 +214,7 @@ MiddlewareRegistry.register(store => next => action => {
* @private
* @returns {Object} The value returned by {@code next(action)}.
*/
function _processPendingRequests({ dispatch, getState }: IStore, next: Function, action: AnyAction) {
function _processPendingRequests({ dispatch, getState }, next, action) {
const result = next(action);
const state = getState();
const { pendingRequests } = state['features/base/devices'];
@@ -228,7 +223,7 @@ function _processPendingRequests({ dispatch, getState }: IStore, next: Function,
return result;
}
pendingRequests.forEach((request: any) => {
pendingRequests.forEach(request => {
processExternalDeviceRequest(
dispatch,
getState,
@@ -253,7 +248,7 @@ function _processPendingRequests({ dispatch, getState }: IStore, next: Function,
* @private
* @returns {void}
*/
function _checkAndNotifyForNewDevice(store: IStore, newDevices: MediaDeviceInfo[], oldDevices: MediaDeviceInfo[]) {
function _checkAndNotifyForNewDevice(store, newDevices, oldDevices) {
const { dispatch } = store;
// let's intersect both newDevices and oldDevices and handle thew newly
@@ -265,9 +260,7 @@ function _checkAndNotifyForNewDevice(store: IStore, newDevices: MediaDeviceInfo[
// we group devices by groupID which normally is the grouping by physical device
// plugging in headset we provide normally two device, one input and one output
// and we want to show only one notification for this physical audio device
const devicesGroupBy: {
[key: string]: MediaDeviceInfo[];
} = onlyNewDevices.reduce((accumulated: any, value) => {
const devicesGroupBy = onlyNewDevices.reduce((accumulated, value) => {
accumulated[value.groupId] = accumulated[value.groupId] || [];
accumulated[value.groupId].push(value);
@@ -321,7 +314,7 @@ function _checkAndNotifyForNewDevice(store: IStore, newDevices: MediaDeviceInfo[
* @returns {boolean} - Returns true in order notifications to be dismissed.
* @private
*/
function _useDevice({ dispatch }: IStore, devices: MediaDeviceInfo[]) {
function _useDevice({ dispatch }, devices) {
devices.forEach(device => {
switch (device.kind) {
case 'videoinput': {

View File

@@ -1,4 +1,4 @@
import React, { type Node, PureComponent } from 'react';
import React, { PureComponent, type Node } from 'react';
import { SafeAreaView, ScrollView, View } from 'react-native';
import { SlidingView } from '../../../react';

View File

@@ -1,3 +1,5 @@
// @flow
import { Component } from 'react';
/**
@@ -8,17 +10,17 @@ export type Props = {
/**
* Function that closes the dialog.
*/
closeDialog: Function;
closeDialog: Function,
/**
* Callback to invoke on change.
*/
onTabStateChange: Function;
onTabStateChange: Function,
/**
* The id of the tab.
*/
tabId: number;
tabId: number
};
@@ -27,7 +29,7 @@ export type Props = {
*
* @augments Component
*/
class AbstractDialogTab<P extends Props, S> extends Component<P, S> {
class AbstractDialogTab<P: Props, S: *> extends Component<P, S> {
/**
* Initializes a new {@code AbstractDialogTab} instance.
*
@@ -41,6 +43,8 @@ class AbstractDialogTab<P extends Props, S> extends Component<P, S> {
this._onChange = this._onChange.bind(this);
}
_onChange: (Object) => void;
/**
* Uses the onTabStateChange function to pass the changed state of the
* controlled tab component to the controlling DialogWithTabs component.
@@ -49,7 +53,7 @@ class AbstractDialogTab<P extends Props, S> extends Component<P, S> {
* value.
* @returns {void}
*/
_onChange(change: Object) {
_onChange(change) {
const { onTabStateChange, tabId } = this.props;
onTabStateChange(tabId, {

View File

@@ -5,8 +5,8 @@ import WarningIcon from '@atlaskit/icon/glyph/warning';
import {
Header,
Title,
TitleText,
titleIconWrapperStyles
titleIconWrapperStyles,
TitleText
// @ts-ignore
} from '@atlaskit/modal-dialog/dist/es2019/styled/Content';
import { Theme } from '@mui/material';

View File

@@ -3,12 +3,12 @@
import {
Dialog,
FillScreen,
PositionerAbsolute,
PositionerRelative,
dialogWidth,
dialogHeight,
dialogWidth
PositionerAbsolute,
PositionerRelative
} from '@atlaskit/modal-dialog/dist/es2019/styled/Modal.js';
import { DN50, N0 } from '@atlaskit/theme/colors';
import { N0, DN50 } from '@atlaskit/theme/colors';
import { themed } from '@atlaskit/theme/components';
import React from 'react';

View File

@@ -1,3 +1,3 @@
<svg width="10" height="6" viewBox="0 0 10 6" xmlns="http://www.w3.org/2000/svg">
<svg width="10" height="6" viewBox="0 0 10 6" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.07001 0.248238C8.3471 -0.0596449 8.82132 -0.0846038 9.1292 0.192491C9.43709 0.469585 9.46205 0.943802 9.18495 1.25168L5.65622 5.19348C5.35829 5.52451 4.83922 5.52451 4.54128 5.19348L1.06752 1.25168C0.79043 0.943802 0.81539 0.469585 1.12327 0.192491C1.43115 -0.0846038 1.90537 -0.0596449 2.18247 0.248238L5.09875 3.57062L8.07001 0.248238Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 482 B

After

Width:  |  Height:  |  Size: 494 B

View File

@@ -1,3 +1,5 @@
// @flow
import { SET_JWT } from './actionTypes';
/**
@@ -9,7 +11,7 @@ import { SET_JWT } from './actionTypes';
* jwt: (string|undefined)
* }}
*/
export function setJWT(jwt?: string) {
export function setJWT(jwt: ?string) {
return {
type: SET_JWT,
jwt

View File

@@ -1,9 +1,9 @@
// @ts-ignore
/* @flow */
import jwtDecode from 'jwt-decode';
import { IState } from '../../app/types';
import { getLocalParticipant } from '../participants/functions';
import { parseURLParams } from '../util/parseURLParams';
import { parseURLParams } from '../util';
import { MEET_FEATURES } from './constants';
@@ -16,18 +16,17 @@ import { MEET_FEATURES } from './constants';
* @returns {string} The JSON Web Token (JWT), if any, defined by the specified
* {@code url}; otherwise, {@code undefined}.
*/
export function parseJWTFromURLParams(url: URL | Location = window.location) {
// @ts-ignore
export function parseJWTFromURLParams(url: URL = window.location) {
return parseURLParams(url, true, 'search').jwt;
}
/**
* Returns the user name after decoding the jwt.
*
* @param {IState} state - The app state.
* @param {Object} state - The app state.
* @returns {string}
*/
export function getJwtName(state: IState) {
export function getJwtName(state: Object) {
const { user } = state['features/base/jwt'];
return user?.name;
@@ -36,12 +35,12 @@ export function getJwtName(state: IState) {
/**
* Check if the given JWT feature is enabled.
*
* @param {IState} state - The app state.
* @param {Object} state - The app state.
* @param {string} feature - The feature we want to check.
* @param {boolean} ifNoToken - Default value if there is no token.
* @returns {string}
*/
export function isJwtFeatureEnabled(state: IState, feature: string, ifNoToken = false) {
export function isJwtFeatureEnabled(state: Object, feature: string, ifNoToken: boolean = false) {
const { jwt } = state['features/base/jwt'];
if (!jwt) {
@@ -55,7 +54,7 @@ export function isJwtFeatureEnabled(state: IState, feature: string, ifNoToken =
return true;
}
return String(features[feature as keyof typeof features]) === 'true';
return String(features[feature]) === 'true';
}
/**
@@ -65,7 +64,7 @@ export function isJwtFeatureEnabled(state: IState, feature: string, ifNoToken =
* @param {any} timestamp - A UNIX timestamp in seconds as stored in the jwt.
* @returns {boolean} - Whether the timestamp is indeed a valid UNIX timestamp or not.
*/
function isValidUnixTimestamp(timestamp: number | string) {
function isValidUnixTimestamp(timestamp: any) {
return typeof timestamp === 'number' && timestamp * 1000 === new Date(timestamp * 1000).getTime();
}
@@ -76,7 +75,7 @@ function isValidUnixTimestamp(timestamp: number | string) {
* @returns {Array<string>} - An array containing all jwt validation errors.
*/
export function validateJwt(jwt: string) {
const errors: string[] = [];
const errors = [];
if (!jwt) {
return errors;
@@ -104,7 +103,7 @@ export function validateJwt(jwt: string) {
} = payload;
// JaaS only
if (sub?.startsWith('vpaas-magic-cookie')) {
if (sub && sub.startsWith('vpaas-magic-cookie')) {
const { kid } = header;
// if Key ID is missing, we return the error immediately without further validations.
@@ -166,7 +165,7 @@ export function validateJwt(jwt: string) {
}
});
}
} catch (e: any) {
} catch (e) {
errors.push(e ? e.message : '- unspecified jwt error');
}

View File

@@ -1,3 +1,5 @@
// @flow
import { getLogger } from '../logging/functions';
export default getLogger('features/base/jwt');

View File

@@ -1,20 +1,22 @@
// @ts-ignore
import jwtDecode from 'jwt-decode';
import { AnyAction } from 'redux';
// @flow
import { IStore } from '../../app/types';
import { SET_CONFIG } from '../config/actionTypes';
import { SET_LOCATION_URL } from '../connection/actionTypes';
import { participantUpdated } from '../participants/actions';
import { getLocalParticipant } from '../participants/functions';
import { Participant } from '../participants/types';
import MiddlewareRegistry from '../redux/MiddlewareRegistry';
import jwtDecode from 'jwt-decode';
import { SET_CONFIG } from '../config';
import { SET_LOCATION_URL } from '../connection';
import {
getLocalParticipant,
participantUpdated
} from '../participants';
import { MiddlewareRegistry } from '../redux';
import { SET_JWT } from './actionTypes';
import { setJWT } from './actions';
import { parseJWTFromURLParams } from './functions';
import logger from './logger';
declare var APP: Object;
/**
* Middleware to parse token data upon setting a new room URL.
*
@@ -49,14 +51,13 @@ MiddlewareRegistry.register(store => next => action => {
* @returns {void}
*/
function _overwriteLocalParticipant(
{ dispatch, getState }: IStore,
{ avatarURL, email, id: jwtId, name, features }:
{ avatarURL?: string; email?: string; features?: any; id?: string; name?: string; }) {
{ dispatch, getState },
{ avatarURL, email, id: jwtId, name, features }) {
let localParticipant;
if ((avatarURL || email || name)
&& (localParticipant = getLocalParticipant(getState))) {
const newProperties: Participant = {
const newProperties: Object = {
id: localParticipant.id,
local: true
};
@@ -96,7 +97,7 @@ function _overwriteLocalParticipant(
* @returns {Object} The new state that is the result of the reduction of the
* specified {@code action}.
*/
function _setConfigOrLocationURL({ dispatch, getState }: IStore, next: Function, action: AnyAction) {
function _setConfigOrLocationURL({ dispatch, getState }, next, action) {
const result = next(action);
const { locationURL } = getState()['features/base/connection'];
@@ -121,8 +122,8 @@ function _setConfigOrLocationURL({ dispatch, getState }: IStore, next: Function,
* @returns {Object} The new state that is the result of the reduction of the
* specified {@code action}.
*/
function _setJWT(store: IStore, next: Function, action: AnyAction) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function _setJWT(store, next, action) {
// eslint-disable-next-line no-unused-vars
const { jwt, type, ...actionPayload } = action;
if (!Object.keys(actionPayload).length) {
@@ -185,13 +186,13 @@ function _setJWT(store: IStore, next: Function, action: AnyAction) {
* @returns {void}
*/
function _undoOverwriteLocalParticipant(
{ dispatch, getState }: IStore,
{ avatarURL, name, email }: { avatarURL?: string; email?: string; name?: string; }) {
{ dispatch, getState },
{ avatarURL, name, email }) {
let localParticipant;
if ((avatarURL || name || email)
&& (localParticipant = getLocalParticipant(getState))) {
const newProperties: Participant = {
const newProperties: Object = {
id: localParticipant.id,
local: true
};
@@ -225,10 +226,8 @@ function _undoOverwriteLocalParticipant(
* hidden-from-recorder: ?boolean
* }}
*/
function _user2participant({ avatar, avatarUrl, email, id, name, 'hidden-from-recorder': hiddenFromRecorder }:
{ avatar: any; avatarUrl: string; email: string; 'hidden-from-recorder': string | boolean;
id: string; name: string; }) {
const participant: any = {};
function _user2participant({ avatar, avatarUrl, email, id, name, 'hidden-from-recorder': hiddenFromRecorder }) {
const participant = {};
if (typeof avatarUrl === 'string') {
participant.avatarURL = avatarUrl.trim();

View File

@@ -4,16 +4,9 @@ import { equals } from '../redux/functions';
import { SET_JWT } from './actionTypes';
export interface IJwtState {
callee?: {
name: string;
};
group?: string;
jwt?: string;
server?: string;
tenant?: string;
user?: {
name: string;
};
}
/**

View File

@@ -3,7 +3,7 @@ import React from 'react';
import { Animated, Text } from 'react-native';
import Icon from '../../../icons/components/Icon';
import { type StyleType, combineStyles } from '../../../styles';
import { combineStyles, type StyleType } from '../../../styles';
import AbstractLabel, {
type Props as AbstractProps
} from '../AbstractLabel';

View File

@@ -1,3 +1,5 @@
// @flow
import { SET_LAST_N } from './actionTypes';
/**

View File

@@ -7,7 +7,7 @@ import { VIDEO_QUALITY_LEVELS } from '../../video-quality/constants';
* @param {number} channelLastN - LastN value set for the whole conference.
* @returns {number} LastN value applicable to the quality level specified.
*/
export function getLastNForQualityLevel(qualityLevel: number, channelLastN: number) {
export function getLastNForQualityLevel(qualityLevel, channelLastN) {
let lastN = channelLastN;
const videoQualityLevels = Object.values(VIDEO_QUALITY_LEVELS);
@@ -15,8 +15,8 @@ export function getLastNForQualityLevel(qualityLevel: number, channelLastN: numb
for (const lvl in videoQualityLevels) {
if (videoQualityLevels.hasOwnProperty(lvl)
&& qualityLevel === videoQualityLevels[lvl]
&& Number(lvl) > 1) {
lastN = Math.floor(channelLastN / Math.pow(2, Number(lvl) - 1));
&& lvl > 1) {
lastN = Math.floor(channelLastN / Math.pow(2, lvl - 1));
}
}
@@ -30,7 +30,7 @@ export function getLastNForQualityLevel(qualityLevel: number, channelLastN: numb
* @param {Object} lastNLimits - The Object to be verified.
* @returns {undefined|Map<number, number>}
*/
export function validateLastNLimits(lastNLimits: any) {
export function validateLastNLimits(lastNLimits) {
// Checks if only numbers are used
if (typeof lastNLimits !== 'object'
|| !Object.keys(lastNLimits).length
@@ -64,7 +64,7 @@ export function validateLastNLimits(lastNLimits: any) {
* @returns {number|undefined} - A "last N" number if there was a corresponding "last N" value matched with the number
* of participants or {@code undefined} otherwise.
*/
export function limitLastN(participantsCount: number, lastNLimits: Map<number, number>) {
export function limitLastN(participantsCount, lastNLimits) {
if (!lastNLimits || !lastNLimits.keys) {
return undefined;
}

View File

@@ -1,3 +1,5 @@
// @flow
import { getLogger } from '../logging/functions';
export default getLogger('features/base/lastn');

View File

@@ -1,6 +1,7 @@
// @flow
import debounce from 'lodash/debounce';
import { IStore } from '../../app/types';
import { SET_FILMSTRIP_ENABLED } from '../../filmstrip/actionTypes';
import { SELECT_LARGE_VIDEO_PARTICIPANT } from '../../large-video/actionTypes';
import { APP_STATE_CHANGED } from '../../mobile/background/actionTypes';
@@ -21,9 +22,7 @@ import {
getParticipantById,
getParticipantCount
} from '../participants/functions';
import MiddlewareRegistry from '../redux/MiddlewareRegistry';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import { MiddlewareRegistry } from '../redux';
import { isLocalVideoTrackDesktop } from '../tracks/functions';
import { setLastN } from './actions';
@@ -37,7 +36,7 @@ import logger from './logger';
* @private
* @returns {void}
*/
const _updateLastN = debounce(({ dispatch, getState }: IStore) => {
const _updateLastN = debounce(({ dispatch, getState }) => {
const state = getState();
const { conference } = state['features/base/conference'];
@@ -62,7 +61,6 @@ const _updateLastN = debounce(({ dispatch, getState }: IStore) => {
let lastNSelected = config.startLastN ?? (config.channelLastN ?? -1);
// Apply last N limit based on the # of participants and config settings.
// @ts-ignore
const limitedLastN = limitLastN(participantCount, lastNLimits);
if (limitedLastN !== undefined) {
@@ -83,7 +81,7 @@ const _updateLastN = debounce(({ dispatch, getState }: IStore) => {
// view since we make an exception only for screenshare when in audio-only mode. If the user unpins
// the screenshare, lastN will be set to 0 here. It will be set to 1 if screenshare has been auto pinned.
if (!tileViewEnabled && largeVideoParticipant && !largeVideoParticipant.local) {
lastNSelected = (remoteScreenShares || []).includes(largeVideoParticipantId ?? '') ? 1 : 0;
lastNSelected = (remoteScreenShares || []).includes(largeVideoParticipantId) ? 1 : 0;
} else {
lastNSelected = 0;
}

View File

@@ -1,11 +1,10 @@
/* eslint-disable lines-around-comment */
// @ts-ignore
import { jitsiLocalStorage } from '@jitsi/js-utils';
/* @flow */
import { jitsiLocalStorage } from '@jitsi/js-utils';
import type { Dispatch } from 'redux';
import { IStore } from '../../app/types';
import { isOnline } from '../net-info/selectors';
// @ts-ignore
import JitsiMeetJS from './_';
import {
LIB_DID_DISPOSE,
@@ -14,16 +13,17 @@ import {
LIB_WILL_DISPOSE,
LIB_WILL_INIT
} from './actionTypes';
// @ts-ignore
import { isAnalyticsEnabled } from './functions';
declare var APP: Object;
/**
* Disposes (of) lib-jitsi-meet.
*
* @returns {Function}
*/
export function disposeLib() {
return (dispatch: IStore['dispatch']) => {
return (dispatch: Dispatch<any>) => {
dispatch({ type: LIB_WILL_DISPOSE });
// TODO Currently, lib-jitsi-meet doesn't have the functionality to
@@ -39,7 +39,7 @@ export function disposeLib() {
* @returns {Function}
*/
export function initLib() {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
return (dispatch: Dispatch<any>, getState: Function): void => {
const state = getState();
const config = state['features/base/config'];
@@ -59,7 +59,7 @@ export function initLib() {
isOnline: isOnline(state)
});
dispatch({ type: LIB_DID_INIT });
} catch (error: any) {
} catch (error) {
dispatch(libInitError(error));
}
};

View File

@@ -1,7 +1,7 @@
import { IStateful } from '../app/types';
import { toState } from '../redux/functions';
// @flow
import { toState } from '../redux';
// @ts-ignore
import JitsiMeetJS from './_';
const JitsiConferenceErrors = JitsiMeetJS.errors.conference;
@@ -18,7 +18,7 @@ const JitsiConnectionErrors = JitsiMeetJS.errors.connection;
*
* @returns {Promise<JitsiLocalTrack>}
*/
export function createLocalTrack(type: string, deviceId: string, timeout?: number, additionalOptions?: Object) {
export function createLocalTrack(type: string, deviceId: string, timeout: ?number, additionalOptions: ?Object) {
return (
JitsiMeetJS.createLocalTracks({
cameraDeviceId: deviceId,
@@ -26,23 +26,23 @@ export function createLocalTrack(type: string, deviceId: string, timeout?: numbe
// eslint-disable-next-line camelcase
firefox_fake_device:
window.config?.firefox_fake_device,
window.config && window.config.firefox_fake_device,
micDeviceId: deviceId,
timeout,
...additionalOptions
})
.then(([ jitsiLocalTrack ]: any[]) => jitsiLocalTrack));
.then(([ jitsiLocalTrack ]) => jitsiLocalTrack));
}
/**
* Determines whether analytics is enabled in a specific redux {@code store}.
*
* @param {IStateful} stateful - The redux store, state, or
* @param {Function|Object} stateful - The redux store, state, or
* {@code getState} function.
* @returns {boolean} If analytics is enabled, {@code true}; {@code false},
* otherwise.
*/
export function isAnalyticsEnabled(stateful: IStateful) {
export function isAnalyticsEnabled(stateful: Function | Object) {
const { disableThirdPartyRequests, analytics = {} } = toState(stateful)['features/base/config'];
return !(disableThirdPartyRequests || analytics.disabled);
@@ -56,13 +56,13 @@ export function isAnalyticsEnabled(stateful: IStateful) {
* that category. I've currently named the category fatal because it appears to
* be used in the cases of unrecoverable errors that necessitate a reload.
*
* @param {Error|string} error - The {@code JitsiConferenceErrors} instance to
* @param {Object|string} error - The {@code JitsiConferenceErrors} instance to
* categorize/classify or an {@link Error}-like object.
* @returns {boolean} If the specified {@code JitsiConferenceErrors} instance
* indicates a fatal {@code JitsiConference} error, {@code true}; otherwise,
* {@code false}.
*/
export function isFatalJitsiConferenceError(error: Error | string) {
export function isFatalJitsiConferenceError(error: Object | string) {
if (typeof error !== 'string') {
error = error.name; // eslint-disable-line no-param-reassign
}
@@ -83,13 +83,13 @@ export function isFatalJitsiConferenceError(error: Error | string) {
* that category. I've currently named the category fatal because it appears to
* be used in the cases of unrecoverable errors that necessitate a reload.
*
* @param {Error|string} error - The {@code JitsiConnectionErrors} instance to
* @param {Object|string} error - The {@code JitsiConnectionErrors} instance to
* categorize/classify or an {@link Error}-like object.
* @returns {boolean} If the specified {@code JitsiConnectionErrors} instance
* indicates a fatal {@code JitsiConnection} error, {@code true}; otherwise,
* {@code false}.
*/
export function isFatalJitsiConnectionError(error: Error | string) {
export function isFatalJitsiConnectionError(error: Object | string) {
if (typeof error !== 'string') {
error = error.name; // eslint-disable-line no-param-reassign
}

View File

@@ -1,3 +1,5 @@
// @flow
export * from './functions.any';
/**
@@ -6,7 +8,7 @@ export * from './functions.any';
* @param {string} url - The URL to load.
* @returns {Promise<Object>}
*/
export async function loadConfig(url: string) { // eslint-disable-line @typescript-eslint/no-unused-vars
export async function loadConfig(url: string): Promise<Object> { // eslint-disable-line no-unused-vars
// Return "the config.js file" from the global scope - that is how the
// Web app on both the client and the server was implemented before the
// React Native app was even conceived.

View File

@@ -1,3 +1,5 @@
// @flow
import { getLogger } from '../logging/functions';
export default getLogger('features/base/lib-jitsi-meet');

View File

@@ -1,16 +1,14 @@
import { AnyAction } from 'redux';
import { SET_CONFIG } from '../config';
import { SET_NETWORK_INFO } from '../net-info';
import { PARTICIPANT_LEFT } from '../participants';
import { MiddlewareRegistry } from '../redux';
import { IStore } from '../../app/types';
import { SET_CONFIG } from '../config/actionTypes';
import { SET_NETWORK_INFO } from '../net-info/actionTypes';
import { PARTICIPANT_LEFT } from '../participants/actionTypes';
import MiddlewareRegistry from '../redux/MiddlewareRegistry';
// @ts-ignore
import JitsiMeetJS from './_';
import { LIB_WILL_INIT } from './actionTypes';
import { disposeLib, initLib } from './actions';
declare var APP: Object;
/**
* Middleware that captures PARTICIPANT_LEFT action for a local participant
* (which signalizes that we finally left the app) and disposes lib-jitsi-meet.
@@ -62,7 +60,7 @@ MiddlewareRegistry.register(store => next => action => {
* @returns {Object} The new state that is the result of the reduction of the
* specified action.
*/
function _setConfig({ dispatch, getState }: IStore, next: Function, action: AnyAction) {
function _setConfig({ dispatch, getState }, next, action) {
const { initialized } = getState()['features/base/lib-jitsi-meet'];
// XXX Since the config is changing, the library lib-jitsi-meet must be
@@ -93,10 +91,10 @@ function _setErrorHandlers() {
if (JitsiMeetJS.getGlobalOnErrorHandler) {
const oldOnErrorHandler = window.onerror;
// @ts-ignore
window.onerror = (message, source, lineno, colno, error) => { // eslint-disable-line max-params
const errMsg = message || error?.message;
const stack = error?.stack;
// eslint-disable-next-line max-params
window.onerror = (message, source, lineno, colno, error) => {
const errMsg = message || (error && error.message);
const stack = error && error.stack;
JitsiMeetJS.getGlobalOnErrorHandler(errMsg, source, lineno, colno, stack);
@@ -109,7 +107,7 @@ function _setErrorHandlers() {
window.onunhandledrejection = function(event) {
let message = event.reason;
let stack: string | undefined = 'n/a';
let stack = 'n/a';
if (event.reason instanceof Error) {
({ message, stack } = event.reason);
@@ -118,7 +116,6 @@ function _setErrorHandlers() {
JitsiMeetJS.getGlobalOnErrorHandler(message, null, null, null, stack);
if (oldOnUnhandledRejection) {
// @ts-ignore
oldOnUnhandledRejection(event);
}
};

View File

@@ -50,6 +50,22 @@ export default class JitsiMeetLogStorage {
return Boolean(conference);
}
/**
* Checks whether callstats logs storage is enabled.
*
* @returns {boolean} <tt>true</tt> when this storage can store logs to
* callstats, <tt>false</tt> otherwise.
*/
canStoreLogsCallstats() {
const { callstatsStoreLogs } = this.getState()['features/base/config'];
// The behavior prior to adding this configuration parameter, is to send logs to callstats (if callstats is
// enabled). So, in order to maintain backwards compatibility I set the default of this option to be true, i.e.
// if the config.callstatsStoreLogs is not set, the JS console logs will be sent to callstats (if callstats is
// enabled)
return callstatsStoreLogs || callstatsStoreLogs === undefined;
}
/**
* Checks whether rtcstats logs storage is enabled.
*
@@ -76,9 +92,9 @@ export default class JitsiMeetLogStorage {
*/
storeLogs(logEntries: Array<string | any>) {
// XXX the config.callStatsApplicationLogsDisabled controls whether or not the logs will be sent to callstats.
// this is done in LJM
this.storeLogsCallstats(logEntries);
if (this.canStoreLogsCallstats()) {
this.storeLogsCallstats(logEntries);
}
if (this.canStoreLogsRtcstats()) {
RTCStats.sendLogs(logEntries);

View File

@@ -1,4 +1,4 @@
import { SET_LOGGING_CONFIG, SET_LOG_COLLECTOR } from './actionTypes';
import { SET_LOG_COLLECTOR, SET_LOGGING_CONFIG } from './actionTypes';
/**
* Stores a {@code Logger.LogCollector} instance which will be uploading logs

View File

@@ -3,7 +3,7 @@ import _ from 'lodash';
import ReducerRegistry from '../redux/ReducerRegistry';
import { equals, set } from '../redux/functions';
import { SET_LOGGING_CONFIG, SET_LOG_COLLECTOR } from './actionTypes';
import { SET_LOG_COLLECTOR, SET_LOGGING_CONFIG } from './actionTypes';
const DEFAULT_LOGGING_CONFIG = {
// default log level for the app and lib-jitsi-meet

View File

@@ -1,12 +1,14 @@
import { Dispatch } from 'redux';
/* @flow */
import type { Dispatch } from 'redux';
import { showModeratedNotification } from '../../av-moderation/actions';
import { shouldShowModeratedNotification } from '../../av-moderation/functions';
import { isModerationNotificationDisplayed } from '../../notifications/functions';
import { isModerationNotificationDisplayed } from '../../notifications';
import {
SET_AUDIO_AVAILABLE,
SET_AUDIO_MUTED,
SET_AUDIO_AVAILABLE,
SET_AUDIO_UNMUTE_PERMISSIONS,
SET_CAMERA_FACING_MODE,
SET_SCREENSHARE_MUTED,
@@ -53,7 +55,7 @@ export function setAudioAvailable(available: boolean) {
* muted: boolean
* }}
*/
export function setAudioMuted(muted: boolean, ensureTrack = false) {
export function setAudioMuted(muted: boolean, ensureTrack: boolean = false) {
return {
type: SET_AUDIO_MUTED,
ensureTrack,
@@ -68,7 +70,7 @@ export function setAudioMuted(muted: boolean, ensureTrack = false) {
* @param {boolean|undefined} skipNotification - True if we want to skip showing the notification.
* @returns {Function}
*/
export function setAudioUnmutePermissions(blocked: boolean, skipNotification = false) {
export function setAudioUnmutePermissions(blocked: boolean, skipNotification: boolean = false) {
return {
type: SET_AUDIO_UNMUTE_PERMISSIONS,
blocked,
@@ -105,7 +107,7 @@ export function setScreenshareMuted(
muted: boolean,
mediaType: MediaType = MEDIA_TYPE.SCREENSHARE,
authority: number = SCREENSHARE_MUTISM_AUTHORITY.USER,
ensureTrack = false) {
ensureTrack: boolean = false) {
return (dispatch: Dispatch<any>, getState: Function) => {
const state = getState();
@@ -166,7 +168,7 @@ export function setVideoMuted(
muted: boolean,
mediaType: string = MEDIA_TYPE.VIDEO,
authority: number = VIDEO_MUTISM_AUTHORITY.USER,
ensureTrack = false) {
ensureTrack: boolean = false) {
return (dispatch: Dispatch<any>, getState: Function) => {
const state = getState();
@@ -201,7 +203,7 @@ export function setVideoMuted(
* @param {boolean|undefined} skipNotification - True if we want to skip showing the notification.
* @returns {Function}
*/
export function setVideoUnmutePermissions(blocked: boolean, skipNotification = false) {
export function setVideoUnmutePermissions(blocked: boolean, skipNotification: boolean = false) {
return {
type: SET_VIDEO_UNMUTE_PERMISSIONS,
blocked,

View File

@@ -54,9 +54,7 @@ export const VIDEO_MUTISM_AUTHORITY = {
*
* @enum {string}
*/
export const VIDEO_TYPE: { [key: string]: VideoType; } = {
export const VIDEO_TYPE = {
CAMERA: 'camera',
DESKTOP: 'desktop'
};
export type VideoType = 'camera' | 'desktop';

View File

@@ -15,17 +15,17 @@ import {
import { isForceMuted } from '../../participants-pane/functions';
import { isScreenMediaShared } from '../../screen-share/functions';
import { SET_AUDIO_ONLY, setAudioOnly } from '../audio-only';
import { SET_ROOM, isRoomValid } from '../conference';
import { isRoomValid, SET_ROOM } from '../conference';
import { getMultipleVideoSendingSupportFeatureFlag } from '../config';
import { getLocalParticipant } from '../participants';
import { MiddlewareRegistry } from '../redux';
import { getPropertyValue } from '../settings';
import {
TRACK_ADDED,
destroyLocalTracks,
isLocalTrackMuted,
isLocalVideoTrackDesktop,
setTrackMuted
setTrackMuted,
TRACK_ADDED
} from '../tracks';
import {

View File

@@ -14,8 +14,6 @@ import MiddlewareRegistry from '../redux/MiddlewareRegistry';
import { SET_VIDEO_MUTED } from './actionTypes';
import './subscriber';
/**
* Implements the entry point of the middleware of the feature base/media.
*

View File

@@ -1,21 +0,0 @@
import { IState, IStore } from '../../app/types';
import StateListenerRegistry from '../redux/StateListenerRegistry';
declare let APP: any;
/**
* Notifies when the local audio mute state changes.
*/
StateListenerRegistry.register(
/* selector */ (state: IState) => state['features/base/media'].audio.muted,
/* listener */ (muted: boolean, store: IStore, previousMuted: boolean) => {
if (typeof APP !== 'object') {
return;
}
if (muted !== previousMuted) {
APP.API.notifyAudioMutedStatusChanged(muted);
}
}
);

View File

@@ -1,5 +1,7 @@
// @flow
import { SET_NETWORK_INFO, _STORE_NETWORK_INFO_CLEANUP } from './actionTypes';
import { NetworkInfo } from './types';
import type { NetworkInfo } from './types';
/**
* Up[dates the network info state.
@@ -12,7 +14,7 @@ import { NetworkInfo } from './types';
* details: Object
* }}
*/
export function setNetworkInfo({ isOnline, networkType, details }: NetworkInfo) {
export function setNetworkInfo({ isOnline, networkType, details }: NetworkInfo): Object {
return {
type: SET_NETWORK_INFO,
isOnline,
@@ -31,7 +33,7 @@ export function setNetworkInfo({ isOnline, networkType, details }: NetworkInfo)
* }}
* @private
*/
export function _storeNetworkInfoCleanup(cleanup?: Function) {
export function _storeNetworkInfoCleanup(cleanup: Function): Object {
return {
type: _STORE_NETWORK_INFO_CLEANUP,
cleanup

View File

@@ -1,3 +1,5 @@
// @flow
import { getLogger } from '../logging/functions';
export default getLogger('features/base/net-info');

View File

@@ -1,7 +1,8 @@
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app/actionTypes';
import MiddlewareRegistry from '../redux/MiddlewareRegistry';
// @flow
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app';
import { MiddlewareRegistry } from '../redux';
// @ts-ignore
import NetworkInfoService from './NetworkInfoService';
import { _storeNetworkInfoCleanup, setNetworkInfo } from './actions';
import { STORE_NAME } from './constants';

View File

@@ -1,13 +1,11 @@
import { IState } from '../../app/types';
import { STORE_NAME } from './constants';
/**
* A selector for the internet online status.
*
* @param {IState} state - The redux state.
* @param {Object} state - The redux state.
* @returns {boolean}
*/
export function isOnline(state: IState) {
export function isOnline(state) {
return state[STORE_NAME].isOnline;
}

View File

@@ -1,3 +1,5 @@
// @flow
import { NetInfoCellularGeneration, NetInfoStateType } from '@react-native-community/netinfo';
/**
@@ -6,32 +8,32 @@ import { NetInfoCellularGeneration, NetInfoStateType } from '@react-native-commu
*/
export type NetworkInfo = {
/**
* Any extra info provided by the OS. Should be JSON and is OS specific. Reported only by iOS and Android and
* the format is whatever comes out of the 'react-native-netinfo' library which is network type dependent.
*/
details?: {
/**
* If {@link networkType} is {@link NetInfoStateType.cellular} then it may provide the info about the type of
* cellular network.
*/
cellularGeneration?: NetInfoCellularGeneration;
/**
* Indicates whether or not the connection is expensive.
*/
isConnectionExpensive?: boolean;
};
/**
* Tells whether or not the internet is reachable.
*/
isOnline: boolean;
isOnline: boolean,
/**
* The network type. Currently reported only on Android/iOS. Can be one of the constants defined by
* the 'react-native-netinfo' library.
*/
networkType?: NetInfoStateType;
};
networkType: ?NetInfoStateType,
/**
* Any extra info provided by the OS. Should be JSON and is OS specific. Reported only by iOS and Android and
* the format is whatever comes out of the 'react-native-netinfo' library which is network type dependent.
*/
details: ?{
/**
* If {@link networkType} is {@link NetInfoStateType.cellular} then it may provide the info about the type of
* cellular network.
*/
cellularGeneration: ?NetInfoCellularGeneration;
/**
* Indicates whether or not the connection is expensive.
*/
isConnectionExpensive: ?boolean;
}
}

View File

@@ -8,8 +8,7 @@
* participant: {
* conference: JitsiConference,
* id: string,
* previousSpeakers: Array<string>,
* silence: boolean
* previousSpeakers: Array<string>
* }
* }
*/

View File

@@ -1,19 +1,21 @@
import { IStore } from '../../app/types';
import { Dispatch } from 'redux';
// @ts-ignore
import { showNotification } from '../../notifications/actions';
import { NOTIFICATION_TIMEOUT_TYPE } from '../../notifications/constants';
import { set } from '../redux/functions';
import {
DOMINANT_SPEAKER_CHANGED,
GRANT_MODERATOR,
HIDDEN_PARTICIPANT_JOINED,
HIDDEN_PARTICIPANT_LEFT,
GRANT_MODERATOR,
KICK_PARTICIPANT,
LOCAL_PARTICIPANT_AUDIO_LEVEL_CHANGED,
LOCAL_PARTICIPANT_RAISE_HAND,
MUTE_REMOTE_PARTICIPANT,
OVERWRITE_PARTICIPANTS_NAMES,
OVERWRITE_PARTICIPANT_NAME,
OVERWRITE_PARTICIPANTS_NAMES,
PARTICIPANT_ID_CHANGED,
PARTICIPANT_JOINED,
PARTICIPANT_KICKED,
@@ -30,10 +32,10 @@ import {
} from './constants';
import {
getLocalParticipant,
getVirtualScreenshareParticipantOwnerId,
getNormalizedDisplayName,
getParticipantById,
getParticipantDisplayName,
getVirtualScreenshareParticipantOwnerId
getParticipantById
} from './functions';
import logger from './logger';
import { Participant } from './types';
@@ -43,7 +45,6 @@ import { Participant } from './types';
*
* @param {string} dominantSpeaker - Participant ID of the dominant speaker.
* @param {Array<string>} previousSpeakers - Participant IDs of the previous speakers.
* @param {boolean} silence - Whether the dominant speaker is silent or not.
* @param {JitsiConference} conference - The {@code JitsiConference} associated
* with the participant identified by the specified {@code id}. Only the local
* participant is allowed to not specify an associated {@code JitsiConference}
@@ -53,20 +54,17 @@ import { Participant } from './types';
* participant: {
* conference: JitsiConference,
* id: string,
* previousSpeakers: Array<string>,
* silence: boolean
* previousSpeakers: Array<string>
* }
* }}
*/
export function dominantSpeakerChanged(
dominantSpeaker: string, previousSpeakers: string[], silence: boolean, conference: any) {
export function dominantSpeakerChanged(dominantSpeaker: string, previousSpeakers: string[], conference: any) {
return {
type: DOMINANT_SPEAKER_CHANGED,
participant: {
conference,
id: dominantSpeaker,
previousSpeakers,
silence
previousSpeakers
}
};
}
@@ -113,7 +111,7 @@ export function kickParticipant(id: string) {
* @returns {Function}
*/
export function localParticipantConnectionStatusChanged(connectionStatus: string) {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
return (dispatch: Dispatch, getState: Function) => {
const participant = getLocalParticipant(getState);
if (participant) {
@@ -133,7 +131,7 @@ export function localParticipantConnectionStatusChanged(connectionStatus: string
* @returns {Function}
*/
export function localParticipantIdChanged(id: string) {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
return (dispatch: Dispatch, getState: Function) => {
const participant = getLocalParticipant(getState);
if (participant) {
@@ -169,7 +167,7 @@ export function localParticipantJoined(participant: Participant = { id: '' }) {
* @returns {Function}
*/
export function localParticipantLeft() {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
return (dispatch: Dispatch, getState: Function) => {
const participant = getLocalParticipant(getState);
if (participant) {
@@ -199,7 +197,7 @@ export function localParticipantLeft() {
* @returns {Function}
*/
export function localParticipantRoleChanged(role: string) {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
return (dispatch: Dispatch, getState: Function) => {
const participant = getLocalParticipant(getState);
if (participant) {
@@ -278,7 +276,7 @@ export function participantJoined(participant: Participant) {
'A remote participant must be associated with a JitsiConference!');
}
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
return (dispatch: Dispatch, getState: Function) => {
// A remote participant is only expected to join in a joined or joining
// conference. The following check is really necessary because a
// JitsiConference may have moved into leaving but may still manage to
@@ -308,7 +306,7 @@ export function participantJoined(participant: Participant) {
* }}
*/
export function updateRemoteParticipantFeatures(jitsiParticipant: any) {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
return (dispatch: Dispatch, getState: Function) => {
if (!jitsiParticipant) {
return;
}
@@ -506,7 +504,7 @@ export function participantUpdated(participant: Participant = { id: '' }) {
* @returns {Promise}
*/
export function participantMutedUs(participant: any, track: any) {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
return (dispatch: Dispatch, getState: Function) => {
if (!participant) {
return;
}
@@ -530,7 +528,7 @@ export function participantMutedUs(participant: any, track: any) {
* @returns {Function}
*/
export function createVirtualScreenshareParticipant(sourceName: string, local: boolean) {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
return (dispatch: Dispatch<any>, getState: Function) => {
const state = getState();
const ownerId = getVirtualScreenshareParticipantOwnerId(sourceName);
const ownerName = getParticipantDisplayName(state, ownerId);
@@ -553,7 +551,7 @@ export function createVirtualScreenshareParticipant(sourceName: string, local: b
* @returns {Promise}
*/
export function participantKicked(kicker: any, kicked: any) {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
return (dispatch: Dispatch<any>, getState: Function) => {
dispatch({
type: PARTICIPANT_KICKED,

View File

@@ -12,7 +12,7 @@ import { Container, TintedView } from '../../react';
import { connect } from '../../redux';
import { TestHint } from '../../testing/components';
import { getVideoTrackByParticipant } from '../../tracks';
import { getParticipantById, shouldRenderParticipantVideo } from '../functions';
import { shouldRenderParticipantVideo, getParticipantById } from '../functions';
import styles from './styles';

Some files were not shown because too many files have changed in this diff Show More