Compare commits

...

30 Commits

Author SHA1 Message Date
Saúl Ibarra Corretgé
d9da14ab12 log: fix log formatting 2019-09-08 19:28:28 +02:00
Saúl Ibarra Corretgé
f6fb859531 build: exit with an error if bundle sizes increase too much
The currently selected values are a bit above the actual sizes, so if a PR
increases the bundle size enough to trigger the failure, it should bump it.
It better have a good reason for it though!
2019-09-06 17:46:25 +02:00
Saúl Ibarra Corretgé
7deb2006c3 build: add integration with webpack-bundle-analyzer
Build as follows to build (production) bundle size stats:

npx webpack -p --progress --analyze-bundle

Then open the report:

npx webpack-bundle-analyzer build/stats.json build/
2019-09-06 17:46:25 +02:00
Saúl Ibarra Corretgé
2aea24ffad dial-in-info: fix bundle bloat
The direct import sidesteps many chained-effect imports, halving the bundle
size.
2019-09-06 16:29:23 +02:00
Saúl Ibarra Corretgé
b5aae0b58d build: style 2019-09-06 16:29:23 +02:00
Saúl Ibarra Corretgé
d436825a45 flacworker: don't use the Grand Unified Logger
There are just a couple of logs in this feature, and it's a standalone bundle,
which would bloat it due to cascaded dependencis.
2019-09-06 16:29:23 +02:00
Saúl Ibarra Corretgé
5276cb6bc8 alwaysontop: don't use the Grand Unified Logger
There are just a couple of logs in this feature, and it's a standalone bundle,
which would bloat it due to cascaded dependencis.
2019-09-06 16:29:23 +02:00
Saúl Ibarra Corretgé
f863733dd3 base/util: don't use the Grand Unified Logger
There are just a couple of logs in this feature, and it's included in bundles
like external_api, which would bloat it due to cascaded dependencis.
2019-09-06 16:29:23 +02:00
Saúl Ibarra Corretgé
2ccd4968a4 external_api: don't use the Jitsi Meet logger
This is for other applications to use, and it's currently only used for logging
1 line, so use console.error.
2019-09-06 16:29:23 +02:00
Saúl Ibarra Corretgé
c233433243 deps: react-native-webrtc@latest 2019-09-05 16:37:51 +02:00
Saúl Ibarra Corretgé
6861f463b3 android: update SDK release script to publish JSC artifacts
In
b53a034aaf (diff-0339cf92cc68bc5981fe6df601316c1c)
I removed this, because RN has updated the builtin JSC version. On the next
release, however, RN introduced a new JS interpreter (Hermes) so JSC is now a RN
dependency. Thus, add the magic spells to publish the AARs to Maven.
2019-09-05 16:32:53 +02:00
Hristo Terezov
ac065f0225 chore(package.json): Update LJM 2019-09-05 04:33:02 -07:00
Saúl Ibarra Corretgé
b4b33c94dd ios: update Podfile.lock 2019-09-05 12:53:26 +02:00
Saúl Ibarra Corretgé
c8753230a4 deps: react-native-webrtc@latest 2019-09-04 20:27:33 +02:00
paweldomas
dbf569e29e chore(deps): update LJM to 00920c0f655a74c757c7fef2cdbd053ae4d1f485 2019-09-04 10:46:18 -05:00
Saúl Ibarra Corretgé
27205e3119 ios: divert RN logs to our logger 2019-09-04 17:45:18 +02:00
Saúl Ibarra Corretgé
f2fdef8361 ios: log fatal errors, don't swallow exceptions 2019-09-04 17:45:18 +02:00
George Politis
d4dd5ab46a deps: lib-jitsi-meet@latest 2019-09-04 17:29:28 +02:00
Saúl Ibarra Corretgé
902da8cc4f rn: add native loggers
These provide the ability to integrate the SDK with some other application
loggers.

At the time this was written we use Timber on Android and CocoaLumberjack on iOS.

In addition to the integration capabilities, a LogBridge React Native module
provides log transports for JavaScript code, thus centralizing all logs on the
native loggers.
2019-09-04 10:50:30 +02:00
Saúl Ibarra Corretgé
c0a5e4f203 rn: fix crash when serializing calendar entries on iOS
Original PR: https://github.com/wmcmahan/react-native-calendar-events/pull/253
2019-09-03 12:37:31 +02:00
virtuacoplenny
55ff9dbe80 feat(api): expose method for playing touch tones (#4584) 2019-08-30 14:17:22 -07:00
Hristo Terezov
bd99108e8e feat(analytics):Add white/black list functionality 2019-08-30 10:26:22 -07:00
damencho
0c042b4078 Adds config to auto turn on captions when recording is started. 2019-08-30 15:46:29 +01:00
damencho
743bbcb846 Commit from translate.jitsi.org by user damencho.: 548 of 596 strings translated (3 fuzzy). 2019-08-30 14:47:00 +00:00
damencho
4ef2f0211a Commit from translate.jitsi.org by user damencho.: 436 of 596 strings translated (18 fuzzy). 2019-08-30 14:46:52 +00:00
damencho
86f765a01f Commit from translate.jitsi.org by user damencho.: 596 of 596 strings translated (0 fuzzy). 2019-08-30 14:46:23 +00:00
damencho
9e8b8313e0 Commit from translate.jitsi.org by user damencho.: 438 of 586 strings translated (16 fuzzy). 2019-08-30 14:46:11 +00:00
damencho
f4a8115b00 Commit from translate.jitsi.org by user damencho.: 552 of 586 strings translated (3 fuzzy). 2019-08-30 14:46:01 +00:00
Bettenbuk Zoltan
a93bd422d3 feat: new invite layout 2019-08-28 13:57:33 +02:00
Bettenbuk Zoltan
c1598b7376 feat: make display name prompt platform independent 2019-08-26 22:20:22 +02:00
84 changed files with 1762 additions and 547 deletions

View File

@@ -10,6 +10,7 @@ MVN_HTTP=0
DEFAULT_SDK_VERSION=$(grep sdkVersion ${THIS_DIR}/../gradle.properties | cut -d"=" -f2)
SDK_VERSION=${OVERRIDE_SDK_VERSION:-${DEFAULT_SDK_VERSION}}
RN_VERSION=$(jq -r '.dependencies."react-native"' ${THIS_DIR}/../../package.json)
JSC_VERSION="r"$(jq -r '.dependencies."jsc-android"' ${THIS_DIR}/../../node_modules/react-native/package.json | cut -d . -f 1)
DO_GIT_TAG=${GIT_TAG:-0}
if [[ $THE_MVN_REPO == http* ]]; then
@@ -37,14 +38,20 @@ if [[ $MVN_HTTP == 1 ]]; then
-DgeneratePom=false \
-DpomFile=react-native-${RN_VERSION}.pom || true
popd
# Push JSC
echo "Pushing JSC ${JSC_VERSION} to the Maven repo"
pushd ${THIS_DIR}/../../node_modules/jsc-android/dist/org/webkit/android-jsc/${JSC_VERSION}
mvn \
deploy:deploy-file \
-Durl=${MVN_REPO} \
-DrepositoryId=${MVN_REPO_ID} \
-Dfile=android-jsc-${JSC_VERSION}.aar \
-Dpackaging=aar \
-DgeneratePom=false \
-DpomFile=android-jsc-${JSC_VERSION}.pom || true
popd
else
# Check if an SDK with that same version has already been released
if [[ -d ${MVN_REPO}/org/jitsi/react/jitsi-meet-sdk/${SDK_VERSION} ]]; then
echo "There is already a release with that version in the Maven repo!"
exit 1
fi
# First push React Native, if necessary
# Push React Native, if necessary
if [[ ! -d ${MVN_REPO}/com/facebook/react/react-native/${RN_VERSION} ]]; then
echo "Pushing React Native ${RN_VERSION} to the Maven repo"
pushd ${THIS_DIR}/../../node_modules/react-native/android/com/facebook/react/react-native/${RN_VERSION}
@@ -57,6 +64,26 @@ else
-DpomFile=react-native-${RN_VERSION}.pom
popd
fi
# Push JSC, if necessary
if [[ ! -d ${MVN_REPO}/org/webkit/android-jsc/${JSC_VERSION} ]]; then
echo "Pushing JSC ${JSC_VERSION} to the Maven repo"
pushd ${THIS_DIR}/../../node_modules/jsc-android/dist/org/webkit/android-jsc/${JSC_VERSION}
mvn \
deploy:deploy-file \
-Durl=${MVN_REPO} \
-Dfile=android-jsc-${JSC_VERSION}.aar \
-Dpackaging=aar \
-DgeneratePom=false \
-DpomFile=android-jsc-${JSC_VERSION}.pom
popd
fi
# Check if an SDK with that same version has already been released
if [[ -d ${MVN_REPO}/org/jitsi/react/jitsi-meet-sdk/${SDK_VERSION} ]]; then
echo "There is already a release with that version in the Maven repo!"
exit 1
fi
fi
# Now build and publish the Jitsi Meet SDK and its dependencies

View File

@@ -44,6 +44,7 @@ dependencies {
implementation 'org.webkit:android-jsc:+'
implementation 'com.dropbox.core:dropbox-core-sdk:3.0.8'
implementation 'com.jakewharton.timber:timber:4.7.1'
if (!rootProject.ext.libreBuild) {
implementation 'com.amplitude:android-sdk:2.14.1'

View File

@@ -24,6 +24,7 @@ import com.facebook.react.bridge.ReadableMap;
import com.amplitude.api.Amplitude;
import com.facebook.react.module.annotations.ReactModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import org.json.JSONException;
import org.json.JSONObject;
@@ -90,7 +91,7 @@ class AmplitudeModule
JSONObject eventProps = new JSONObject(eventPropsString);
Amplitude.getInstance(instanceName).logEvent(eventType, eventProps);
} catch (JSONException e) {
e.printStackTrace();
JitsiMeetLogger.e(e, "Error logging event");
}
}

View File

@@ -25,7 +25,6 @@ import android.content.pm.PackageManager;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.os.Build;
import android.util.Log;
import androidx.annotation.RequiresApi;
import com.facebook.react.bridge.Arguments;
@@ -37,6 +36,8 @@ import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.module.annotations.ReactModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -121,7 +122,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
case DEVICE_SPEAKER:
return android.telecom.CallAudioState.ROUTE_SPEAKER;
default:
Log.e(TAG, "Unsupported device name: " + audioDevice);
JitsiMeetLogger.e(TAG + " Unsupported device name: " + audioDevice);
return android.telecom.CallAudioState.ROUTE_EARPIECE;
}
}
@@ -218,7 +219,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
}
availableDevices = devices;
Log.d(TAG, "Available audio devices: " +
JitsiMeetLogger.i(TAG + " Available audio devices: " +
availableDevices.toString());
// Reset user selection
@@ -360,7 +361,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
data.pushMap(deviceInfo);
}
ReactInstanceManagerHolder.emitEvent(DEVICE_CHANGE_EVENT, data);
Log.i(TAG, "Updating audio device list");
JitsiMeetLogger.i(TAG + " Updating audio device list");
}
});
}
@@ -443,8 +444,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
if (audioDevicesChanged) {
supportedRouteMask = newSupportedRoutes;
availableDevices = routesToDeviceNames(supportedRouteMask);
Log.d(TAG,
"Available audio devices: "
JitsiMeetLogger.i(TAG + " Available audio devices: "
+ availableDevices.toString());
}
@@ -478,7 +478,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN: {
Log.d(TAG, "Audio focus gained");
JitsiMeetLogger.d(TAG + " Audio focus gained");
// Some other application potentially stole our audio focus
// temporarily. Restore our mode.
if (audioFocusLost) {
@@ -490,7 +490,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
case AudioManager.AUDIOFOCUS_LOSS:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: {
Log.d(TAG, "Audio focus lost");
JitsiMeetLogger.d(TAG + " Audio focus lost");
audioFocusLost = true;
break;
}
@@ -517,13 +517,13 @@ class AudioModeModule extends ReactContextBaseJavaModule
@Override
public void run() {
if (!availableDevices.contains(device)) {
Log.d(TAG, "Audio device not available: " + device);
JitsiMeetLogger.w(TAG + " Audio device not available: " + device);
userSelectedDevice = null;
return;
}
if (mode != -1) {
Log.d(TAG, "User selected device set to: " + device);
JitsiMeetLogger.i(TAG + " User selected device set to: " + device);
userSelectedDevice = device;
updateAudioRoute(mode);
}
@@ -594,10 +594,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
success = updateAudioRoute(mode);
} catch (Throwable e) {
success = false;
Log.e(
TAG,
"Failed to update audio route for mode: " + mode,
e);
JitsiMeetLogger.e(e, TAG + " Failed to update audio route for mode: " + mode);
}
if (success) {
AudioModeModule.this.mode = mode;
@@ -633,14 +630,14 @@ class AudioModeModule extends ReactContextBaseJavaModule
@Override
public void onAudioDevicesAdded(
AudioDeviceInfo[] addedDevices) {
Log.d(TAG, "Audio devices added");
JitsiMeetLogger.d(TAG + " Audio devices added");
onAudioDeviceChange();
}
@Override
public void onAudioDevicesRemoved(
AudioDeviceInfo[] removedDevices) {
Log.d(TAG, "Audio devices removed");
JitsiMeetLogger.d(TAG + " Audio devices removed");
onAudioDeviceChange();
}
};
@@ -659,7 +656,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
BroadcastReceiver wiredHeadsetReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Wired headset added / removed");
JitsiMeetLogger.d(TAG + " Wired headset added / removed");
onHeadsetDeviceChange();
}
};
@@ -677,7 +674,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
* {@code false}, otherwise.
*/
private boolean updateAudioRoute(int mode) {
Log.d(TAG, "Update audio route for mode: " + mode);
JitsiMeetLogger.i(TAG + " Update audio route for mode: " + mode);
if (mode == DEFAULT) {
if (!useConnectionService()) {
@@ -703,7 +700,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
AudioManager.STREAM_VOICE_CALL,
AudioManager.AUDIOFOCUS_GAIN)
== AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
Log.d(TAG, "Audio focus request failed");
JitsiMeetLogger.w(TAG + " Audio focus request failed");
return false;
}
}
@@ -734,7 +731,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
}
selectedDevice = audioDevice;
Log.d(TAG, "Selected audio device: " + audioDevice);
JitsiMeetLogger.i(TAG + " Selected audio device: " + audioDevice);
if (useConnectionService()) {
setAudioRoute(audioDevice);

View File

@@ -24,7 +24,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.util.Log;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
/**
* Helper class to detect and handle Bluetooth device changes. It monitors
@@ -77,7 +78,7 @@ class BluetoothHeadsetMonitor {
= (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
if (!audioManager.isBluetoothScoAvailableOffCall()) {
Log.w(AudioModeModule.TAG, "Bluetooth SCO is not available");
JitsiMeetLogger.w(AudioModeModule.TAG + " Bluetooth SCO is not available");
return;
}
@@ -93,7 +94,7 @@ class BluetoothHeadsetMonitor {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter == null) {
Log.w(AudioModeModule.TAG, "Device doesn't support Bluetooth");
JitsiMeetLogger.w(AudioModeModule.TAG + " Device doesn't support Bluetooth");
return false;
}
@@ -148,9 +149,7 @@ class BluetoothHeadsetMonitor {
switch (state) {
case BluetoothHeadset.STATE_CONNECTED:
case BluetoothHeadset.STATE_DISCONNECTED:
Log.d(
AudioModeModule.TAG,
"BT headset connection state changed: " + state);
JitsiMeetLogger.d(AudioModeModule.TAG + " BT headset connection state changed: " + state);
updateDevices();
break;
}
@@ -164,9 +163,7 @@ class BluetoothHeadsetMonitor {
switch (state) {
case AudioManager.SCO_AUDIO_STATE_CONNECTED:
case AudioManager.SCO_AUDIO_STATE_DISCONNECTED:
Log.d(
AudioModeModule.TAG,
"BT SCO connection state changed: " + state);
JitsiMeetLogger.d(AudioModeModule.TAG + " BT SCO connection state changed: " + state);
updateDevices();
break;
}

View File

@@ -13,13 +13,14 @@ import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.util.Log;
import androidx.annotation.RequiresApi;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableNativeMap;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -129,9 +130,7 @@ public class ConnectionService extends android.telecom.ConnectionService {
if (connection != null) {
connection.setActive();
} else {
Log.e(TAG, String.format(
"setConnectionActive - no connection for UUID: %s",
callUUID));
JitsiMeetLogger.e("% setConnectionActive - no connection for UUID: %s", TAG, callUUID);
}
}
@@ -162,7 +161,7 @@ public class ConnectionService extends android.telecom.ConnectionService {
connection.setDisconnected(cause);
connection.destroy();
} else {
Log.e(TAG, "endCall no connection for UUID: " + callUUID);
JitsiMeetLogger.e(TAG + " endCall no connection for UUID: " + callUUID);
}
}
@@ -194,15 +193,14 @@ public class ConnectionService extends android.telecom.ConnectionService {
boolean hasVideo
= callState.getBoolean(ConnectionImpl.KEY_HAS_VIDEO);
Log.d(TAG, String.format(
"updateCall: %s hasVideo: %s", callUUID, hasVideo));
JitsiMeetLogger.i(" %s updateCall: %s hasVideo: %s", TAG, callUUID, hasVideo);
connection.setVideoState(
hasVideo
? VideoProfile.STATE_BIDIRECTIONAL
: VideoProfile.STATE_AUDIO_ONLY);
}
} else {
Log.e(TAG, "updateCall no connection for UUID: " + callUUID);
JitsiMeetLogger.e(TAG + " updateCall no connection for UUID: " + callUUID);
}
}
@@ -238,13 +236,11 @@ public class ConnectionService extends android.telecom.ConnectionService {
= unregisterStartCallPromise(connection.getCallUUID());
if (startCallPromise != null) {
Log.d(TAG,
"onCreateOutgoingConnection " + connection.getCallUUID());
JitsiMeetLogger.d(TAG + " onCreateOutgoingConnection " + connection.getCallUUID());
startCallPromise.resolve(null);
} else {
Log.e(TAG, String.format(
"onCreateOutgoingConnection: no start call Promise for %s",
connection.getCallUUID()));
JitsiMeetLogger.e(
TAG + " onCreateOutgoingConnection: no start call Promise for " + connection.getCallUUID());
}
return connection;
@@ -268,7 +264,7 @@ public class ConnectionService extends android.telecom.ConnectionService {
PhoneAccountHandle theAccountHandle = request.getAccountHandle();
String callUUID = theAccountHandle.getId();
Log.e(TAG, "onCreateOutgoingConnectionFailed " + callUUID);
JitsiMeetLogger.e(TAG + " onCreateOutgoingConnectionFailed " + callUUID);
if (callUUID != null) {
Promise startCallPromise = unregisterStartCallPromise(callUUID);
@@ -278,12 +274,10 @@ public class ConnectionService extends android.telecom.ConnectionService {
"CREATE_OUTGOING_CALL_FAILED",
"The request has been denied by the system");
} else {
Log.e(TAG, String.format(
"startCallFailed - no start call Promise for UUID: %s",
callUUID));
JitsiMeetLogger.e(TAG + " startCallFailed - no start call Promise for UUID: " + callUUID);
}
} else {
Log.e(TAG, "onCreateOutgoingConnectionFailed - no call UUID");
JitsiMeetLogger.e(TAG + " onCreateOutgoingConnectionFailed - no call UUID");
}
unregisterPhoneAccount(theAccountHandle);
@@ -295,10 +289,10 @@ public class ConnectionService extends android.telecom.ConnectionService {
if (phoneAccountHandle != null) {
telecom.unregisterPhoneAccount(phoneAccountHandle);
} else {
Log.e(TAG, "unregisterPhoneAccount - account handle is null");
JitsiMeetLogger.e(TAG + " unregisterPhoneAccount - account handle is null");
}
} else {
Log.e(TAG, "unregisterPhoneAccount - telecom is null");
JitsiMeetLogger.e(TAG + "unregisterPhoneAccount - telecom is null");
}
}
@@ -357,7 +351,7 @@ public class ConnectionService extends android.telecom.ConnectionService {
*/
@Override
public void onDisconnect() {
Log.d(TAG, "onDisconnect " + getCallUUID());
JitsiMeetLogger.i(TAG + " onDisconnect " + getCallUUID());
WritableNativeMap data = new WritableNativeMap();
data.putString("callUUID", getCallUUID());
ReactInstanceManagerHolder.emitEvent(
@@ -377,7 +371,7 @@ public class ConnectionService extends android.telecom.ConnectionService {
*/
@Override
public void onAbort() {
Log.d(TAG, "onAbort " + getCallUUID());
JitsiMeetLogger.i(TAG + " onAbort " + getCallUUID());
WritableNativeMap data = new WritableNativeMap();
data.putString("callUUID", getCallUUID());
ReactInstanceManagerHolder.emitEvent(
@@ -395,9 +389,7 @@ public class ConnectionService extends android.telecom.ConnectionService {
// What ?! Android will still call this method even if we do not add
// the HOLD capability, so do the same thing as on abort.
// TODO implement HOLD
Log.d(TAG, String.format(
"onHold %s - HOLD is not supported, aborting the call...",
getCallUUID()));
JitsiMeetLogger.w(TAG + " onHold %s - HOLD is not supported, aborting the call...", getCallUUID());
this.onAbort();
}
@@ -410,7 +402,7 @@ public class ConnectionService extends android.telecom.ConnectionService {
*/
@Override
public void onCallAudioStateChanged(CallAudioState state) {
Log.d(TAG, "onCallAudioStateChanged: " + state);
JitsiMeetLogger.d(TAG + " onCallAudioStateChanged: " + state);
AudioModeModule audioModeModule
= ReactInstanceManagerHolder
.getNativeModule(AudioModeModule.class);
@@ -426,10 +418,8 @@ public class ConnectionService extends android.telecom.ConnectionService {
*/
@Override
public void onStateChanged(int state) {
Log.d(TAG,
String.format("onStateChanged: %s %s",
Connection.stateToString(state),
getCallUUID()));
JitsiMeetLogger.d(
"%s onStateChanged: %s %s", TAG, Connection.stateToString(state), getCallUUID());
if (state == STATE_DISCONNECTED) {
removeConnection(this);

View File

@@ -16,14 +16,14 @@
package org.jitsi.meet.sdk;
import android.util.Log;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.module.annotations.ReactModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
/**
* Module implementing an API for sending events from JavaScript to native code.
*/
@@ -76,11 +76,11 @@ class ExternalAPIModule
BaseReactView view = BaseReactView.findViewByExternalAPIScope(scope);
if (view != null) {
Log.d(TAG, "Sending event: " + name + " with data: " + data);
JitsiMeetLogger.d(TAG + " Sending event: " + name + " with data: " + data);
try {
view.onExternalAPIEvent(name, data);
} catch(Exception e) {
Log.e(TAG, "onExternalAPIEvent: error sending event", e);
JitsiMeetLogger.e(e, TAG + " onExternalAPIEvent: error sending event");
}
}
}

View File

@@ -20,12 +20,13 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import com.facebook.react.modules.core.PermissionListener;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.Map;
@@ -208,19 +209,19 @@ public class JitsiMeetActivity extends FragmentActivity
@Override
public void onConferenceJoined(Map<String, Object> data) {
Log.d(TAG, "Conference joined: " + data);
JitsiMeetLogger.i("Conference joined: " + data);
// Launch the service for the ongoing notification.
JitsiMeetOngoingConferenceService.launch(this);
}
@Override
public void onConferenceTerminated(Map<String, Object> data) {
Log.d(TAG, "Conference terminated: " + data);
JitsiMeetLogger.i("Conference terminated: " + data);
finish();
}
@Override
public void onConferenceWillJoin(Map<String, Object> data) {
Log.d(TAG, "Conference will join: " + data);
JitsiMeetLogger.i("Conference will join: " + data);
}
}

View File

@@ -23,7 +23,8 @@ import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
/**
@@ -55,7 +56,7 @@ public class JitsiMeetOngoingConferenceService extends Service
componentName = context.startService(intent);
}
if (componentName == null) {
Log.w(TAG, "Ongoing conference service not started");
JitsiMeetLogger.w(TAG + " Ongoing conference service not started");
}
}
@@ -90,20 +91,20 @@ public class JitsiMeetOngoingConferenceService extends Service
Notification notification = OngoingNotification.buildOngoingConferenceNotification();
if (notification == null) {
stopSelf();
Log.w(TAG, "Couldn't start service, notification is null");
JitsiMeetLogger.w(TAG + " Couldn't start service, notification is null");
} else {
startForeground(OngoingNotification.NOTIFICATION_ID, notification);
Log.i(TAG, "Service started");
JitsiMeetLogger.i(TAG + " Service started");
}
} else if (action.equals(Actions.HANGUP)) {
Log.i(TAG, "Hangup requested");
JitsiMeetLogger.i(TAG + " Hangup requested");
// Abort all ongoing calls
if (AudioModeModule.useConnectionService()) {
ConnectionService.abortConnections();
}
stopSelf();
} else {
Log.w(TAG, "Unknown action received: " + action);
JitsiMeetLogger.w(TAG + " Unknown action received: " + action);
stopSelf();
}
@@ -114,7 +115,7 @@ public class JitsiMeetOngoingConferenceService extends Service
public void onCurrentConferenceChanged(String conferenceUrl) {
if (conferenceUrl == null) {
stopSelf();
Log.i(TAG, "Service stopped");
JitsiMeetLogger.i(TAG + "Service stopped");
}
}
}

View File

@@ -17,7 +17,7 @@
package org.jitsi.meet.sdk;
import android.util.Log;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
class JitsiMeetUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
private final Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler;
@@ -37,7 +37,7 @@ class JitsiMeetUncaughtExceptionHandler implements Thread.UncaughtExceptionHandl
@Override
public void uncaughtException(Thread t, Throwable e) {
Log.e(this.getClass().getSimpleName(), "FATAL ERROR", e);
JitsiMeetLogger.e(e, this.getClass().getSimpleName() + " FATAL ERROR");
// Abort all ConnectionService ongoing calls
if (AudioModeModule.useConnectionService()) {

View File

@@ -19,12 +19,13 @@ package org.jitsi.meet.sdk;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReadableMap;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.lang.reflect.Method;
import java.util.Map;
@@ -39,12 +40,6 @@ public class JitsiMeetView extends BaseReactView<JitsiMeetViewListener>
private static final Map<String, Method> LISTENER_METHODS
= ListenerUtils.mapListenerMethods(JitsiMeetViewListener.class);
/**
* The {@link Log} tag which identifies the source of the log messages of
* {@code JitsiMeetView}.
*/
private static final String TAG = JitsiMeetView.class.getSimpleName();
/**
* The URL of the current conference.
*/
@@ -137,7 +132,7 @@ public class JitsiMeetView extends BaseReactView<JitsiMeetViewListener>
try {
pipModule.enterPictureInPicture();
} catch (RuntimeException re) {
Log.e(TAG, "failed to enter PiP mode", re);
JitsiMeetLogger.e(re, "Failed to enter PiP mode");
}
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jitsi.meet.sdk;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.module.annotations.ReactModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import javax.annotation.Nonnull;
/**
* Module implementing a "bridge" between the JS loggers and the native one.
*/
@ReactModule(name = LogBridgeModule.NAME)
class LogBridgeModule extends ReactContextBaseJavaModule {
public static final String NAME = "LogBridge";
public LogBridgeModule(@Nonnull ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return NAME;
}
@ReactMethod
public void trace(final String message) {
JitsiMeetLogger.v(message);
}
@ReactMethod
public void debug(final String message) {
JitsiMeetLogger.d(message);
}
@ReactMethod
public void info(final String message) {
JitsiMeetLogger.i(message);
}
@ReactMethod
public void log(final String message) {
JitsiMeetLogger.i(message);
}
@ReactMethod
public void warn(final String message) {
JitsiMeetLogger.w(message);
}
@ReactMethod
public void error(final String message) {
JitsiMeetLogger.e(message);
}
}

View File

@@ -24,7 +24,8 @@ import android.content.Context;
import android.content.Intent;
import android.os.Build;
import androidx.core.app.NotificationCompat;
import android.util.Log;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.Random;
@@ -50,7 +51,7 @@ class OngoingNotification {
Context context = ReactInstanceManagerHolder.getCurrentActivity();
if (context == null) {
Log.w(TAG, "Cannot create notification channel: no current context");
JitsiMeetLogger.w(TAG + " Cannot create notification channel: no current context");
return;
}
@@ -75,7 +76,7 @@ class OngoingNotification {
static Notification buildOngoingConferenceNotification() {
Context context = ReactInstanceManagerHolder.getCurrentActivity();
if (context == null) {
Log.w(TAG, "Cannot create notification: no current context");
JitsiMeetLogger.w(TAG + " Cannot create notification: no current context");
return null;
}

View File

@@ -20,7 +20,6 @@ import android.annotation.TargetApi;
import android.app.Activity;
import android.app.PictureInPictureParams;
import android.os.Build;
import android.util.Log;
import android.util.Rational;
import com.facebook.react.bridge.Promise;
@@ -29,6 +28,8 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.module.annotations.ReactModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
@ReactModule(name = PictureInPictureModule.NAME)
class PictureInPictureModule
extends ReactContextBaseJavaModule {
@@ -70,7 +71,7 @@ class PictureInPictureModule
throw new IllegalStateException("No current Activity!");
}
Log.d(TAG, "Entering Picture-in-Picture");
JitsiMeetLogger.i(TAG + " Entering Picture-in-Picture");
PictureInPictureParams.Builder builder
= new PictureInPictureParams.Builder()

View File

@@ -10,7 +10,6 @@ import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.util.Log;
import androidx.annotation.RequiresApi;
import com.facebook.react.bridge.Promise;
@@ -20,6 +19,8 @@ import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.module.annotations.ReactModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
/**
* The react-native side of Jitsi Meet's {@link ConnectionService}. Exposes
* the Java Script API.
@@ -74,11 +75,11 @@ class RNConnectionService
String handle,
boolean hasVideo,
Promise promise) {
Log.d(TAG,
String.format("startCall UUID=%s, h=%s, v=%s",
JitsiMeetLogger.d("%s startCall UUID=%s, h=%s, v=%s",
TAG,
callUUID,
handle,
hasVideo));
hasVideo);
ReactApplicationContext ctx = getReactApplicationContext();
@@ -118,7 +119,7 @@ class RNConnectionService
*/
@ReactMethod
public void reportCallFailed(String callUUID) {
Log.d(TAG, "reportCallFailed " + callUUID);
JitsiMeetLogger.d(TAG + " reportCallFailed " + callUUID);
ConnectionService.setConnectionDisconnected(
callUUID,
new DisconnectCause(DisconnectCause.ERROR));
@@ -131,7 +132,7 @@ class RNConnectionService
*/
@ReactMethod
public void endCall(String callUUID) {
Log.d(TAG, "endCall " + callUUID);
JitsiMeetLogger.d(TAG + " endCall " + callUUID);
ConnectionService.setConnectionDisconnected(
callUUID,
new DisconnectCause(DisconnectCause.LOCAL));
@@ -144,7 +145,7 @@ class RNConnectionService
*/
@ReactMethod
public void reportConnectedOutgoingCall(String callUUID) {
Log.d(TAG, "reportConnectedOutgoingCall " + callUUID);
JitsiMeetLogger.d(TAG + " reportConnectedOutgoingCall " + callUUID);
ConnectionService.setConnectionActive(callUUID);
}

View File

@@ -34,6 +34,7 @@ import com.facebook.soloader.SoLoader;
import com.oney.WebRTCModule.RTCVideoViewManager;
import com.oney.WebRTCModule.WebRTCModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import org.webrtc.SoftwareVideoDecoderFactory;
import org.webrtc.SoftwareVideoEncoderFactory;
import org.webrtc.VideoDecoderFactory;
@@ -67,6 +68,7 @@ class ReactInstanceManagerHolder {
new DropboxModule(reactContext),
new ExternalAPIModule(reactContext),
new LocaleDetector(reactContext),
new LogBridgeModule(reactContext),
new PictureInPictureModule(reactContext),
new ProximityModule(reactContext),
new WiFiStatsModule(reactContext),

View File

@@ -19,7 +19,6 @@ package org.jitsi.meet.sdk;
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.util.Log;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
@@ -27,6 +26,7 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.module.annotations.ReactModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import org.json.JSONArray;
import org.json.JSONObject;
@@ -184,17 +184,15 @@ class WiFiStatsModule
}
} catch (SocketException e) {
Log.wtf(TAG,
"Unable to NetworkInterface.getNetworkInterfaces()"
);
JitsiMeetLogger.e(e, TAG + " Unable to NetworkInterface.getNetworkInterfaces()");
}
result.put("addresses", addresses);
promise.resolve(result.toString());
Log.d(TAG, "WiFi stats: " + result.toString());
JitsiMeetLogger.d(TAG + " WiFi stats: " + result.toString());
} catch (Throwable e) {
Log.e(TAG, "Failed to obtain wifi stats", e);
JitsiMeetLogger.e(e, TAG + " Failed to obtain wifi stats");
promise.reject(
new Exception("Failed to obtain wifi stats"));
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jitsi.meet.sdk.log;
import android.util.Log;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.text.MessageFormat;
import timber.log.Timber;
/**
* Base class for all custom log handlers. Implementations must inherit from this class and
* implement a `doLog` method which does the actual logging, in addition with a `getTag` method
* with which to tag all logs coming into this logger.
*
* See {@link JitsiMeetDefaultLogHandler} for an example.
*/
public abstract class JitsiMeetBaseLogHandler extends Timber.Tree {
@Override
protected void log(int priority, @Nullable String tag, @NotNull String msg, @Nullable Throwable t) {
String errmsg = Log.getStackTraceString(t);
if (errmsg.isEmpty()) {
doLog(priority, getTag(), msg);
} else {
doLog(priority, getTag(), MessageFormat.format("{0}\n{1}", msg, errmsg));
}
}
protected abstract void doLog(int priority, @NotNull String tag, @NotNull String msg);
protected abstract String getTag();
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jitsi.meet.sdk.log;
import android.util.Log;
import org.jetbrains.annotations.NotNull;
/**
* Default implementation of a {@link JitsiMeetBaseLogHandler}. This is the main SDK logger, which
* logs using the Android util.Log module.
*/
public class JitsiMeetDefaultLogHandler extends JitsiMeetBaseLogHandler {
private static final String TAG = "JitsiMeetSDK";
@Override
protected void doLog(int priority, @NotNull String tag, @NotNull String msg) {
Log.println(priority, tag, msg);
}
@Override
protected String getTag() {
return TAG;
}
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jitsi.meet.sdk.log;
import timber.log.Timber;
public class JitsiMeetLogger {
static {
addHandler(new JitsiMeetDefaultLogHandler());
}
public static void addHandler(JitsiMeetBaseLogHandler handler) {
Timber.plant(handler);
}
public static void removeHandler(JitsiMeetBaseLogHandler handler) {
Timber.uproot(handler);
}
public static void v(String message, Object... args) {
Timber.v(message, args);
}
public static void v(Throwable t, String message, Object... args) {
Timber.v(t, message, args);
}
public static void v(Throwable t) {
Timber.v(t);
}
public static void d(String message, Object... args) {
Timber.d(message, args);
}
public static void d(Throwable t, String message, Object... args) {
Timber.d(t, message, args);
}
public static void d(Throwable t) {
Timber.d(t);
}
public static void i(String message, Object... args) {
Timber.i(message, args);
}
public static void i(Throwable t, String message, Object... args) {
Timber.i(t, message, args);
}
public static void i(Throwable t) {
Timber.i(t);
}
public static void w(String message, Object... args) {
Timber.w(message, args);
}
public static void w(Throwable t, String message, Object... args) {
Timber.w(t, message, args);
}
public static void w(Throwable t) {
Timber.w(t);
}
public static void e(String message, Object... args) {
Timber.e(message, args);
}
public static void e(Throwable t, String message, Object... args) {
Timber.e(t, message, args);
}
public static void e(Throwable t) {
Timber.e(t);
}
}

View File

@@ -15,14 +15,14 @@
*/
package org.jitsi.meet.sdk.net;
import android.util.Log;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.module.annotations.ReactModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.net.UnknownHostException;
/**
@@ -97,7 +97,7 @@ public class NAT64AddrInfoModule
try {
info = NAT64AddrInfo.discover(host);
} catch (UnknownHostException e) {
Log.e(TAG, "NAT64AddrInfo.discover: " + host, e);
JitsiMeetLogger.e(e, TAG + " NAT64AddrInfo.discover: " + host);
}
infoTimestamp = System.currentTimeMillis();
}
@@ -107,7 +107,7 @@ public class NAT64AddrInfoModule
try {
result = info == null ? null : info.getIPv6Address(ipv4Address);
} catch (IllegalArgumentException exc) {
Log.e(TAG, "Failed to get IPv6 address for: " + ipv4Address, exc);
JitsiMeetLogger.e(exc, TAG + " Failed to get IPv6 address for: " + ipv4Address);
// We don't want to reject. It's not a big deal if there's no IPv6
// address resolved.

View File

@@ -2200,12 +2200,6 @@ export default {
APP.keyboardshortcut.init();
if (config.requireDisplayName
&& !APP.conference.getLocalDisplayName()
&& !room.isHidden()) {
APP.UI.promptDisplayName();
}
APP.store.dispatch(conferenceJoined(room));
const displayName

View File

@@ -201,6 +201,9 @@ var config = {
// subtitles and buttons can be configured)
// transcribingEnabled: false,
// Enables automatic turning on captions when recording is started
// autoCaptionOnRecord: false,
// Misc
// Default value for the channel "last N" attribute. -1 for unlimited.

View File

@@ -25,6 +25,12 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-cancel:before {
content: "\e91c";
}
.icon-check:before {
content: "\e91b";
}
.icon-send:before {
content: "\e911";
}

View File

@@ -197,6 +197,15 @@ api.executeCommand('displayName', 'New Nickname');
api.executeCommand('password', 'The Password');
```
* **sendTones** - Play touch tones.
```javascript
api.executeCommand('sendTones', {
tones: string, // The dial pad touch tones to play. For example, '12345#'.
duration: number, // Optional. The number of milliseconds each tone should play. The default is 200.
pause: number // Optional. The number of milliseconds between each tone. The default is 200.
});
```
* **subject** - Sets the subject of the conference. This command requires one argument - the new subject to be set.
```javascript
api.executeCommand('subject', 'New Conference Subject');

Binary file not shown.

View File

@@ -54,6 +54,8 @@
<glyph unicode="&#xe918;" glyph-name="camera" d="M726 576l170 170v-468l-170 170v-150c0-24-20-42-44-42h-512c-24 0-42 18-42 42v428c0 24 18 42 42 42h512c24 0 44-18 44-42v-150z" />
<glyph unicode="&#xe919;" glyph-name="camera-disabled" d="M140 938l756-756-54-54-136 136c-6-4-16-8-24-8h-512c-24 0-42 18-42 42v428c0 24 18 42 42 42h32l-116 116zM896 746v-456l-478 478h264c24 0 44-18 44-42v-150z" />
<glyph unicode="&#xe91a;" glyph-name="volume" d="M598 886c172-38 298-192 298-374s-126-336-298-374v88c124 36 212 150 212 286s-88 250-212 286v88zM704 512c0-76-42-140-106-172v344c64-32 106-96 106-172zM128 640h170l214 214v-684l-214 214h-170v256z" />
<glyph unicode="&#xe91b;" glyph-name="check" d="M384 334l452 452 60-60-512-512-238 238 60 60z" />
<glyph unicode="&#xe91c;" glyph-name="cancel" d="M726 358l-154 154 154 154-60 60-154-154-154 154-60-60 154-154-154-154 60-60 154 154 154-154zM512 938q176 0 301-125t125-301-125-301-301-125-301 125-125 301 125 301 301 125z" />
<glyph unicode="&#xe91d;" glyph-name="feedback" d="M42.667 128h170.667v512h-170.667v-512zM981.333 597.333c0 46.933-38.4 85.333-85.333 85.333h-269.227l40.533 194.987 1.28 13.653c0 17.493-7.253 33.707-18.773 45.227l-45.227 44.8-280.747-281.173c-15.787-15.36-25.173-36.693-25.173-60.16v-426.667c0-46.933 38.4-85.333 85.333-85.333h384c35.413 0 65.707 21.333 78.507 52.053l128.853 300.8c3.84 9.813 5.973 20.053 5.973 31.147v81.493l-0.427 0.427 0.427 3.413z" />
<glyph unicode="&#xe91e;" glyph-name="raised-hand" d="M982 790v-620c0-94-78-170-172-170h-310c-46 0-90 18-122 50l-336 342s54 52 56 52c10 8 22 12 34 12 10 0 18-2 26-6 2 0 184-104 184-104v508c0 36 28 64 64 64s64-28 64-64v-300h42v406c0 36 28 64 64 64s64-28 64-64v-406h42v364c0 36 28 64 64 64s64-28 64-64v-364h44v236c0 36 28 64 64 64s64-28 64-64z" />
<glyph unicode="&#xe91f;" glyph-name="menu-up" d="M512 682l256-256-60-60-196 196-196-196-60 60z" />

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -61,6 +61,7 @@ target 'JitsiMeet' do
#
pod 'Amplitude-iOS', '~> 4.0.4'
pod 'CocoaLumberjack', '~>3.5.3'
pod 'ObjectiveDropboxOfficial', '~> 3.9.4'
use_native_modules!

View File

@@ -3,6 +3,9 @@ PODS:
- boost-for-react-native (1.63.0)
- BVLinearGradient (2.5.6):
- React
- CocoaLumberjack (3.5.3):
- CocoaLumberjack/Core (= 3.5.3)
- CocoaLumberjack/Core (3.5.3)
- Crashlytics (3.12.0):
- Fabric (~> 1.9.0)
- DoubleConversion (1.1.6)
@@ -141,7 +144,7 @@ PODS:
- React
- react-native-netinfo (4.1.5):
- React
- react-native-webrtc (1.69.2):
- react-native-webrtc (1.75.0):
- React
- react-native-webview (5.8.1):
- React
@@ -187,6 +190,7 @@ PODS:
DEPENDENCIES:
- Amplitude-iOS (~> 4.0.4)
- BVLinearGradient (from `../node_modules/react-native-linear-gradient`)
- CocoaLumberjack (~> 3.5.3)
- Crashlytics (~> 3.12.0)
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- Fabric (~> 1.9.0)
@@ -205,7 +209,7 @@ DEPENDENCIES:
- react-native-background-timer (from `../node_modules/react-native-background-timer`)
- react-native-calendar-events (from `../node_modules/react-native-calendar-events`)
- react-native-keep-awake (from `../node_modules/react-native-keep-awake`)
- react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
- react-native-webrtc (from `../node_modules/react-native-webrtc`)
- react-native-webview (from `../node_modules/react-native-webview`)
- React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
@@ -229,6 +233,7 @@ SPEC REPOS:
https://github.com/cocoapods/specs.git:
- Amplitude-iOS
- boost-for-react-native
- CocoaLumberjack
- Crashlytics
- Fabric
- Firebase
@@ -317,6 +322,7 @@ SPEC CHECKSUMS:
Amplitude-iOS: 2ad4d7270c99186236c1272a3a9425463b1ae1a7
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
CocoaLumberjack: 2f44e60eb91c176d471fdba43b9e3eae6a721947
Crashlytics: 07fb167b1694128c1c9a5a5cc319b0e9c3ca0933
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
Fabric: f988e33c97f08930a413e08123064d2e5f68d655
@@ -346,7 +352,7 @@ SPEC CHECKSUMS:
react-native-calendar-events: 2fe35a9294af05de0ed819d3a1b5dac048d2c010
react-native-keep-awake: eba3137546b10003361b37c761f6c429b59814ae
react-native-netinfo: 8d8db463bcc5db66a8ac5c48a7d86beb3b92f61a
react-native-webrtc: 1415d2a54b2246dd85ba95eb3e4bf2b66533f951
react-native-webrtc: c5e3d631179a933548a8e49bddbd8fad02586095
react-native-webview: a95842e3f351a6d2c8bc8bcc9eab689c7e7e5ad4
React-RCTActionSheet: b0f1ea83f4bf75fb966eae9bfc47b78c8d3efd90
React-RCTAnimation: 359ba1b5690b1e87cc173558a78e82d35919333e
@@ -365,6 +371,6 @@ SPEC CHECKSUMS:
RNWatch: 09738b339eceb66e4d80a2371633ca5fb380fa42
yoga: 312528f5bbbba37b4dcea5ef00e8b4033fdd9411
PODFILE CHECKSUM: 0907bfe60b5b5f11dbdc6b4e65d40a248d000513
PODFILE CHECKSUM: 0e3406a4217cc348dcadad5b016e8d939d4aa61f
COCOAPODS: 1.7.2

View File

@@ -26,8 +26,6 @@
0BCA496C1EC4BBF900B793EE /* jitsi.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 0BCA496B1EC4BBF900B793EE /* jitsi.ttf */; };
0BD906EA1EC0C00300C8C18E /* JitsiMeet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BD906E81EC0C00300C8C18E /* JitsiMeet.h */; settings = {ATTRIBUTES = (Public, ); }; };
0F65EECE1D95DA94561BB47E /* libPods-JitsiMeet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 03F2ADC957FF109849B7FCA1 /* libPods-JitsiMeet.a */; };
C30F88D0CB0F4F5593216D24 /* liveStreamingOff.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = C30F88D1CB0F4F5593216D24 /* liveStreamingOff.mp3 */; };
C30F88D2CB0F4F5593216D24 /* liveStreamingOn.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = C30F88D3CB0F4F5593216D24 /* liveStreamingOn.mp3 */; };
6C31EDC820C06D490089C899 /* recordingOn.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 6C31EDC720C06D490089C899 /* recordingOn.mp3 */; };
6C31EDCA20C06D530089C899 /* recordingOff.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 6C31EDC920C06D530089C899 /* recordingOff.mp3 */; };
75635B0A20751D6D00F29C9F /* joined.wav in Resources */ = {isa = PBXBuildFile; fileRef = 75635B0820751D6D00F29C9F /* joined.wav */; };
@@ -36,6 +34,8 @@
A4414AE020B37F1A003546E6 /* rejected.wav in Resources */ = {isa = PBXBuildFile; fileRef = A4414ADF20B37F1A003546E6 /* rejected.wav */; };
A480429C21EE335600289B73 /* AmplitudeModule.m in Sources */ = {isa = PBXBuildFile; fileRef = A480429B21EE335600289B73 /* AmplitudeModule.m */; };
A4A934E9212F3ADB001E9388 /* Dropbox.m in Sources */ = {isa = PBXBuildFile; fileRef = A4A934E8212F3ADB001E9388 /* Dropbox.m */; };
C30F88D0CB0F4F5593216D24 /* liveStreamingOff.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = C30F88D1CB0F4F5593216D24 /* liveStreamingOff.mp3 */; };
C30F88D2CB0F4F5593216D24 /* liveStreamingOn.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = C30F88D3CB0F4F5593216D24 /* liveStreamingOn.mp3 */; };
C6245F5D2053091D0040BE68 /* image-resize@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C6245F5B2053091D0040BE68 /* image-resize@2x.png */; };
C6245F5E2053091D0040BE68 /* image-resize@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C6245F5C2053091D0040BE68 /* image-resize@3x.png */; };
C69EFA0C209A0F660027712B /* JMCallKitEmitter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C69EFA09209A0F650027712B /* JMCallKitEmitter.swift */; };
@@ -43,8 +43,15 @@
C69EFA0E209A0F660027712B /* JMCallKitListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = C69EFA0B209A0F660027712B /* JMCallKitListener.swift */; };
C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3425E204EF76800E062DD /* DragGestureController.swift */; };
C6CC49AF207412CF000DFA42 /* PiPViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6CC49AE207412CF000DFA42 /* PiPViewCoordinator.swift */; };
DE65AACA2317FFCD00290BEC /* LogUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AAC92317FFCD00290BEC /* LogUtils.h */; };
DE65AACC2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */; };
DE762DB422AFDE76000DEBD6 /* JitsiMeetUserInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DE762DB322AFDE76000DEBD6 /* JitsiMeetUserInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
DE762DB622AFDE8D000DEBD6 /* JitsiMeetUserInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = DE762DB522AFDE8D000DEBD6 /* JitsiMeetUserInfo.m */; };
DE81A2D42316AC4D00AE1940 /* JitsiMeetLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = DE81A2D22316AC4D00AE1940 /* JitsiMeetLogger.h */; settings = {ATTRIBUTES = (Public, ); }; };
DE81A2D52316AC4D00AE1940 /* JitsiMeetLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = DE81A2D32316AC4D00AE1940 /* JitsiMeetLogger.m */; };
DE81A2D92316AC7600AE1940 /* LogBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = DE81A2D72316AC7600AE1940 /* LogBridge.m */; };
DE81A2DE2317ED5400AE1940 /* JitsiMeetBaseLogHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = DE81A2DC2317ED5400AE1940 /* JitsiMeetBaseLogHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
DE81A2DF2317ED5400AE1940 /* JitsiMeetBaseLogHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = DE81A2DD2317ED5400AE1940 /* JitsiMeetBaseLogHandler.m */; };
DEAD3226220C497000E93636 /* JitsiMeetConferenceOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = DEAD3224220C497000E93636 /* JitsiMeetConferenceOptions.h */; settings = {ATTRIBUTES = (Public, ); }; };
DEAD3227220C497000E93636 /* JitsiMeetConferenceOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = DEAD3225220C497000E93636 /* JitsiMeetConferenceOptions.m */; };
DEAFA779229EAD520033A7FA /* RNRootView.m in Sources */ = {isa = PBXBuildFile; fileRef = DEAFA778229EAD520033A7FA /* RNRootView.m */; };
@@ -77,8 +84,6 @@
0BD906E51EC0C00300C8C18E /* JitsiMeet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JitsiMeet.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0BD906E81EC0C00300C8C18E /* JitsiMeet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeet.h; sourceTree = "<group>"; };
0BD906E91EC0C00300C8C18E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C30F88D1CB0F4F5593216D24 /* liveStreamingOff.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = liveStreamingOff.mp3; path = ../../sounds/liveStreamingOff.mp3; sourceTree = "<group>"; };
C30F88D3CB0F4F5593216D24 /* liveStreamingOn.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = liveStreamingOn.mp3; path = ../../sounds/liveStreamingOn.mp3; sourceTree = "<group>"; };
6C31EDC720C06D490089C899 /* recordingOn.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = recordingOn.mp3; path = ../../sounds/recordingOn.mp3; sourceTree = "<group>"; };
6C31EDC920C06D530089C899 /* recordingOff.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = recordingOff.mp3; path = ../../sounds/recordingOff.mp3; sourceTree = "<group>"; };
75635B0820751D6D00F29C9F /* joined.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = joined.wav; path = ../../sounds/joined.wav; sourceTree = "<group>"; };
@@ -90,6 +95,8 @@
A480429B21EE335600289B73 /* AmplitudeModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AmplitudeModule.m; path = src/analytics/AmplitudeModule.m; sourceTree = SOURCE_ROOT; };
A4A934E8212F3ADB001E9388 /* Dropbox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Dropbox.m; sourceTree = "<group>"; };
A4A934EB21349A06001E9388 /* Dropbox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Dropbox.h; sourceTree = "<group>"; };
C30F88D1CB0F4F5593216D24 /* liveStreamingOff.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = liveStreamingOff.mp3; path = ../../sounds/liveStreamingOff.mp3; sourceTree = "<group>"; };
C30F88D3CB0F4F5593216D24 /* liveStreamingOn.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = liveStreamingOn.mp3; path = ../../sounds/liveStreamingOn.mp3; sourceTree = "<group>"; };
C6245F5B2053091D0040BE68 /* image-resize@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "image-resize@2x.png"; path = "src/picture-in-picture/image-resize@2x.png"; sourceTree = "<group>"; };
C6245F5C2053091D0040BE68 /* image-resize@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "image-resize@3x.png"; path = "src/picture-in-picture/image-resize@3x.png"; sourceTree = "<group>"; };
C69EFA09209A0F650027712B /* JMCallKitEmitter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JMCallKitEmitter.swift; sourceTree = "<group>"; };
@@ -98,9 +105,16 @@
C6A3425E204EF76800E062DD /* DragGestureController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DragGestureController.swift; sourceTree = "<group>"; };
C6CC49AE207412CF000DFA42 /* PiPViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PiPViewCoordinator.swift; sourceTree = "<group>"; };
C6F99C13204DB63D0001F710 /* JitsiMeetView+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetView+Private.h"; sourceTree = "<group>"; };
DE65AAC92317FFCD00290BEC /* LogUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LogUtils.h; sourceTree = "<group>"; };
DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetBaseLogHandler+Private.h"; sourceTree = "<group>"; };
DE762DB322AFDE76000DEBD6 /* JitsiMeetUserInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeetUserInfo.h; sourceTree = "<group>"; };
DE762DB522AFDE8D000DEBD6 /* JitsiMeetUserInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JitsiMeetUserInfo.m; sourceTree = "<group>"; };
DE762DB722AFE166000DEBD6 /* JitsiMeetUserInfo+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetUserInfo+Private.h"; sourceTree = "<group>"; };
DE81A2D22316AC4D00AE1940 /* JitsiMeetLogger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeetLogger.h; sourceTree = "<group>"; };
DE81A2D32316AC4D00AE1940 /* JitsiMeetLogger.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JitsiMeetLogger.m; sourceTree = "<group>"; };
DE81A2D72316AC7600AE1940 /* LogBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LogBridge.m; sourceTree = "<group>"; };
DE81A2DC2317ED5400AE1940 /* JitsiMeetBaseLogHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeetBaseLogHandler.h; sourceTree = "<group>"; };
DE81A2DD2317ED5400AE1940 /* JitsiMeetBaseLogHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JitsiMeetBaseLogHandler.m; sourceTree = "<group>"; };
DEAD3224220C497000E93636 /* JitsiMeetConferenceOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeetConferenceOptions.h; sourceTree = "<group>"; };
DEAD3225220C497000E93636 /* JitsiMeetConferenceOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JitsiMeetConferenceOptions.m; sourceTree = "<group>"; };
DEAD3228220C734300E93636 /* JitsiMeetConferenceOptions+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetConferenceOptions+Private.h"; sourceTree = "<group>"; };
@@ -186,8 +200,15 @@
DE762DB322AFDE76000DEBD6 /* JitsiMeetUserInfo.h */,
DE762DB722AFE166000DEBD6 /* JitsiMeetUserInfo+Private.h */,
DE762DB522AFDE8D000DEBD6 /* JitsiMeetUserInfo.m */,
DE81A2D22316AC4D00AE1940 /* JitsiMeetLogger.h */,
DE81A2D32316AC4D00AE1940 /* JitsiMeetLogger.m */,
DE81A2DC2317ED5400AE1940 /* JitsiMeetBaseLogHandler.h */,
DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */,
DE81A2DD2317ED5400AE1940 /* JitsiMeetBaseLogHandler.m */,
0B412F161EDEC65D00B1A0A6 /* JitsiMeetView.h */,
0B412F171EDEC65D00B1A0A6 /* JitsiMeetView.m */,
DE81A2D72316AC7600AE1940 /* LogBridge.m */,
DE65AAC92317FFCD00290BEC /* LogUtils.h */,
DEAFA777229EAD3B0033A7FA /* RNRootView.h */,
DEAFA778229EAD520033A7FA /* RNRootView.m */,
C6F99C13204DB63D0001F710 /* JitsiMeetView+Private.h */,
@@ -273,8 +294,12 @@
DE762DB422AFDE76000DEBD6 /* JitsiMeetUserInfo.h in Headers */,
0B412F181EDEC65D00B1A0A6 /* JitsiMeetView.h in Headers */,
0B93EF7E1EC9DDCD0030D24D /* RCTBridgeWrapper.h in Headers */,
DE81A2DE2317ED5400AE1940 /* JitsiMeetBaseLogHandler.h in Headers */,
DE65AACC2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h in Headers */,
0B412F221EDEF6EA00B1A0A6 /* JitsiMeetViewDelegate.h in Headers */,
0BD906EA1EC0C00300C8C18E /* JitsiMeet.h in Headers */,
DE81A2D42316AC4D00AE1940 /* JitsiMeetLogger.h in Headers */,
DE65AACA2317FFCD00290BEC /* LogUtils.h in Headers */,
DEAD3226220C497000E93636 /* JitsiMeetConferenceOptions.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -496,7 +521,9 @@
buildActionMask = 2147483647;
files = (
0BB9AD7B1F5EC8F4001C08DB /* CallKit.m in Sources */,
DE81A2DF2317ED5400AE1940 /* JitsiMeetBaseLogHandler.m in Sources */,
0BB9AD7D1F60356D001C08DB /* AppInfo.m in Sources */,
DE81A2D92316AC7600AE1940 /* LogBridge.m in Sources */,
DEAFA779229EAD520033A7FA /* RNRootView.m in Sources */,
DE762DB622AFDE8D000DEBD6 /* JitsiMeetUserInfo.m in Sources */,
DEAD3227220C497000E93636 /* JitsiMeetConferenceOptions.m in Sources */,
@@ -513,6 +540,7 @@
C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */,
A4A934E9212F3ADB001E9388 /* Dropbox.m in Sources */,
C69EFA0D209A0F660027712B /* JMCallKitProxy.swift in Sources */,
DE81A2D52316AC4D00AE1940 /* JitsiMeetLogger.m in Sources */,
C69EFA0E209A0F660027712B /* JMCallKitListener.swift in Sources */,
0B412F191EDEC65D00B1A0A6 /* JitsiMeetView.m in Sources */,
DEFE535421FB1BF800011A3A /* JitsiMeet.m in Sources */,

View File

@@ -20,6 +20,8 @@
#import <React/RCTLog.h>
#import <WebRTC/WebRTC.h>
#import "LogUtils.h"
// Audio mode
typedef enum {
@@ -167,7 +169,7 @@ RCT_EXPORT_METHOD(setMode:(int)mode
RCT_EXPORT_METHOD(setAudioDevice:(NSString *)device
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {
NSLog(@"[AudioMode] Selected device: %@", device);
DDLogInfo(@"[AudioMode] Selected device: %@", device);
RTCAudioSession *session = [RTCAudioSession sharedInstance];
[session lockForConfiguration];
@@ -260,7 +262,7 @@ RCT_EXPORT_METHOD(updateDeviceList) {
// This is to play well with other components which could be integrated
// into the final application.
if (self->activeMode != kAudioModeDefault) {
NSLog(@"[AudioMode] Route changed, reapplying RTCAudioSession config");
DDLogInfo(@"[AudioMode] Route changed, reapplying RTCAudioSession config");
RTCAudioSessionConfiguration *config = [self configForMode:self->activeMode];
[self setConfig:config error:nil];
if (self->forceSpeaker && !self->isSpeakerOn) {
@@ -274,7 +276,7 @@ RCT_EXPORT_METHOD(updateDeviceList) {
}
- (void)audioSession:(RTCAudioSession *)audioSession didSetActive:(BOOL)active {
NSLog(@"[AudioMode] Audio session didSetActive:%d", active);
DDLogInfo(@"[AudioMode] Audio session didSetActive:%d", active);
}
#pragma mark - Helper methods

View File

@@ -18,6 +18,8 @@
#import <JitsiMeet/JitsiMeetView.h>
#import <JitsiMeet/JitsiMeetViewDelegate.h>
#import <JitsiMeet/JitsiMeetConferenceOptions.h>
#import <JitsiMeet/JitsiMeetLogger.h>
#import <JitsiMeet/JitsiMeetBaseLogHandler.h>
@interface JitsiMeet : NSObject

View File

@@ -51,6 +51,9 @@
// Register a fatal error handler for React.
registerReactFatalErrorHandler();
// Register a log handler for React.
registerReactLogHandler();
}
return self;

View File

@@ -0,0 +1,24 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "LogUtils.h"
#import "JitsiMeetBaseLogHandler.h"
@interface JitsiMeetBaseLogHandler ()
@property (nonatomic, retain) id<DDLogger> logger;
@end

View File

@@ -0,0 +1,28 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
@interface JitsiMeetBaseLogHandler : NSObject
// These are "abstract".
- (void)logVerbose:(NSString *)msg;
- (void)logDebug:(NSString *)msg;
- (void)logInfo:(NSString *)msg;
- (void)logWarn:(NSString *)msg;
- (void)logError:(NSString *)msg;
@end

View File

@@ -0,0 +1,105 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "JitsiMeetBaseLogHandler+Private.h"
@interface PrivateLogger : DDAbstractLogger <DDLogger>
@end
@implementation PrivateLogger {
JitsiMeetBaseLogHandler *_delegate;
}
- (instancetype)initWithDelegate:(JitsiMeetBaseLogHandler *)delegate {
if (self = [super init]) {
_delegate = delegate;
}
return self;
}
#pragma mark - DDAbstractLogger interface
- (void)logMessage:(DDLogMessage *)logMessage {
NSString *logMsg = logMessage.message;
if (_logFormatter)
logMsg = [_logFormatter formatLogMessage:logMessage];
if (logMsg && _delegate) {
switch (logMessage.flag) {
case DDLogFlagError:
[_delegate logError:logMsg];
break;
case DDLogFlagWarning:
[_delegate logWarn:logMsg];
break;
case DDLogFlagInfo:
[_delegate logInfo:logMsg];
break;
case DDLogFlagDebug:
[_delegate logDebug:logMsg];
break;
case DDLogFlagVerbose:
[_delegate logVerbose:logMsg];
break;
}
}
}
@end
@implementation JitsiMeetBaseLogHandler
#pragma mark - Proxy logger not to expose the CocoaLumberjack headers
- (instancetype)init {
if (self = [super init]) {
self.logger = [[PrivateLogger alloc] initWithDelegate:self];
}
return self;
}
#pragma mark - Public API
- (void)logVerbose:(NSString *)msg {
// Override me!
[self doesNotRecognizeSelector:_cmd];
}
- (void)logDebug:(NSString *)msg {
// Override me!
[self doesNotRecognizeSelector:_cmd];
}
- (void)logInfo:(NSString *)msg {
// Override me!
[self doesNotRecognizeSelector:_cmd];
}
- (void)logWarn:(NSString *)msg {
// Override me!
[self doesNotRecognizeSelector:_cmd];
}
- (void)logError:(NSString *)msg {
// Override me!
[self doesNotRecognizeSelector:_cmd];
}
@end

View File

@@ -0,0 +1,27 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import "JitsiMeetBaseLogHandler.h"
@interface JitsiMeetLogger : NSObject
+ (void)addHandler:(JitsiMeetBaseLogHandler *)handler;
+ (void)removeHandler:(JitsiMeetBaseLogHandler *)handler;
@end

View File

@@ -0,0 +1,40 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "LogUtils.h"
#import "JitsiMeetLogger.h"
#import "JitsiMeetBaseLogHandler+Private.h"
@implementation JitsiMeetLogger
/**
* This gets called automagically when the program starts.
*/
__attribute__((constructor))
static void initializeLogger() {
[DDLog addLogger:[DDOSLogger sharedInstance]];
}
+ (void)addHandler:(JitsiMeetBaseLogHandler *)handler {
[DDLog addLogger:handler.logger];
}
+ (void)removeHandler:(JitsiMeetBaseLogHandler *)handler {
[DDLog removeLogger:handler.logger];
}
@end

57
ios/sdk/src/LogBridge.m Normal file
View File

@@ -0,0 +1,57 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <React/RCTBridgeModule.h>
#import "LogUtils.h"
@interface LogBridge : NSObject<RCTBridgeModule>
@end
@implementation LogBridge
RCT_EXPORT_MODULE();
+ (BOOL)requiresMainQueueSetup {
return NO;
}
RCT_EXPORT_METHOD(trace:(NSString *)msg) {
DDLogDebug(@"%@", msg);
}
RCT_EXPORT_METHOD(debug:(NSString *)msg) {
DDLogDebug(@"%@", msg);
}
RCT_EXPORT_METHOD(info:(NSString *)msg) {
DDLogInfo(@"%@", msg);
}
RCT_EXPORT_METHOD(log:(NSString *)msg) {
DDLogInfo(@"%@", msg);
}
RCT_EXPORT_METHOD(warn:(NSString *)msg) {
DDLogWarn(@"%@", msg);
}
RCT_EXPORT_METHOD(error:(NSString *)msg) {
DDLogError(@"%@", msg);
}
@end

23
ios/sdk/src/LogUtils.h Normal file
View File

@@ -0,0 +1,23 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef JM_LOG_UTILS_H
#define JM_LOG_UTILS_H
#import <CocoaLumberjack/CocoaLumberjack.h>
static const DDLogLevel ddLogLevel = DDLogLevelVerbose;
#endif

View File

@@ -19,5 +19,6 @@
NSMutableDictionary* mergeProps(NSDictionary *a, NSDictionary *b);
void registerReactFatalErrorHandler(void);
void registerReactLogHandler(void);
#endif /* JM_REACTUTILS_H */

View File

@@ -15,7 +15,9 @@
*/
#import <React/RCTAssert.h>
#import <React/RCTLog.h>
#import "LogUtils.h"
#import "ReactUtils.h"
#pragma mark - Utility functions
@@ -67,19 +69,11 @@ NSMutableDictionary* mergeProps(NSDictionary *a, NSDictionary *b) {
*/
RCTFatalHandler _RCTFatal = ^(NSError *error) {
id jsStackTrace = error.userInfo[RCTJSStackTraceKey];
@try {
NSString *name
= [NSString stringWithFormat:@"%@: %@",
RCTFatalExceptionName,
error.localizedDescription];
NSString *message
= RCTFormatError(error.localizedDescription, jsStackTrace, 75);
[NSException raise:name format:@"%@", message];
} @catch (NSException *e) {
if (!jsStackTrace) {
@throw;
}
}
NSString *name
= [NSString stringWithFormat:@"%@: %@", RCTFatalExceptionName, error.localizedDescription];
NSString *message
= RCTFormatError(error.localizedDescription, jsStackTrace, -1);
DDLogError(@"FATAL ERROR: %@\n%@", name, message);
};
/**
@@ -98,3 +92,62 @@ void registerReactFatalErrorHandler() {
}
#endif
}
/**
* A `RTCLogFunction` implementation which uses CocoaLumberjack.
*/
RCTLogFunction _RCTLog
= ^(RCTLogLevel level, __unused RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message)
{
// Convert RN log levels into Lumberjack's log flags.
//
DDLogFlag logFlag;
switch (level) {
case RCTLogLevelTrace:
logFlag = DDLogFlagDebug;
break;
case RCTLogLevelInfo:
logFlag = DDLogFlagInfo;
break;
case RCTLogLevelWarning:
logFlag = DDLogFlagWarning;
break;
case RCTLogLevelError:
logFlag = DDLogFlagError;
break;
case RCTLogLevelFatal:
logFlag = DDLogFlagError;
break;
default:
// Just in case more are added in the future.
logFlag = DDLogFlagInfo;
break;
}
// Build the message object we want to log.
//
DDLogMessage *logMessage
= [[DDLogMessage alloc] initWithMessage:message
level:LOG_LEVEL_DEF
flag:logFlag
context:0
file:fileName
function:nil
line:[lineNumber integerValue]
tag:nil
options:0
timestamp:nil];
// Log the message. Errors are logged synchronously, and other async, as the Lumberjack defaults.
//
[DDLog log:logFlag != DDLogFlagError
message:logMessage];
};
/**
* Helper function which registers a React Native log handler.
*/
void registerReactLogHandler() {
RCTSetLogFunction(_RCTLog);
RCTSetLogThreshold(RCTLogLevelInfo);
}

View File

@@ -15,10 +15,12 @@
*/
#import <React/RCTBridgeModule.h>
#import "Amplitude.h"
#import "LogUtils.h"
@interface AmplitudeModule : NSObject<RCTBridgeModule>
@end
@implementation AmplitudeModule
@@ -50,7 +52,7 @@ RCT_EXPORT_METHOD(logEvent:(NSString*)instanceName eventType:(NSString*)eventTyp
options:NSJSONReadingMutableContainers
error:&error];
if (eventProperties == nil) {
NSLog(@"[Amplitude handler] Error parsing event properties: %@", error);
DDLogError(@"[Amplitude] Error parsing event properties: %@", error);
} else {
[[Amplitude instanceWithName:instanceName] logEvent:eventType withEventProperties:eventProperties];
}

View File

@@ -30,6 +30,9 @@
#import <JitsiMeet/JitsiMeet-Swift.h>
#import "LogUtils.h"
// The events emitted/supported by RNCallKit:
static NSString * const RNCallKitPerformAnswerCallAction
= @"performAnswerCallAction";
@@ -69,9 +72,7 @@ RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(endCall:(NSString *)callUUID
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {
#ifdef DEBUG
NSLog(@"[RNCallKit][endCall] callUUID = %@", callUUID);
#endif
DDLogInfo(@"[RNCallKit][endCall] callUUID = %@", callUUID);
NSUUID *callUUID_ = [[NSUUID alloc] initWithUUIDString:callUUID];
@@ -92,9 +93,7 @@ RCT_EXPORT_METHOD(setMuted:(NSString *)callUUID
muted:(BOOL)muted
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {
#ifdef DEBUG
NSLog(@"[RNCallKit][setMuted] callUUID = %@", callUUID);
#endif
DDLogInfo(@"[RNCallKit][setMuted] callUUID = %@", callUUID);
NSUUID *callUUID_ = [[NSUUID alloc] initWithUUIDString:callUUID];
@@ -111,11 +110,7 @@ RCT_EXPORT_METHOD(setMuted:(NSString *)callUUID
}
RCT_EXPORT_METHOD(setProviderConfiguration:(NSDictionary *)dictionary) {
#ifdef DEBUG
NSLog(
@"[RNCallKit][setProviderConfiguration:] dictionary = %@",
dictionary);
#endif
DDLogInfo(@"[RNCallKit][setProviderConfiguration:] dictionary = %@", dictionary);
if (![JMCallKitProxy isProviderConfigured]) {
[self configureProviderFromDictionary:dictionary];
@@ -131,9 +126,7 @@ RCT_EXPORT_METHOD(startCall:(NSString *)callUUID
video:(BOOL)video
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {
#ifdef DEBUG
NSLog(@"[RNCallKit][startCall] callUUID = %@", callUUID);
#endif
DDLogInfo(@"[RNCallKit][startCall] callUUID = %@", callUUID);
NSUUID *callUUID_ = [[NSUUID alloc] initWithUUIDString:callUUID];
@@ -197,12 +190,7 @@ RCT_EXPORT_METHOD(updateCall:(NSString *)callUUID
options:(NSDictionary *)options
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {
#ifdef DEBUG
NSLog(
@"[RNCallKit][updateCall] callUUID = %@ options = %@",
callUUID,
options);
#endif
DDLogInfo(@"[RNCallKit][updateCall] callUUID = %@ options = %@", callUUID, options);
NSUUID *callUUID_ = [[NSUUID alloc] initWithUUIDString:callUUID];
@@ -225,9 +213,7 @@ RCT_EXPORT_METHOD(updateCall:(NSString *)callUUID
#pragma mark - Helper methods
- (void)configureProviderFromDictionary:(NSDictionary* )dictionary {
#ifdef DEBUG
NSLog(@"[RNCallKit][providerConfigurationFromDictionary:]");
#endif
DDLogInfo(@"[RNCallKit][providerConfigurationFromDictionary: %@]", dictionary);
if (!dictionary) {
dictionary = @{};
@@ -271,17 +257,12 @@ RCT_EXPORT_METHOD(updateCall:(NSString *)callUUID
- (void)requestTransaction:(CXTransaction *)transaction
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject {
#ifdef DEBUG
NSLog(@"[RNCallKit][requestTransaction] transaction = %@", transaction);
#endif
DDLogInfo(@"[RNCallKit][requestTransaction] transaction = %@", transaction);
[JMCallKitProxy request:transaction
completion:^(NSError * _Nullable error) {
if (error) {
NSLog(
@"[RNCallKit][requestTransaction] Error requesting transaction (%@): (%@)",
transaction.actions,
error);
DDLogError(@"[RNCallKit][requestTransaction] Error requesting transaction (%@): (%@)", transaction.actions, error);
reject(nil, @"Error processing CallKit transaction", error);
} else {
resolve(nil);
@@ -293,18 +274,14 @@ RCT_EXPORT_METHOD(updateCall:(NSString *)callUUID
// Called when the provider has been reset. We should terminate all calls.
- (void)providerDidReset {
#ifdef DEBUG
NSLog(@"[RNCallKit][CXProviderDelegate][providerDidReset:]");
#endif
DDLogInfo(@"[RNCallKit][CXProviderDelegate][providerDidReset:]");
[self sendEventWithName:RNCallKitProviderDidReset body:nil];
}
// Answering incoming call
- (void) performAnswerCallWithUUID:(NSUUID *)UUID {
#ifdef DEBUG
NSLog(@"[RNCallKit][CXProviderDelegate][provider:performAnswerCallAction:]");
#endif
DDLogInfo(@"[RNCallKit][CXProviderDelegate][provider:performAnswerCallAction:]");
[self sendEventWithName:RNCallKitPerformAnswerCallAction
body:@{ @"callUUID": UUID.UUIDString }];
@@ -312,9 +289,7 @@ RCT_EXPORT_METHOD(updateCall:(NSString *)callUUID
// Call ended, user request
- (void) performEndCallWithUUID:(NSUUID *)UUID {
#ifdef DEBUG
NSLog(@"[RNCallKit][CXProviderDelegate][provider:performEndCallAction:]");
#endif
DDLogInfo(@"[RNCallKit][CXProviderDelegate][provider:performEndCallAction:]");
[self sendEventWithName:RNCallKitPerformEndCallAction
body:@{ @"callUUID": UUID.UUIDString }];
@@ -323,9 +298,7 @@ RCT_EXPORT_METHOD(updateCall:(NSString *)callUUID
// Handle audio mute from CallKit view
- (void) performSetMutedCallWithUUID:(NSUUID *)UUID
isMuted:(BOOL)isMuted {
#ifdef DEBUG
NSLog(@"[RNCallKit][CXProviderDelegate][provider:performSetMutedCallAction:]");
#endif
DDLogInfo(@"[RNCallKit][CXProviderDelegate][provider:performSetMutedCallAction:]");
[self sendEventWithName:RNCallKitPerformSetMutedCallAction
body:@{
@@ -337,31 +310,26 @@ RCT_EXPORT_METHOD(updateCall:(NSString *)callUUID
// Starting outgoing call
- (void) performStartCallWithUUID:(NSUUID *)UUID
isVideo:(BOOL)isVideo {
#ifdef DEBUG
NSLog(@"[RNCallKit][CXProviderDelegate][provider:performStartCallAction:]");
#endif
DDLogInfo(@"[RNCallKit][CXProviderDelegate][provider:performStartCallAction:]");
[JMCallKitProxy reportOutgoingCallWith:UUID
startedConnectingAt:nil];
}
- (void) providerDidActivateAudioSessionWithSession:(AVAudioSession *)session {
#ifdef DEBUG
NSLog(@"[RNCallKit][CXProviderDelegate][provider:didActivateAudioSession:]");
#endif
DDLogInfo(@"[RNCallKit][CXProviderDelegate][provider:didActivateAudioSession:]");
[[RTCAudioSession sharedInstance] audioSessionDidActivate:session];
}
- (void) providerDidDeactivateAudioSessionWithSession:(AVAudioSession *)session {
#ifdef DEBUG
NSLog(@"[RNCallKit][CXProviderDelegate][provider:didDeactivateAudioSession:]");
#endif
DDLogInfo(@"[RNCallKit][CXProviderDelegate][provider:didDeactivateAudioSession:]");
[[RTCAudioSession sharedInstance] audioSessionDidDeactivate:session];
}
- (void) providerTimedOutPerformingActionWithAction:(CXAction *)action {
#ifdef DEBUG
NSLog(@"[RNCallKit][CXProviderDelegate][provider:timedOutPerformingAction:]");
#endif
DDLogWarn(@"[RNCallKit][CXProviderDelegate][provider:timedOutPerformingAction:]");
}

View File

@@ -1,24 +1,24 @@
{
"en": "Anglais",
"af": "",
"af": "Afrikaans",
"bg": "Bulgare",
"ca": "",
"ca": "Catalan",
"cs": "Tchèque",
"de": "Allemand",
"el": "Grec",
"enGB": "",
"enGB": "Anglais (Royaume-Uni) ",
"eo": "Espéranto",
"es": "Espagnol",
"esUS": "",
"fi": "",
"esUS": "Espagnol (Amérique latine)",
"fi": "Finlandais",
"fr": "Français",
"frCA": "",
"hr": "",
"frCA": "Français (Canadien)",
"hr": "Croate",
"hy": "Arménien",
"it": "Italien",
"ja": "Japonais",
"ko": "Coréen",
"nl": "",
"nl": "Néerlandais",
"oc": "Occitan",
"pl": "Polonais",
"ptBR": "Portugais (Brésil)",
@@ -27,5 +27,5 @@
"tr": "Turc",
"vi": "Vietnamien",
"zhCN": "Chinois (Chine)",
"zhTW": ""
"zhTW": "Chinois (Taiwan)"
}

View File

@@ -1,27 +1,31 @@
{
"en": "Anglés",
"af": "Afrikaans",
"az": "Azèri",
"bg": "Bulgar",
"ca": "",
"cs": "Chèc",
"de": "Aleman",
"el": "Grèc",
"enGB": "",
"eo": "Esperanto",
"es": "Castelhan",
"esUS": "",
"fi": "",
"fr": "Francés",
"frCA": "",
"hr": "",
"hy": "Armenian",
"it": "Italian",
"ja": "Japonés",
"ko": "Corean",
"nb": "Norvegian Bokmål",
"nl": "",
"oc": "Occitan",
"pl": "Polonés",
"ptBR": "Portugués (Brasil)",
"ru": "Rus",
"sk": "Eslovac",
"sl": "Eslovèn",
"sv": "Suedés",
"tr": "Turc",
"vi": "Vietnamian",
"zhCN": "Chinés (China)"
"zhCN": "Chinés (China)",
"zhTW": ""
}

View File

@@ -1,27 +1,31 @@
{
"en": "Английский",
"af": "",
"az": "Азербайджанский",
"bg": "Болгарский",
"ca": "",
"cs": "Чешский",
"de": "Немецкий",
"el": "Греческий",
"enGB": "",
"eo": "Эсперанто",
"es": "Испанский",
"esUS": "",
"fi": "",
"fr": "Французский",
"frCA": "",
"hr": "",
"hy": "Армянский",
"it": "Итальянский",
"ja": "Японский",
"ko": "Корейский",
"nb": "Норвежский букмол",
"nl": "",
"oc": "Окситанский",
"pl": "Польский",
"ptBR": "Португальский (Бразилия)",
"ru": "Русский",
"sk": "Словацкий",
"sl": "Словенский",
"sv": "Шведский",
"tr": "Турецкий",
"vi": "Вьетнамский",
"zhCN": "Китайский (Китай)"
"zhCN": "Китайский (Китай)",
"zhTW": ""
}

View File

@@ -4,7 +4,7 @@
"countryNotSupported": "Nous ne supportons pas encore cette destination.",
"countryReminder": "Appel hors États-Unis? Veuillez commencer avec le code du pays!",
"disabled": "Vous ne pouvez pas inviter quelqu'un.",
"failedToAdd": "",
"failedToAdd": "Erreur lors de l'ajout des participants",
"footerText": "Appels sortants désactivés",
"loading": "Rechercher des personnes et des numéros de téléphone",
"loadingNumber": "Validation du numéro de téléphone",
@@ -22,7 +22,7 @@
"headphones": "Écouteurs",
"phone": "Téléphone",
"speaker": "Haut-parleur",
"none": ""
"none": "Aucune source audio n'est disponible"
},
"audioOnly": {
"audioOnly": "Bande passante faible"
@@ -31,9 +31,9 @@
"addMeetingURL": "Ajouter un lien de conférence",
"confirmAddLink": "Voulez-vous ajouter un lien Jitsi à cet événement?",
"error": {
"appConfiguration": "L'intégration au calendrier n'est pas correctement configurée.",
"appConfiguration": "l'intégration du calendrier n'est pas correctement configurée",
"generic": "Une erreur s'est produite. Veuillez vérifier les paramètres de votre calendrier ou tenter de l'actualiser.",
"notSignedIn": "Une erreur s'est produite lors de l'authentification permettant d'afficher les évènements du calendrier. Veuillez vérifier les paramètres de votre calendrier et essayer de vous reconnecter."
"notSignedIn": "Une erreur s'est produite lors de l'authentification permettant d'afficher les événements du calendrier. Veuillez vérifier les paramètres de votre calendrier et essayer de vous reconnecter."
},
"join": "Joindre",
"joinTooltip": "Rejoindre la réunion",
@@ -47,15 +47,15 @@
},
"chat": {
"error": "Erreur : votre message \"{{originalText}}\" n'a pas été envoyé. Raison : {{error}}",
"messagebox": "Saisir un message",
"messagebox": "Saisissez un message",
"nickname": {
"popover": "Choisissez un pseudonyme",
"title": "Entrer un pseudonyme pour utiliser le chat"
"title": "Entrez un pseudonyme pour utiliser le chat"
},
"title": "Chat"
},
"connectingOverlay": {
"joiningRoom": "Connexion à votre réunion en cours…"
"joiningRoom": "Connexion à la réunion..."
},
"connection": {
"ATTACHED": "Attachée",
@@ -97,8 +97,7 @@
"resolution": "Résolution :",
"status": "Connexion:",
"transport": "Transport :",
"transport_plural": "Transports :",
"turn": "(tour)"
"transport_plural": "Transports :"
},
"dateUtils": {
"earlier": "Plus tôt",
@@ -108,7 +107,7 @@
"deepLinking": {
"appNotInstalled": "Vous avez besoin de l'application mobile {{app}} pour participer à cette réunion avec votre téléphone.",
"description": "Rien ne s'est passé? Nous avons essayé de lancer votre réunion dans l'application de bureau {{app}}. Essayez à nouveau ou lancez-la dans l'application web {{app}}.",
"descriptionWithoutWeb": "",
"descriptionWithoutWeb": "Rien ne s'est passé? Nous avons essayé de démarrer votre réunion dans l'application bureau {{app}}.",
"downloadApp": "Télécharger l'application",
"launchWebButton": "Lancer dans le navigateur",
"openApp": "Continuer vers l'application",
@@ -134,7 +133,7 @@
"liveStreaming": "Diffusion en direct"
},
"allow": "Autoriser",
"alreadySharedVideoMsg": "",
"alreadySharedVideoMsg": "Un autre participant est en train de partager sa vidéo. Cette conférence ne permet de partager qu'une seule vidéo à la fois.",
"alreadySharedVideoTitle": "Une seule vidéo partagée est autorisée à la fois",
"applicationWindow": "Fenêtre d'application",
"Back": "Retour",
@@ -160,51 +159,51 @@
"contactSupport": "Contacter le support",
"copy": "Copier",
"dismiss": "Rejeter",
"displayNameRequired": "",
"displayNameRequired": "Salut! Quel est votre nom?",
"done": "Terminé",
"enterDisplayName": "",
"enterDisplayName": "Merci de saisir votre nom ici",
"error": "Erreur",
"externalInstallationMsg": "Vous devez installer notre extension de partage de bureau.",
"externalInstallationTitle": "Extension requise : ",
"goToStore": "Aller sur le webstore",
"gracefulShutdown": "Le service est actuellement en maintenance. Réessayez plus tard.",
"IamHost": "Je suis lhôte",
"incorrectRoomLockPassword": "",
"incorrectRoomLockPassword": "Mot de passe incorrect",
"incorrectPassword": "Nom d'utilisateur ou mot de passe incorrect",
"inlineInstallationMsg": "Vous devez installer notre extension de partage de bureau.",
"inlineInstallExtension": "Installer maintenant",
"internalError": "Oups! Quelque chose s'est mal passée. L'erreur suivante s'est produite: {{error}}",
"internalErrorTitle": "Erreur interne",
"kickMessage": "",
"kickMessage": "Vous pouvez contacter {{participantDisplayName}} pour plus de détails.",
"kickParticipantButton": "Expulser",
"kickParticipantDialog": "Êtes-vous sûr(e) de vouloir expulser ce participant ?",
"kickParticipantTitle": "Couper le micro de ce participant?",
"kickTitle": "",
"kickParticipantTitle": "Expulser ce participant?",
"kickTitle": "Oups! vous avez été expulsé(e) par {{participantDisplayName}}",
"liveStreaming": "Direct",
"liveStreamingDisabledForGuestTooltip": "Les invités ne peuvent démarrer la diffusion en direct.",
"liveStreamingDisabledTooltip": "La diffusion en direct est désactivé",
"lockMessage": "Impossible de verrouiller la conférence.",
"lockRoom": "",
"lockRoom": "Ajouter la réunion $t(lockRoomPasswordUppercase)",
"lockTitle": "Échec du verrouillage",
"logoutQuestion": "Voulez-vous vraiment vous déconnecter et arrêter la conférence ?",
"logoutTitle": "Déconnexion",
"maxUsersLimitReached": "",
"maxUsersLimitReachedTitle": "",
"maxUsersLimitReached": "Le nombre maximal de participant est atteint. Le conférence est complète. Merci de contacter l'organisateur de la réunion ou réessayer plus tard!",
"maxUsersLimitReachedTitle": "Le nombre maximal de participants est atteint",
"micConstraintFailedError": "Votre microphone ne satisfait pas certaines des contraintes nécessaires.",
"micNotFoundError": "Le microphone n'a pas été détecté.",
"micNotSendingData": "",
"micNotSendingDataTitle": "",
"micNotSendingData": "Accédez aux paramètres de votre ordinateur pour réactiver le micro et ajuster son niveau",
"micNotSendingDataTitle": "Votre micro est désactivé par les paramètres de votre système",
"micPermissionDeniedError": "Vous n'avez pas autorisé l'utilisation de votre microphone. Vous pouvez toujours participer à la conférence, mais les autres ne vont pas vous entendre. Utilisez le bouton du microphone dans la barre d'adresse pour résoudre ce problème.",
"micUnknownError": "Vous ne pouvez pas utiliser le microphone pour une raison inconnue.",
"muteParticipantBody": "Vous ne pourrez plus réactiver leurs micros, mais ils peuvent l'activer par eux-même à tout moment.",
"muteParticipantButton": "Couper le micro",
"muteParticipantDialog": "Êtes-vous sûr(e) de vouloir désactiver le micro de ce participant ? Seul le participant lui-même pourra ensuite réactiver son micro à tout moment.",
"muteParticipantDialog": "Êtes-vous sûr(e) de vouloir couper le micro de ce participant ? Seul le participant pourra ensuite réactiver son micro à tout moment.",
"muteParticipantTitle": "Couper le micro de ce participant?",
"Ok": "Ok",
"passwordLabel": "",
"passwordNotSupported": "La définition d'un mot de passe de conférence n'est pas prise en charge.",
"passwordNotSupportedTitle": "",
"passwordRequired": "",
"passwordLabel": "$t(lockRoomPasswordUppercase)",
"passwordNotSupported": "La définition d'un $t(lockRoomPassword) de réunion n'est pas prise en charge.",
"passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) n'est pas supporté",
"passwordRequired": "$t(lockRoomPasswordUppercase) requis",
"popupError": "Votre navigateur bloque les fenêtres pop-up. Veuillez autoriser les fenêtres pop-up dans les paramètres de votre navigateur.",
"popupErrorTitle": "Pop-up bloquée",
"recording": "Enregistrement",
@@ -219,7 +218,7 @@
"remoteControlStopMessage": "La prise en main à distance est terminée!",
"remoteControlTitle": "Contrôle de bureau à distance",
"Remove": "Supprimer",
"removePassword": "",
"removePassword": "Supprimer $t(lockRoomPassword)",
"removeSharedVideoMsg": "Voulez-vous vraiment supprimer votre vidéo partagée ?",
"removeSharedVideoTitle": "Supprimer la vidéo partagée",
"reservationError": "Erreur du système de réservation",
@@ -237,7 +236,7 @@
"shareVideoTitle": "Partager une vidéo",
"shareYourScreen": "Partagez votre écran",
"shareYourScreenDisabled": "Le partage décran est désactivé.",
"shareYourScreenDisabledForGuest": "Les invités ne peuvent partager l'écran",
"shareYourScreenDisabledForGuest": "Les invités ne peuvent partager l'écran.",
"startLiveStreaming": "Démarrer la diffusion en direct",
"startRecording": "Commencer l'enregistrement",
"startRemoteControlErrorMessage": "Une erreur est survenue lors de la tentative de démarrage de la session de contrôle à distance!",
@@ -252,7 +251,7 @@
"tokenAuthFailed": "Désolé, vous n'êtes pas autorisé à rejoindre cette conversation.",
"tokenAuthFailedTitle": "Échec de l'authentification",
"transcribing": "Transcription",
"unlockRoom": "",
"unlockRoom": "Supprimer $t(lockRoomPassword) de la réunion",
"userPassword": "mot de passe utilisateur",
"WaitForHostMsg": "La conférence <b>{{room}}</b> n'a pas encore commencé. Si vous en êtes l'hôte, veuillez vous authentifier. Sinon, veuillez attendre son arrivée.",
"WaitForHostMsgWOk": "La conférence <b>{{room}}</b> n'a pas encore commencé. Si vous en êtes l'hôte, veuillez appuyer sur Ok pour vous authentifier. Sinon, veuillez attendre son arrivée.",
@@ -281,11 +280,11 @@
},
"info": {
"accessibilityLabel": "Afficher les informations",
"addPassword": "",
"cancelPassword": "",
"addPassword": "Ajouter $t(lockRoomPassword)",
"cancelPassword": "Annuler $t(lockRoomPassword)",
"conferenceURL": "Lien:",
"country": "Pays",
"dialANumber": "Pour rejoindre la réunion, composez l'un de ces numéros, puis saisissez le code confidentiel.",
"dialANumber": "Pour rejoindre votre réunion, composez l'un de ces numéros, puis saisissez le code confidentiel.",
"dialInConferenceID": "PIN:",
"dialInNotSupported": "Désolé, l'accès par téléphone n'est pas pris en charge pour l'instant.",
"dialInNumber": "Composer:",
@@ -293,21 +292,21 @@
"dialInTollFree": "Numéro gratuit",
"genericError": "Oups, quelque chose a mal tourné.",
"inviteLiveStream": "Pour voir la diffusion en direct de cette réunion, cliquez sur ce lien : {{url}}",
"invitePhone": "",
"invitePhoneAlternatives": "",
"invitePhone": "Pour rejoindre depuis un téléphone, saisissez : {{number}},,{{conferenceID}}#\n",
"invitePhoneAlternatives": "Vous cherchez un numéro d'appel différent?\nAfficher les numéros d'appel de la réunion: {{url}}\n\n\nSi vous appelez également via un téléphone de salle, vous pouvez vous connecter sans audio: {{silentUrl}}",
"inviteURLFirstPartGeneral": "Vous êtes invité(e) à participer à une réunion.",
"inviteURLFirstPartPersonal": "",
"inviteURLSecondPart": "",
"inviteURLFirstPartPersonal": "{{name}} vous invite à une réunion.\n",
"inviteURLSecondPart": "\nRejoindre la réunion:\n{{url}}\n",
"liveStreamURL": "Diffusion en direct :",
"moreNumbers": "Plus de numéros ",
"noNumbers": "Numéros à composer non trouvés",
"noPassword": "Aucun",
"noRoom": "Aucune réunion n'a été spécifiée pour l'appel entrant.",
"numbers": "Numéros d'appel",
"password": "",
"password": "$t(lockRoomPasswordUppercase):",
"title": "Partager",
"tooltip": "Partager le lien et les informations de connexion pour cette conférence",
"label": "Infos de la réunion"
"label": "Information de la réunion"
},
"inviteDialog": {
"alertText": "Échec lors de l'invitation de certains participants.",
@@ -354,7 +353,7 @@
"expandedOn": "La conférence est en cours de diffusion sur YouTube.",
"expandedPending": "La diffusion en direct a commencé...",
"failedToStart": "Le Streaming n'as pas réussi à démarrer",
"getStreamKeyManually": "",
"getStreamKeyManually": "Nous n'avons pu récupérer aucun flux en direct. Essayez dobtenir votre clé de diffusion en direct sur YouTube.",
"invalidStreamKey": "La clé de diffusion en direct n'est peut-être pas correcte.",
"off": "Le Streaming a été arrêté",
"on": "Direct",
@@ -409,30 +408,30 @@
"focusFail": "{{component}} n'est pas disponible - réessayez dans {{ms}} sec",
"grantedTo": "Droits modérateur accordés à {{to}} !",
"invitedOneMember": "{{displayName}} a été invité(e)",
"invitedThreePlusMembers": "",
"invitedTwoMembers": "",
"kickParticipant": "",
"invitedThreePlusMembers": "{{name}} et {{count}} autres ont été invités",
"invitedTwoMembers": "{{first}} et {{second}} ont été invités",
"kickParticipant": "{{kicked}} a été expulsé par {{kicker}}",
"me": "Moi",
"moderator": "Droits modérateur accordés !",
"muted": "Vous avez commencé la conversation en muet.",
"mutedTitle": "Vous êtes en muet !",
"mutedRemotelyTitle": "",
"mutedRemotelyDescription": "",
"passwordRemovedRemotely": "",
"passwordSetRemotely": "",
"mutedRemotelyTitle": "Votre micro a été coupé par {{participantDisplayName}}!",
"mutedRemotelyDescription": "Vous pouvez toujours activer votre micro pour prendre la parole. Désactivez votre micro quand vous terminez pour éviter les bruits parasites.",
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) a été supprimé par un autre participant",
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) défini par un autre participant",
"raisedHand": "{{name}} aimerait prendre la parole.",
"somebody": "Quelqu'un",
"startSilentTitle": "",
"startSilentDescription": "",
"suboptimalBrowserWarning": "",
"startSilentTitle": "Vous avez rejoint sans sortie audio!",
"startSilentDescription": "Rejoignez la réunion de nouveau pour activer l'audio",
"suboptimalBrowserWarning": "Nous craignons que votre expérience de réunion en ligne ne soit bonne ici. Nous cherchons des moyens daméliorer cela, mais dici-là, essayez dutiliser lun des <a href='static/recommendedBrowsers.html' target='_blank'>navigateurs supportés</a>.",
"suboptimalExperienceTitle": "Avertissement du navigateur",
"unmute": "",
"unmute": "Rétablir le son",
"newDeviceCameraTitle": "Nouvelle caméra détectée",
"newDeviceAudioTitle": "Nouveau périphérique audio détecté",
"newDeviceAction": "Utiliser"
},
"passwordSetRemotely": "défini par un autre participant",
"passwordDigitsOnly": "",
"passwordDigitsOnly": "Jusqu'à {{number}} chiffres",
"poweredby": "Produit par",
"presenceStatus": {
"busy": "Occupé",
@@ -522,7 +521,7 @@
"version": "Version"
},
"share": {
"dialInfoText": "",
"dialInfoText": "\n\n=====\n\nVoulez-vous appeler depuis votre téléphone?\n\n{{defaultDialInNumber}}Cliquez sur ce lien pour afficher les numéros d'appels pour cette réunion\n{{dialInfoPageUrl}}",
"mainText": "Cliquez sur le lien suivant pour rejoindre une conférence :\n{{roomUrl}}"
},
"speaker": "Haut-parleur",
@@ -546,8 +545,8 @@
"toolbar": {
"accessibilityLabel": {
"audioOnly": "Activer/désactiver le mode voix uniquement",
"audioRoute": "Sélectionner le périphérique audio",
"callQuality": "Accorder la qualité des appels",
"audioRoute": "Sélectionner la source audio",
"callQuality": "Ajuster la qualité vidéo",
"cc": "Activer/désactiver les sous-titres",
"chat": "Afficher/masquer la discussion instantanée",
"document": "Activer/désactiver le document partagé",
@@ -571,19 +570,19 @@
"shareRoom": "Inviter quelqu'un",
"shareYourScreen": "Activer/désactiver le partage décran",
"shortcuts": "Afficher/masquer les raccourcis",
"show": "",
"show": "Afficher en premier plan",
"speakerStats": "Afficher/cacher les statistiques de parole",
"tileView": "Activer/désactiver la vue mosaïque",
"toggleCamera": "Activer/désactiver la caméra",
"videomute": "Activer/désactiver la vidéo",
"videoblur": ""
"videoblur": "Activer/désactiver le flou de la vidéo"
},
"addPeople": "Ajouter des personnes à votre appel",
"audioOnlyOff": "",
"audioOnlyOn": "",
"audioRoute": "Sélectionner le périphérique audio",
"audioOnlyOff": "Désactiver le mode bande passante réduite",
"audioOnlyOn": "Activer le mode bande passante réduite",
"audioRoute": "Sélectionner la source audio",
"authenticate": "Authentifiez-vous",
"callQuality": "Accorder la qualité des appels",
"callQuality": "Ajuster la qualité vidéo",
"chat": "Ouvrir / Fermer le chat",
"closeChat": "Fermer le chat",
"documentClose": "Fermer le document partagé",
@@ -619,8 +618,8 @@
"tileViewToggle": "Activer/désactiver la vue mosaïque",
"toggleCamera": "Activer/désactiver la caméra",
"videomute": "Démarrer / Arrêter la caméra",
"startvideoblur": "",
"stopvideoblur": ""
"startvideoblur": "Flouter mon arrière plan",
"stopvideoblur": "Désactiver le flou d'arrière-plan"
},
"transcribing": {
"ccButtonTooltip": "Activer/Désactiver les sous-titres",
@@ -658,20 +657,20 @@
},
"videoStatus": {
"audioOnly": "VOIX",
"audioOnlyExpanded": "",
"callQuality": "",
"audioOnlyExpanded": "Vous êtes en mode bande passante réduite. Dans ce mode, vous ne recevrez que le partage audio et le partage décran.",
"callQuality": "Qualité vidéo",
"hd": "HD",
"hdTooltip": "Regardez la vidéo en haute définition",
"highDefinition": "Haute définition",
"labelTooiltipNoVideo": "Aucune vidéo",
"labelTooltipAudioOnly": "",
"labelTooltipAudioOnly": "Mode bande passante réduite activé",
"ld": "BD",
"ldTooltip": "Regardez la vidéo en basse définition",
"lowDefinition": "Basse définition",
"onlyAudioAvailable": "Seul l'audio est disponible",
"onlyAudioSupported": "Nous ne supportons que l'audio sur ce navigateur.",
"p2pEnabled": "Peer to Peer activé",
"p2pVideoQualityDescription": "",
"p2pVideoQualityDescription": "En mode peer to peer, la qualité vidéo reçue ne peut être basculée qu'entre haute et audio uniquement. Les autres paramètres ne seront pas pris en compte jusqu'à ce que vous quittiez le mode peer to peer.",
"recHighDefinitionOnly": "Va préférer la haute définition",
"sd": "MD",
"sdTooltip": "Regardez la vidéo en définition standard",
@@ -685,8 +684,8 @@
"mute": "Un participant a coupé son micro",
"muted": "Muet",
"remoteControl": "Contrôle à distance",
"show": "",
"videomute": ""
"show": "Afficher en premier plan",
"videomute": "Le participant a arrêté la caméra"
},
"welcomepage": {
"accessibilityLabel": {
@@ -709,7 +708,7 @@
"recentList": "Récent",
"recentListDelete": "Supprimer",
"recentListEmpty": "Votre liste récente est actuellement vide. Discuter avec votre équipe et vous trouverez toutes vos réunions récentes ici.",
"reducedUIText": "",
"reducedUIText": "Bienvenue sur {{app}}!",
"roomname": "Saisissez un nom de salle",
"roomnameHint": "Entrez le nom ou l'URL de la salle que vous souhaitez rejoindre. Vous pouvez faire un nom, laissez les gens que vous rencontrerez le savoir afin qu'ils entrent le même nom.",
"sendFeedback": "Envoyer votre avis",

View File

@@ -21,18 +21,19 @@
"bluetooth": "Bluetooth",
"headphones": "Escotadors",
"phone": "Telefòn",
"speaker": "Nautparlaire"
"speaker": "Nautparlaire",
"none": ""
},
"audioOnly": {
"audioOnly": "Àudio solament"
"audioOnly": "Benda passanta febla"
},
"calendarSync": {
"addMeetingURL": "Ajustar un ligam de reünion",
"confirmAddLink": "Volètz ajustar un ligam Jitsi cap a aqueste eveniment ?",
"error": {
"appConfiguration": "",
"generic": "",
"notSignedIn": ""
"appConfiguration": "Lintegracion del calendièr es pas corrèctament configurada.",
"generic": "Una error ses producha. Verificatz vòstres paramètres de calendièr o ensajatz de lactualizar.",
"notSignedIn": "Una error ses producha pendent lautentificacion per veire los eveniments del calendièr. Verificatz los paramètres del calendièr e connectatz-vos tornamai."
},
"join": "Jónher",
"joinTooltip": "Rejónher la conferéncia",
@@ -54,7 +55,7 @@
"title": "Messatjariá"
},
"connectingOverlay": {
"joiningRoom": ""
"joiningRoom": "Connexion a vòstra reünion…"
},
"connection": {
"ATTACHED": "Estacada",
@@ -95,8 +96,7 @@
"remoteport_plural": "Pòrts distants :",
"resolution": "Resolucion :",
"status": "Connexion :",
"transport": "Transpòrt :",
"turn": " (virar)"
"transport": "Transpòrt :"
},
"dateUtils": {
"earlier": "Mai dora",
@@ -106,7 +106,7 @@
"deepLinking": {
"appNotInstalled": "Vos cal laplicacion {{app}} per jónher la conferéncia amb vòstre mobil.",
"description": "Res ses pas passat? Avèm ensajat de lançar la conferéncia dins laplicacion {{app}}. Mercés de tornar ensajar o de la lançar dins laplicacion web {{app}}.",
"descriptionWithoutWeb": "",
"descriptionWithoutWeb": "Res se passa pas ? Avèm ensajat de lançar la conferéncia dins laplicacion de burèu {{app}}.",
"downloadApp": "Telecargar laplicacion",
"launchWebButton": "Lançar del navigador",
"openApp": "Telecargar laplicacion",
@@ -114,6 +114,7 @@
"tryAgainButton": "Tornar ensajar del burèu"
},
"defaultLink": "ex. {{url}}",
"defaultNickname": "ex. Joan Delpuèch",
"deviceError": {
"cameraError": "Fracàs de laccès a vòstra camèra",
"cameraPermission": "Error d'obtencion de la permission per la camèra",
@@ -131,7 +132,7 @@
"liveStreaming": "Difusion en dirècte"
},
"allow": "Autorizar",
"alreadySharedVideoMsg": "",
"alreadySharedVideoMsg": "Un autre participant parteja ja sa vidèo. Aquesta conferéncia permet pas quun partatge de vidèo a lencòp.",
"alreadySharedVideoTitle": "Solament un partatge de vidèo a l'encòp es autorizat",
"applicationWindow": "Fenèstra de l'aplicacion",
"Back": "Retorn",
@@ -157,26 +158,26 @@
"contactSupport": "Contactar l'assisténcia",
"copy": "Copiar",
"dismiss": "Regetar",
"displayNameRequired": "",
"displayNameRequired": "Adiu! Cossí vos dison?",
"done": "Tampar",
"enterDisplayName": "",
"enterDisplayName": "Volgatz picar vòstre nom aquí",
"error": "Error",
"externalInstallationMsg": "Avètz d'installar nòstra extension de partiment d'ecran.",
"externalInstallationTitle": "Extension requesida :",
"goToStore": "Anar al webstore",
"gracefulShutdown": "Lo servici es actualament en mantenença. Ensajatz tornamai pus tard.",
"IamHost": "Soi lòste",
"incorrectRoomLockPassword": "",
"incorrectRoomLockPassword": "Senhal incorrècte",
"incorrectPassword": "Nom de compte o senhal incorrècte",
"inlineInstallationMsg": "Avètz d'installar nòstra extension de partiment d'ecran.",
"inlineInstallExtension": "Installar ara",
"internalError": "Òu ! Quicòm a pas foncionat. L'error seguenta s'es producha : {{error}}",
"internalErrorTitle": "Error intèrna",
"kickMessage": "",
"kickParticipantButton": "",
"kickParticipantDialog": "",
"kickParticipantTitle": "",
"kickTitle": "",
"kickMessage": "Podètz contactat {{participantDisplayName}} per mai de detalhs.",
"kickParticipantButton": "Forabandir",
"kickParticipantDialog": "Volètz vertadièrament forabandir aqueste participant?",
"kickParticipantTitle": "Forabandir aqueste participant?",
"kickTitle": "Ai! {{participantDisplayName}} vos a forabandit de la conferéncia",
"liveStreaming": "La difusion en dirècte es estada arrestada",
"liveStreamingDisabledForGuestTooltip": "Los convidats pòdon pas aviar una difusion en dirècte",
"liveStreamingDisabledTooltip": "Difusion en dirècte desactivada.",
@@ -185,12 +186,12 @@
"lockTitle": "Fracàs del verrolhatge",
"logoutQuestion": "Sètz segur que vos volètz desconnectar e arrestar la conferéncia ?",
"logoutTitle": "Desconnexion",
"maxUsersLimitReached": "",
"maxUsersLimitReachedTitle": "",
"maxUsersLimitReached": "La limita de nombre maximum de participant es estada atenguda. La conferéncia es complèta. Contactatz lo proprietari de la conferéncia o tornatz ensajar mai tard.",
"maxUsersLimitReachedTitle": "Limita de participants maximum atenguda ",
"micConstraintFailedError": "Vòstre microfòn satisfà pas totas las constrentas necessàrias.",
"micNotFoundError": "Lo microfòn es pas estat trobat.",
"micNotSendingData": "",
"micNotSendingDataTitle": "",
"micNotSendingData": "Anatz als paramètres de lordenador per tornar metre lo son del microfòn e ajustar son nivèl.",
"micNotSendingDataTitle": "Lo microfòn es copat pels paramètres del sistèma",
"micPermissionDeniedError": "Avètz pas donat l'autorizacion d'utilizar vòstre microfòn. Podètz encara participar a la conferéncia mai los demai vos ausiràn pas. Utilizatz lo boton del microfòn dins la barra d'adreça per resòlvre aquò.",
"micUnknownError": "Impossible d'utilizar lo microfòn per una rason desconeguda.",
"muteParticipantBody": "Poiretz pas lo tornar activar lo microfòn, mai eles pòdon o far quand vòlon.",
@@ -251,8 +252,8 @@
"transcribing": "Transcripcion",
"unlockRoom": "",
"userPassword": "senhal utilizaire",
"WaitForHostMsg": "",
"WaitForHostMsgWOk": "",
"WaitForHostMsg": "La conferéncia <b>{{room}}</b> a pas encara començat. Se sètz lòst volgatz ben vos identificar. Autrament esperatz quarribe lòste.",
"WaitForHostMsgWOk": "La conferéncia <b>{{room}}</b> a pas encara començat. Se sètz lòst volgatz ben clicar Ok per vos identificar. Autrament esperatz quarribe lòste.",
"WaitingForHost": "Òm pòt pas que partejar una vidèo a l'encòp",
"Yes": "Òc",
"yourEntireScreen": "Vòstre ecran complet"
@@ -294,7 +295,7 @@
"invitePhoneAlternatives": "",
"inviteURLFirstPartGeneral": "Sètz convidat a participar a la conferéncia.",
"inviteURLFirstPartPersonal": "{{name}} vos convida a la conferéncia.\n",
"inviteURLSecondPart": "",
"inviteURLSecondPart": "\nParticipar a la conferéncia :\n{{url}}\n",
"liveStreamURL": "Flux dirècte:",
"moreNumbers": "Mai de numèros",
"noNumbers": "Pas cap de numèro.",
@@ -307,11 +308,11 @@
"label": "Info conferéncia"
},
"inviteDialog": {
"alertText": "",
"alertText": "Fracàs en convidant unes participants.",
"header": "Convidar",
"searchCallOnlyPlaceholder": "Picatz un numerò de telefòn",
"searchPeopleOnlyPlaceholder": "Cercar de participants",
"searchPlaceholder": "",
"searchPlaceholder": "Participant o numèro de telefòn",
"send": "Mandar"
},
"inlineDialogFailure": {
@@ -334,7 +335,8 @@
"toggleFilmstrip": "Mostrar o amagar la vinheta vidèo",
"toggleScreensharing": "Caplevar entre camèra e partatge d'ecran",
"toggleShortcuts": "Mostrar o amagar los acorchis clavièr",
"videoMute": "Aviar o arrestar vòstra camèra"
"videoMute": "Aviar o arrestar vòstra camèra",
"videoQuality": "Gerir la qualitat de las sonadas"
},
"liveStreaming": {
"busy": "Sèm a ensajar de liurar de ressorças flux. Mercés de tornar ensajar dins una estona.",
@@ -351,7 +353,7 @@
"expandedPending": "La difusion en dirècte comença...",
"failedToStart": "La difusion en dirècte a pas capitat de s'aviar",
"getStreamKeyManually": "",
"invalidStreamKey": "",
"invalidStreamKey": "La clau de difusion en dirècte es benlèu pas corrècta.",
"off": "La difusion en dirècte es estada arrestada",
"on": "La difusion en dirècte es estada arrestada",
"pending": "Començar lo dirècte...",
@@ -397,38 +399,38 @@
"lockRoomPasswordUppercase": "Senhal",
"me": "ieu",
"notify": {
"connectedOneMember": "",
"connectedOneMember": "{{name}} a jonch la conferéncia",
"connectedThreePlusMembers": "{{name}} e {{count}} personas mai participan a la conferéncia",
"connectedTwoMembers": "{{first}} e {{second}} participan a la conferéncia",
"disconnected": "desconnectat",
"focus": "Focus de conferéncia",
"focusFail": "{{component}} es pas disponible - ensajatz tornamai dins {{ms}} sec",
"grantedTo": "Dreits moderator acordats a {{to}} !",
"invitedOneMember": "",
"invitedThreePlusMembers": "",
"invitedTwoMembers": "",
"kickParticipant": "",
"invitedOneMember": "{{name}} es estat convidat",
"invitedThreePlusMembers": "{{name}} e {{count}} autres son estats convidats",
"invitedTwoMembers": "{{first}} e {{second}} son estats convidats",
"kickParticipant": "{{kicked}} es estat expulsat per {{kicker}}",
"me": "Ieu",
"moderator": "Dreits moderator acordats !",
"muted": "Avètz començat la conversacion en mut.",
"mutedTitle": "Sètz en mut !",
"mutedRemotelyTitle": "",
"mutedRemotelyTitle": "{{participantDisplayName}} vos a mes en silenci !",
"mutedRemotelyDescription": "",
"passwordRemovedRemotely": "",
"passwordSetRemotely": "",
"raisedHand": "{{name}} volriá parlar.",
"somebody": "Qualqu'un",
"startSilentTitle": "",
"startSilentDescription": "",
"suboptimalExperienceDescription": "Mmm, o plànhem que vòstra experiéncia amb {{appName}} es pas tan bona quaquò. Sèm a cercar de biais de melhorar aquò, per ara, podètz utilizar un dels <a href='static/recommendedBrowsers.html' target='_blank'> navegadors complètament compatibles</a>.",
"startSilentTitle": "Avètz jonch sens cap de sortida àudio !",
"startSilentDescription": "Rejónher la conferéncia per activar làudio",
"suboptimalBrowserWarning": "",
"suboptimalExperienceTitle": "Avertiment del navegador",
"unmute": "",
"unmute": "Restablir lo son",
"newDeviceCameraTitle": "Nòva camèra detectada",
"newDeviceAudioTitle": "Nòu periferic àudio detectat",
"newDeviceAction": "Utilizar"
},
"passwordSetRemotely": "causit per qualqu'un mai",
"passwordDigitsOnly": "",
"passwordDigitsOnly": "Fins a {{number}} chifras",
"poweredby": "produit per",
"presenceStatus": {
"busy": "Ocupat",
@@ -450,6 +452,7 @@
"setEmailLabel": "Definissètz vòstre corrièl per gravatar",
"title": "Perfil"
},
"raisedHand": "Volriá charrar",
"recording": {
"authDropboxText": "Enviar a Dropbox",
"availableSpace": "Espaci disponible : {{spaceLeft}} Mo (altorn de {{duration}} minutas denregistrament)",
@@ -461,14 +464,14 @@
"expandedOn": "La conferéncia es enregistrada.",
"expandedPending": "Aviada de lenregistrament...",
"failedToStart": "L'enregistrament n'as pas réussi a démarrer",
"fileSharingdescription": "",
"fileSharingdescription": "Partejar lenregistrament amb los participants de la reünion",
"live": "DIRÈCTE",
"loggedIn": "Session a {{userName}}",
"off": "Enregistrament arrestar",
"on": "Enregistrament",
"pending": "Preparacion de lenregistrament de la conferéncia...",
"rec": "ENRG",
"serviceDescription": "",
"serviceDescription": "Vòstre enregistrament serà salvagardat pel servici dedicat.",
"serviceName": "Servici denregistrament",
"signIn": "Connexion",
"signOut": "Se desconnectar",
@@ -514,7 +517,7 @@
"serverURL": "URL del servidor",
"startWithAudioMuted": "Començar sens son",
"startWithVideoMuted": "Començar sens vièdo",
"version": ""
"version": "Version"
},
"share": {
"dialInfoText": "",
@@ -542,7 +545,7 @@
"accessibilityLabel": {
"audioOnly": "Passar al sol àudio",
"audioRoute": "Seleccionar lo periferic àudio",
"callQuality": "",
"callQuality": "Gerir la qualitat vidèo",
"cc": "Passar als jostítols",
"chat": "Passar a la fenèstra chat",
"document": "Tampar los documents partejats",
@@ -574,11 +577,11 @@
"videoblur": ""
},
"addPeople": "Ajustar de monde a vòstra sonada",
"audioOnlyOff": "Desactivar lo mòde àudio sol",
"audioOnlyOn": "Activar lo mòde àudio sol",
"audioOnlyOff": "",
"audioOnlyOn": "",
"audioRoute": "Seleccionar lo periferic àudio",
"authenticate": "Autentificatz-vos",
"callQuality": "Gerir la qualitat de las sonadas",
"callQuality": "Gerir la qualitat vidèo",
"chat": "Dobrir / tampar la conversacion",
"closeChat": "Tampar la messatjariá",
"documentClose": "Tampar los documents partejats",
@@ -592,23 +595,23 @@
"invite": "Convidar de monde",
"login": "Connexion",
"logout": "Desconnexion",
"lowerYourHand": "",
"lowerYourHand": "Baissar la man",
"moreActions": "Mai dopcions",
"mute": "Mut / Actiu",
"openChat": "Dobrir la messatjariá ",
"pip": "Passar al mòde Picture-in-Picture",
"profile": "Modificar vòstre perfil",
"raiseHand": "Demandar / Daissar la paraula",
"raiseYourHand": "",
"raiseYourHand": "Levar la man",
"Settings": "Paramètres",
"sharedvideo": "Partejar una vidèo Youtube",
"shareRoom": "Convidar qualquun",
"shortcuts": "Veire los acorchis clavièr",
"speakerStats": "Estatisticas parladors",
"startScreenSharing": "",
"startSubtitles": "",
"stopScreenSharing": "",
"stopSubtitles": "",
"startScreenSharing": "Aviar lo partatge decran",
"startSubtitles": "Aviar los sostítols",
"stopScreenSharing": "Arrestar lo partatge decran",
"stopSubtitles": "Arrestar los sostítols ",
"stopSharedVideo": "Arrestar la vidèo Youtube",
"talkWhileMutedPopup": "Ensajatz de parlar ? Vòstre microfòn es copat.",
"tileViewToggle": "Activar/Desactivar la vista en mosaïc",
@@ -618,7 +621,7 @@
"stopvideoblur": ""
},
"transcribing": {
"ccButtonTooltip": "",
"ccButtonTooltip": "Aviar / Arrestat los sostítols",
"error": "Fracàs de la transcripcion. Mercés de tornar ensajar.",
"expandedLabel": "La transcripcion es activada",
"failedToStart": "Fracàs de laviada de la transcripcion",
@@ -653,13 +656,15 @@
},
"videoStatus": {
"audioOnly": "AUD",
"audioOnlyExpanded": "Sètz en mòde àudio solament. Aqueste mòde estàlvia la connexion mas poiretz pas veire las vidèos dels autres. ",
"callQuality": "",
"audioOnlyExpanded": "",
"callQuality": "Qualitat vidèo",
"hd": "HD",
"hdTooltip": "Difusion vidèo en nauta definicion",
"highDefinition": "Nauta definicion",
"labelTooiltipNoVideo": "Pas cap de vidèo",
"labelTooltipAudioOnly": "Mòde àudio sol activat",
"labelTooltipAudioOnly": "",
"ld": "Bassa definicion",
"ldTooltip": "Difusion vidèo en bassa definicion",
"lowDefinition": "Bassa definicion",
"onlyAudioAvailable": "Pas que làudio es disponible",
"onlyAudioSupported": "Sèm compatibles solament amb làudio dins aqueste navigator.",
@@ -667,6 +672,7 @@
"p2pVideoQualityDescription": "",
"recHighDefinitionOnly": "Nauta definicion preferida.",
"sd": "SD",
"sdTooltip": "Difusion vidèo en definicion estandard",
"standardDefinition": "Definicion estandard"
},
"videothumbnail": {
@@ -701,7 +707,7 @@
"recentList": "Recents",
"recentListDelete": "Suprimits",
"recentListEmpty": "Vòstra lista de contactes recents es voida. Charratz amb vòstra còla e trobaretz totes vòstras conferéncias recentas aquí.",
"reducedUIText": "",
"reducedUIText": "Benvengut a {{app}} !",
"roomname": "Sasissètz un nom de sala",
"roomnameHint": "Picatz lo nom o lURL de la sala que volètz jónher. Podètz inventar un nom, cal pas que lo monde que volètz convidar lo sàpian. ",
"sendFeedback": "Mandar vòstra opinion",

View File

@@ -21,10 +21,11 @@
"bluetooth": "Bluetooth",
"headphones": "Наушники",
"phone": "Телефон",
"speaker": "Колонка"
"speaker": "Колонка",
"none": ""
},
"audioOnly": {
"audioOnly": "Только звук"
"audioOnly": "Не нагружает канал"
},
"calendarSync": {
"addMeetingURL": "Добавить ссылку конференции",
@@ -101,8 +102,7 @@
"status": "Связь:",
"transport_0": "Методы отправки:",
"transport_1": "Методы отправки:",
"transport_2": "Методы отправки:",
"turn": " (повернуть)"
"transport_2": "Методы отправки:"
},
"dateUtils": {
"earlier": "Ранее",
@@ -120,6 +120,7 @@
"tryAgainButton": "Повторите в настольном приложении"
},
"defaultLink": "напр. {{url}}",
"defaultNickname": "напр. Яна Цветкова",
"deviceError": {
"cameraError": "Ошибка доступа к камере",
"cameraPermission": "Ошибка доступа к микрофону",
@@ -254,7 +255,7 @@
"token": "токен",
"tokenAuthFailed": "Извините, вам не разрешено присоединиться к этому сеансу связи.",
"tokenAuthFailedTitle": "Ошибка аутентификации",
"transcribing": "",
"transcribing": "Расшифровка",
"unlockRoom": "",
"userPassword": "пароль пользователя",
"WaitForHostMsg": "",
@@ -329,7 +330,7 @@
"keyboardShortcuts": {
"focusLocal": "Фокус на ваше видео",
"focusRemote": "Фокус на видео другого участника",
"fullScreen": "Вкл/выкл полноэкранный режим",
"fullScreen": "Вкл/выкл полноэкранный режим ",
"keyboardShortcuts": "Комбинации клавиш",
"localRecording": "",
"mute": "Микрофон (вкл./выкл.)",
@@ -339,8 +340,9 @@
"toggleChat": "Чат (открыть/закрыть)",
"toggleFilmstrip": "Показать/Скрыть краткое описание",
"toggleScreensharing": "Переключиться между камерой и показом экрана",
"toggleShortcuts": "",
"videoMute": "Камера (вкл./выкл.)"
"toggleShortcuts": "Скрыть/Показать горячие клавиши",
"videoMute": "Камера (вкл./выкл.)",
"videoQuality": "Качество связи"
},
"liveStreaming": {
"busy": "Освобождаем новые ресурсы для трансляции. Пожалуйста, попробуйте снова через несколько минут.",
@@ -365,7 +367,7 @@
"signedInAs": "",
"signIn": "Войти через Google",
"signInCTA": "Войдите или введите свой ключ трансляции YouTube.",
"signOut": "",
"signOut": "Выход",
"start": "Начать трансляцию",
"streamIdHelp": "Что это?",
"unavailableTitle": "Трансляция недоступна"
@@ -376,12 +378,12 @@
"on": "Подключен",
"unknown": "Неизвестен"
},
"dialogTitle": "",
"dialogTitle": "Кнопки локальной записи",
"duration": "Длительность",
"durationNA": "неизвестно",
"encoding": "Кодировка",
"label": "",
"labelToolTip": "",
"label": "Левый/Правый",
"labelToolTip": "Локальная запись активна",
"localRecording": "",
"me": "Я",
"messages": {
@@ -426,7 +428,7 @@
"somebody": "Кто-то",
"startSilentTitle": "",
"startSilentDescription": "",
"suboptimalExperienceDescription": "К сожалению, этот браузер не очень подходит для работы с {{appName}}. Мы работаем над проблемой, а пока попробуйте один из <a href='static/recommendedBrowsers.html 'target='_blank'>полностью поддерживаемых браузеров</a>.",
"suboptimalBrowserWarning": "",
"suboptimalExperienceTitle": "Предупреждение",
"unmute": "",
"newDeviceCameraTitle": "",
@@ -456,6 +458,7 @@
"setEmailLabel": "E-mail для gravatar",
"title": "Профиль"
},
"raisedHand": "Хочет говорить",
"recording": {
"authDropboxText": "",
"availableSpace": "Доступно места: {{spaceLeft}} MB (примерно {{duration}} минут записи)",
@@ -548,7 +551,7 @@
"accessibilityLabel": {
"audioOnly": "Вкл/выкл только звук",
"audioRoute": "Выбрать аудиоустройство",
"callQuality": "",
"callQuality": "Качество связи",
"cc": "Вкл/выкл субтитры",
"chat": "Показать/скрыть окно чата",
"document": "Закрыть общий документ",
@@ -580,8 +583,8 @@
"videoblur": ""
},
"addPeople": "Добавить людей к вашему сеансу связи",
"audioOnlyOff": "Выключить режим 'только звук'",
"audioOnlyOn": "Выключить режим 'только звук'",
"audioOnlyOff": "",
"audioOnlyOn": "",
"audioRoute": "Выбрать аудиоустройство",
"authenticate": "Аутентифицировать",
"callQuality": "Качество связи",
@@ -662,10 +665,12 @@
"audioOnlyExpanded": "",
"callQuality": "",
"hd": "HD",
"hdTooltip": "Видео высокого качества",
"highDefinition": "Высокое качество",
"labelTooiltipNoVideo": "Нет видео",
"labelTooltipAudioOnly": "Включен режим \"только звук\"",
"labelTooltipAudioOnly": "",
"ld": "LD",
"ldTooltip": "Видео низкого качества",
"lowDefinition": "Низкое качество",
"onlyAudioAvailable": "Только звук",
"onlyAudioSupported": "В этом браузере разрешен только звук.",
@@ -673,6 +678,7 @@
"p2pVideoQualityDescription": "",
"recHighDefinitionOnly": "Предпочтительно высокое качество.",
"sd": "SD",
"sdTooltip": "Видео стандартного качества",
"standardDefinition": "Стандартное качество (SD)"
},
"videothumbnail": {

View File

@@ -5,7 +5,11 @@ import {
createApiEvent,
sendAnalytics
} from '../../react/features/analytics';
import { setPassword, setSubject } from '../../react/features/base/conference';
import {
sendTones,
setPassword,
setSubject
} from '../../react/features/base/conference';
import { parseJWTFromURLParams } from '../../react/features/base/jwt';
import { invite } from '../../react/features/invite';
import { toggleTileView } from '../../react/features/video-layout';
@@ -90,6 +94,11 @@ function initCommands() {
'proxy-connection-event': event => {
APP.conference.onProxyConnectionEvent(event);
},
'send-tones': (options = {}) => {
const { duration, tones, pause } = options;
APP.store.dispatch(sendTones(tones, duration, pause));
},
'subject': subject => {
sendAnalytics(createApiEvent('subject.changed'));
APP.store.dispatch(setSubject(subject));

View File

@@ -18,8 +18,6 @@ import {
setVideoInputDevice
} from './functions';
const logger = require('jitsi-meet-logger').getLogger(__filename);
const ALWAYS_ON_TOP_FILENAMES = [
'css/all.css', 'libs/alwaysontop.min.js'
];
@@ -34,6 +32,7 @@ const commands = {
email: 'email',
hangup: 'video-hangup',
password: 'password',
sendTones: 'send-tones',
subject: 'subject',
submitFeedback: 'submit-feedback',
toggleAudio: 'toggle-audio',
@@ -617,7 +616,7 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
*/
executeCommand(name, ...args) {
if (!(name in commands)) {
logger.error('Not supported command name.');
console.error('Not supported command name.');
return;
}

View File

@@ -15,7 +15,6 @@ import Filmstrip from './videolayout/Filmstrip';
import { getLocalParticipant } from '../../react/features/base/participants';
import { toggleChat } from '../../react/features/chat';
import { openDisplayNamePrompt } from '../../react/features/display-name';
import { setEtherpadHasInitialzied } from '../../react/features/etherpad';
import { setFilmstripVisible } from '../../react/features/filmstrip';
import { setNotificationsEnabled } from '../../react/features/notifications';
@@ -549,13 +548,6 @@ UI.handleLastNEndpoints = function(leavingIds, enteringIds) {
VideoLayout.onLastNEndpointsChanged(leavingIds, enteringIds);
};
/**
* Prompt user for nickname.
*/
UI.promptDisplayName = () => {
APP.store.dispatch(openDisplayNamePrompt(undefined));
};
/**
* Update audio level visualization for specified user.
* @param {string} id user id

313
package-lock.json generated
View File

@@ -2852,9 +2852,9 @@
}
},
"@jitsi/sdp-simulcast": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@jitsi/sdp-simulcast/-/sdp-simulcast-0.2.1.tgz",
"integrity": "sha512-uEMQTi2Poq7NMUJfLD83iPm5nJfTC62w8PLdq7o6KEsXMcCJtCA1G6zmFpzd6NGQ6+zpaGwF9BuqV+6utLK9ag==",
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/@jitsi/sdp-simulcast/-/sdp-simulcast-0.2.2.tgz",
"integrity": "sha512-zQt9DRnG/wn7bQg3nat0+G2yptBtuZuQN0iG5LHy4/wedyzV7HjEE73Zod69i7boZlRgvdjyexoaiwisrj9knw==",
"requires": {
"sdp-transform": "2.3.0"
}
@@ -3444,6 +3444,12 @@
"acorn": "^5.0.3"
}
},
"acorn-walk": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz",
"integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==",
"dev": true
},
"ajv": {
"version": "5.5.2",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
@@ -4413,6 +4419,26 @@
"tweetnacl": "^0.14.3"
}
},
"bfj": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz",
"integrity": "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==",
"dev": true,
"requires": {
"bluebird": "^3.5.5",
"check-types": "^8.0.3",
"hoopy": "^0.1.4",
"tryer": "^1.0.1"
},
"dependencies": {
"bluebird": {
"version": "3.5.5",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz",
"integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==",
"dev": true
}
}
},
"big-integer": {
"version": "1.6.44",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.44.tgz",
@@ -4835,6 +4861,12 @@
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
"integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I="
},
"check-types": {
"version": "8.0.3",
"resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz",
"integrity": "sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==",
"dev": true
},
"chokidar": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz",
@@ -6083,6 +6115,12 @@
"moment": "^2.19.3"
}
},
"duplexer": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
"dev": true
},
"duplexify": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.4.tgz",
@@ -6142,6 +6180,12 @@
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"ejs": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.1.tgz",
"integrity": "sha512-kS/gEPzZs3Y1rRsbGX4UOSjtP/CeJP0CxSNZHYxGfVM/VgLcv0ZqM7C45YyTj2DI2g7+P9Dd24C+IMIg6D0nYQ==",
"dev": true
},
"electron-to-chromium": {
"version": "1.3.34",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.34.tgz",
@@ -7220,6 +7264,12 @@
"object-assign": "^4.0.1"
}
},
"filesize": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz",
"integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==",
"dev": true
},
"fill-range": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
@@ -8100,8 +8150,7 @@
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"functional-red-black-tree": {
"version": "1.0.1",
@@ -8254,6 +8303,24 @@
"resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz",
"integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw=="
},
"gzip-size": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz",
"integrity": "sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==",
"dev": true,
"requires": {
"duplexer": "^0.1.1",
"pify": "^4.0.1"
},
"dependencies": {
"pify": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
"dev": true
}
}
},
"handle-thing": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz",
@@ -8306,7 +8373,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz",
"integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=",
"dev": true,
"requires": {
"function-bind": "^1.0.2"
}
@@ -8325,6 +8391,11 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
"integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo="
},
"has-symbols": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
"integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q="
},
"has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
@@ -8429,6 +8500,12 @@
}
}
},
"hoopy": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
"integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==",
"dev": true
},
"hosted-git-info": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz",
@@ -9305,6 +9382,11 @@
"kind-of": "^3.0.2"
}
},
"is-arguments": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
"integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA=="
},
"is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
@@ -9357,8 +9439,7 @@
"is-date-object": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
"integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
"dev": true
"integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="
},
"is-descriptor": {
"version": "0.1.6",
@@ -9401,6 +9482,11 @@
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
},
"is-generator-function": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz",
"integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw=="
},
"is-number": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
@@ -9456,7 +9542,6 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
"integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
"dev": true,
"requires": {
"has": "^1.0.1"
}
@@ -10554,11 +10639,11 @@
}
},
"lib-jitsi-meet": {
"version": "github:jitsi/lib-jitsi-meet#4010d2a301fa847374f2744d6f826d3decebe76a",
"from": "github:jitsi/lib-jitsi-meet#4010d2a301fa847374f2744d6f826d3decebe76a",
"version": "github:jitsi/lib-jitsi-meet#486c61e2a91eeb3d9b6f179ea0c82044e321dccf",
"from": "github:jitsi/lib-jitsi-meet#486c61e2a91eeb3d9b6f179ea0c82044e321dccf",
"requires": {
"@jitsi/sdp-interop": "0.1.14",
"@jitsi/sdp-simulcast": "0.2.1",
"@jitsi/sdp-simulcast": "0.2.2",
"async": "0.9.0",
"current-executing-script": "0.1.3",
"jitsi-meet-logger": "github:jitsi/jitsi-meet-logger#a885cc98688ef2c3972284bda901596a26ffee52",
@@ -12032,6 +12117,15 @@
"requires": {
"safe-buffer": "~5.1.0"
}
},
"util": {
"version": "0.10.4",
"resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
"integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
"dev": true,
"requires": {
"inherits": "2.0.3"
}
}
}
},
@@ -12285,6 +12379,76 @@
"isobject": "^3.0.0"
}
},
"object.entries": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz",
"integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==",
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.12.0",
"function-bind": "^1.1.1",
"has": "^1.0.3"
},
"dependencies": {
"define-properties": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
"requires": {
"object-keys": "^1.0.12"
}
},
"es-abstract": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
"integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
"requires": {
"es-to-primitive": "^1.2.0",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"is-callable": "^1.1.4",
"is-regex": "^1.0.4",
"object-keys": "^1.0.12"
}
},
"es-to-primitive": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
"integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
"requires": {
"is-callable": "^1.1.4",
"is-date-object": "^1.0.1",
"is-symbol": "^1.0.2"
}
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"requires": {
"function-bind": "^1.1.1"
}
},
"is-callable": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
"integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA=="
},
"is-symbol": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
"integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
"requires": {
"has-symbols": "^1.0.0"
}
},
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
}
}
},
"object.getownpropertydescriptors": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
@@ -12346,6 +12510,12 @@
"is-wsl": "^1.1.0"
}
},
"opener": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz",
"integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==",
"dev": true
},
"optionator": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
@@ -14090,8 +14260,8 @@
"integrity": "sha512-cuXIIv+dcG8a8qkTD8pMzeqOEZCO+UGKglZWIe1osve+yJslmCowYQff+bI9xa7NOt2w+Vtd4L3d9JonlSqODg=="
},
"react-native-calendar-events": {
"version": "github:jitsi/react-native-calendar-events#f621cbe97b182cfaca41545fd6b818a85d632506",
"from": "github:jitsi/react-native-calendar-events#f621cbe97b182cfaca41545fd6b818a85d632506"
"version": "github:jitsi/react-native-calendar-events#902e6e92d6bae450a6052f76ba4d02f977ffd8f2",
"from": "github:jitsi/react-native-calendar-events#902e6e92d6bae450a6052f76ba4d02f977ffd8f2"
},
"react-native-callstats": {
"version": "3.61.0",
@@ -14184,8 +14354,8 @@
"integrity": "sha512-l3Quzbb+qa4in2U5RSt/lT0/pHrIpEChT1NnqrVAAXNrjkXjVOsxduaaEDdDhTzNJQEm/PcAcoyrFmgvGOohxw=="
},
"react-native-webrtc": {
"version": "github:jitsi/react-native-webrtc#44ecfddfa816d260087e16c92f299ded169a4472",
"from": "github:jitsi/react-native-webrtc#44ecfddfa816d260087e16c92f299ded169a4472",
"version": "github:react-native-webrtc/react-native-webrtc#b1275ccf1e0e083d2a5c238e7d21c37657766463",
"from": "github:react-native-webrtc/react-native-webrtc#b1275ccf1e0e083d2a5c238e7d21c37657766463",
"requires": {
"base64-js": "^1.1.2",
"event-target-shim": "^1.0.5",
@@ -14194,9 +14364,9 @@
},
"dependencies": {
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
"integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
}
}
},
@@ -17019,6 +17189,12 @@
"glob": "^7.1.2"
}
},
"tryer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz",
"integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==",
"dev": true
},
"tslib": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
@@ -17339,12 +17515,22 @@
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
},
"util": {
"version": "0.10.4",
"resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
"integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
"dev": true,
"version": "0.12.1",
"resolved": "https://registry.npmjs.org/util/-/util-0.12.1.tgz",
"integrity": "sha512-MREAtYOp+GTt9/+kwf00IYoHZyjM8VU4aVrkzUlejyqaIjd2GztVl5V9hGXKlvBKE3gENn/FMfHE5v6hElXGcQ==",
"requires": {
"inherits": "2.0.3"
"inherits": "^2.0.3",
"is-arguments": "^1.0.4",
"is-generator-function": "^1.0.7",
"object.entries": "^1.1.0",
"safe-buffer": "^5.1.2"
},
"dependencies": {
"safe-buffer": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
}
}
},
"util-deprecate": {
@@ -17845,6 +18031,85 @@
}
}
},
"webpack-bundle-analyzer": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.4.1.tgz",
"integrity": "sha512-Bs8D/1zF+17lhqj2OYmzi7HEVYqEVxu7lCO9Ff8BwajenOU0vAwEoV8e4ICCPNZAcqR1PCR/7o2SkW+cnCmF0A==",
"dev": true,
"requires": {
"acorn": "^6.0.7",
"acorn-walk": "^6.1.1",
"bfj": "^6.1.1",
"chalk": "^2.4.1",
"commander": "^2.18.0",
"ejs": "^2.6.1",
"express": "^4.16.3",
"filesize": "^3.6.1",
"gzip-size": "^5.0.0",
"lodash": "^4.17.15",
"mkdirp": "^0.5.1",
"opener": "^1.5.1",
"ws": "^6.0.0"
},
"dependencies": {
"acorn": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz",
"integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==",
"dev": true
},
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
"dev": true
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
},
"ws": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
"integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
"dev": true,
"requires": {
"async-limiter": "~1.0.0"
}
}
}
},
"webpack-cli": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.1.2.tgz",

View File

@@ -55,7 +55,7 @@
"js-utils": "github:jitsi/js-utils#192b1c996e8c05530eb1f19e82a31069c3021e31",
"jsrsasign": "8.0.12",
"jwt-decode": "2.2.0",
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#4010d2a301fa847374f2744d6f826d3decebe76a",
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#486c61e2a91eeb3d9b6f179ea0c82044e321dccf",
"libflacjs": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d",
"lodash": "4.17.13",
"moment": "2.19.4",
@@ -68,7 +68,7 @@
"react-linkify": "1.0.0-alpha",
"react-native": "0.60.5",
"react-native-background-timer": "2.1.1",
"react-native-calendar-events": "github:jitsi/react-native-calendar-events#f621cbe97b182cfaca41545fd6b818a85d632506",
"react-native-calendar-events": "github:jitsi/react-native-calendar-events#902e6e92d6bae450a6052f76ba4d02f977ffd8f2",
"react-native-callstats": "3.61.0",
"react-native-google-signin": "2.0.0",
"react-native-immersive": "2.0.0",
@@ -78,7 +78,7 @@
"react-native-swipeout": "2.3.6",
"react-native-vector-icons": "6.0.2",
"react-native-watch-connectivity": "0.2.0",
"react-native-webrtc": "github:jitsi/react-native-webrtc#44ecfddfa816d260087e16c92f299ded169a4472",
"react-native-webrtc": "github:react-native-webrtc/react-native-webrtc#b1275ccf1e0e083d2a5c238e7d21c37657766463",
"react-native-webview": "5.8.1",
"react-redux": "7.1.0",
"react-textarea-autosize": "7.1.0",
@@ -86,6 +86,7 @@
"redux": "4.0.4",
"redux-thunk": "2.2.0",
"styled-components": "3.4.9",
"util": "0.12.1",
"uuid": "3.1.0",
"windows-iana": "^3.1.0",
"xmldom": "0.1.27"
@@ -123,6 +124,7 @@
"string-replace-loader": "2.1.1",
"style-loader": "0.19.0",
"webpack": "4.26.1",
"webpack-bundle-analyzer": "3.4.1",
"webpack-cli": "3.1.2",
"webpack-dev-server": "3.1.14"
},

View File

@@ -5,8 +5,6 @@
import AbstractAudioMuteButton from '../base/toolbox/components/AbstractAudioMuteButton';
import type { Props } from '../base/toolbox/components/AbstractButton';
import logger from './logger';
const { api } = window.alwaysOnTop;
/**
@@ -72,7 +70,7 @@ export default class AudioMuteButton
audioAvailable,
audioMuted
}))
.catch(logger.error);
.catch(console.error);
}
/**

View File

@@ -5,8 +5,6 @@
import AbstractVideoMuteButton from '../base/toolbox/components/AbstractVideoMuteButton';
import type { Props } from '../base/toolbox/components/AbstractButton';
import logger from './logger';
const { api } = window.alwaysOnTop;
/**
@@ -72,7 +70,7 @@ export default class VideoMuteButton
videoAvailable,
videoMuted
}))
.catch(logger.error);
.catch(console.error);
}
/**

View File

@@ -1,3 +0,0 @@
import { getLogger } from '../base/logging/functions';
export default getLogger('features/always-on-top');

View File

@@ -63,12 +63,15 @@ export function initAnalytics({ getState }: { getState: Function }) {
} = config;
const {
amplitudeAPPKey,
blackListedEvents,
scriptURLs,
googleAnalyticsTrackingId
googleAnalyticsTrackingId,
whiteListedEvents
} = analyticsConfig;
const { group, server, user } = state['features/base/jwt'];
const handlerConstructorOptions = {
amplitudeAPPKey,
blackListedEvents,
envType: (deploymentInfo && deploymentInfo.envType) || 'dev',
googleAnalyticsTrackingId,
group,
@@ -76,7 +79,8 @@ export function initAnalytics({ getState }: { getState: Function }) {
product: deploymentInfo && deploymentInfo.product,
subproduct: deploymentInfo && deploymentInfo.environment,
user: user && user.id,
version: JitsiMeetJS.version
version: JitsiMeetJS.version,
whiteListedEvents
};
_loadHandlers(scriptURLs, handlerConstructorOptions)

View File

@@ -4,12 +4,22 @@
export default class AbstractHandler {
/**
* Creates new instance.
*
* @param {Object} options - Optional parameters.
*/
constructor() {
constructor(options = {}) {
this._enabled = false;
this._ignoredEvents
= [ 'e2e_rtt', 'rtp.stats', 'rtt.by.region', 'available.device',
'stream.switch.delay', 'ice.state.changed', 'ice.duration' ];
this._whiteListedEvents = options.whiteListedEvents;
// FIXME:
// Keeping the list with the very noisy events so that we don't flood with events whoever hasn't configured
// white/black lists yet. We need to solve this issue properly by either making these events not so noisy or
// by removing them completely from the code.
this._blackListedEvents = [
...(options.blackListedEvents || []), // eslint-disable-line no-extra-parens
'e2e_rtt', 'rtp.stats', 'rtt.by.region', 'available.device', 'stream.switch.delay', 'ice.state.changed',
'ice.duration'
];
}
/**
@@ -60,7 +70,16 @@ export default class AbstractHandler {
return true;
}
// Temporary removing some of the events that are too noisy.
return this._ignoredEvents.indexOf(event.action) !== -1;
const name = this._extractName(event);
if (Array.isArray(this._whiteListedEvents)) {
return this._whiteListedEvents.indexOf(name) === -1;
}
if (Array.isArray(this._blackListedEvents)) {
return this._blackListedEvents.indexOf(name) !== -1;
}
return false;
}
}

View File

@@ -13,7 +13,7 @@ export default class AmplitudeHandler extends AbstractHandler {
* by the Amplitude API.
*/
constructor(options) {
super();
super(options);
const { amplitudeAPPKey, host, user } = options;

View File

@@ -17,7 +17,7 @@ class GoogleAnalyticsHandler extends AbstractHandler {
* required by the GA API.
*/
constructor(options) {
super();
super(options);
this._userProperties = {};

View File

@@ -118,6 +118,18 @@ export const LOCK_STATE_CHANGED = 'LOCK_STATE_CHANGED';
*/
export const P2P_STATUS_CHANGED = 'P2P_STATUS_CHANGED';
/**
* The type of (redux) action which signals to play specified touch tones.
*
* {
* type: SEND_TONES,
* tones: string,
* duration: number,
* pause: number
* }
*/
export const SEND_TONES = 'SEND_TONES';
/**
* The type of (redux) action which sets the desktop sharing enabled flag for
* the current conference.

View File

@@ -37,6 +37,7 @@ import {
KICKED_OUT,
LOCK_STATE_CHANGED,
P2P_STATUS_CHANGED,
SEND_TONES,
SET_DESKTOP_SHARING_ENABLED,
SET_FOLLOW_ME,
SET_MAX_RECEIVER_VIDEO_QUALITY,
@@ -520,6 +521,28 @@ export function p2pStatusChanged(p2p: boolean) {
};
}
/**
* Signals to play touch tones.
*
* @param {string} tones - The tones to play.
* @param {number} [duration] - How long to play each tone.
* @param {number} [pause] - How long to pause between each tone.
* @returns {{
* type: SEND_TONES,
* tones: string,
* duration: number,
* pause: number
* }}
*/
export function sendTones(tones: string, duration: number, pause: number) {
return {
type: SEND_TONES,
tones,
duration,
pause
};
}
/**
* Sets the flag for indicating if desktop sharing is enabled.
*

View File

@@ -1,6 +1,8 @@
// @flow
import { reloadNow } from '../../app';
import { openDisplayNamePrompt } from '../../display-name';
import {
ACTION_PINNED,
ACTION_UNPINNED,
@@ -12,6 +14,7 @@ import {
import { CONNECTION_ESTABLISHED, CONNECTION_FAILED } from '../connection';
import { JitsiConferenceErrors } from '../lib-jitsi-meet';
import {
getLocalParticipant,
getParticipantById,
getPinnedParticipant,
PARTICIPANT_UPDATED,
@@ -32,6 +35,7 @@ import {
CONFERENCE_SUBJECT_CHANGED,
CONFERENCE_WILL_LEAVE,
DATA_CHANNEL_OPENED,
SEND_TONES,
SET_PENDING_SUBJECT_CHANGE,
SET_ROOM
} from './actionTypes';
@@ -86,6 +90,9 @@ MiddlewareRegistry.register(store => next => action => {
case PIN_PARTICIPANT:
return _pinParticipant(store, next, action);
case SEND_TONES:
return _sendTones(store, next, action);
case SET_ROOM:
return _setRoom(store, next, action);
@@ -186,6 +193,7 @@ function _conferenceJoined({ dispatch, getState }, next, action) {
const result = next(action);
const { conference } = action;
const { pendingSubjectChange } = getState()['features/base/conference'];
const { requireDisplayName } = getState()['features/base/config'];
pendingSubjectChange && dispatch(setSubject(pendingSubjectChange));
@@ -199,6 +207,12 @@ function _conferenceJoined({ dispatch, getState }, next, action) {
};
window.addEventListener('beforeunload', beforeUnloadHandler);
if (requireDisplayName
&& !getLocalParticipant(getState)?.name
&& !conference.isHidden()) {
dispatch(openDisplayNamePrompt(undefined));
}
return result;
}
@@ -436,6 +450,31 @@ function _pinParticipant({ getState }, next, action) {
return next(action);
}
/**
* Requests the specified tones to be played.
*
* @param {Store} store - The redux store in which the specified {@code action}
* is being dispatched.
* @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
* specified {@code action} to the specified {@code store}.
* @param {Action} action - The redux action {@code SEND_TONES} which is
* being dispatched in the specified {@code store}.
* @private
* @returns {Object} The value returned by {@code next(action)}.
*/
function _sendTones({ getState }, next, action) {
const state = getState();
const { conference } = state['features/base/conference'];
if (conference) {
const { duration, tones, pause } = action;
conference.sendTones(tones, duration, pause);
}
return next(action);
}
/**
* Helper function for updating the preferred receiver video constraint, based
* on the user preference and the internal maximum.

View File

@@ -0,0 +1,65 @@
// @flow
import { NativeModules } from 'react-native';
import { format } from 'util';
// Some code adapted from https://github.com/houserater/react-native-lumberjack
// License: MIT
const { LogBridge } = NativeModules;
/**
* Returns the stack trace for a given @code {Error} object.
*
* @param {Errror} e - The rrror.
* @returns {string} - The stack trace.
*/
function stackToString(e) {
let ce;
let s = e.stack;
if (typeof e.cause === 'function' && (ce = e.cause())) {
s += `\nCaused by: ${stackToString(ce)}`;
}
return s;
}
/**
* Constructs a log transport object for use with jitsi-meet-logger.
*
* @returns {Object} - The transport object.
*/
function buildTransport() {
return [
'trace',
'debug',
'info',
'log',
'warn',
'error'
].reduce((logger, logName) => {
logger[logName] = (...args: Array<string>) => {
const nargs = args.map(arg => {
if (arg instanceof Error) {
const errorBody = {
message: arg.message,
code: arg.code,
stack: stackToString(arg)
};
return `Error(${arg.name})${JSON.stringify(errorBody)}`;
}
return arg;
});
const message = format(...nargs);
LogBridge[logName](message);
};
return logger;
}, {});
}
export default buildTransport();

View File

@@ -1,6 +1,9 @@
// @flow
import { getLogger as _getLogger } from 'jitsi-meet-logger';
import _ from 'lodash';
import Logger, { getLogger as _getLogger } from 'jitsi-meet-logger';
import LogTransport from './LogTransport';
/**
* Options for building the logger. We disable the callee info on RN because it's
@@ -20,3 +23,22 @@ export function getLogger(id: string) {
return _getLogger(id, undefined, opts);
}
/**
* Initializes native logging. This operations must be done as early as possible.
*/
export const _initLogging = _.once(() => {
if (navigator.product !== 'ReactNative') {
return;
}
// Lazy load it to avoid cycles in early web bootstrap code.
const { default: JitsiMeetJS } = require('../lib-jitsi-meet');
Logger.setGlobalOptions(DEFAULT_RN_OPTS);
JitsiMeetJS.setGlobalLogOptions(DEFAULT_RN_OPTS);
Logger.removeGlobalTransport(console);
JitsiMeetJS.removeGlobalLogTransport(console);
Logger.addGlobalTransport(LogTransport);
JitsiMeetJS.addGlobalLogTransport(LogTransport);
});

View File

@@ -163,12 +163,6 @@ function _initLogging({ dispatch, getState }, loggingConfig, isTestingEnabled) {
logCollector.stop();
dispatch(setLogCollector(undefined));
}
// Disable caller function info.
if (navigator.product === 'ReactNative') {
Logger.setGlobalOptions({ disableCallerInfo: true });
JitsiMeetJS.setGlobalLogOptions({ disableCallerInfo: true });
}
}
/**

View File

@@ -13,6 +13,11 @@ import styles, { AVATAR_SIZE, UNDERLAY_COLOR } from './styles';
type Props = {
/**
* If true, only the avatar gets rendered, no lines of text.
*/
avatarOnly?: boolean,
/**
* Preferred size of the avatar.
*/
@@ -76,6 +81,7 @@ export default class AvatarListItem extends Component<Props> {
*/
render() {
const {
avatarOnly,
avatarSize = AVATAR_SIZE,
avatarStyle
} = this.props;
@@ -92,7 +98,7 @@ export default class AvatarListItem extends Component<Props> {
size = { avatarSize }
style = { avatarStyle }
url = { avatar } />
<Container style = { styles.listItemDetails }>
{ avatarOnly || <Container style = { styles.listItemDetails }>
<Text
numberOfLines = { 1 }
style = { [
@@ -103,7 +109,7 @@ export default class AvatarListItem extends Component<Props> {
{ title }
</Text>
{this._renderItemLines(lines)}
</Container>
</Container>}
{ this.props.children }
</Container>
);

View File

@@ -1,7 +1,5 @@
// @flow
import logger from './logger';
/**
* Creates a deferred object.
*
@@ -106,6 +104,6 @@ export function assignIfDefined(target: Object, source: Object) {
* @returns {void}
*/
export function reportError(e: Object, msg: string = '') {
logger.error(msg, e);
console.error(msg, e);
window.onerror && window.onerror(msg, null, null, null, e);
}

View File

@@ -1,7 +1,5 @@
import { timeoutPromise } from './timeoutPromise';
import logger from './logger';
/**
* The number of milliseconds before deciding that we need retry a fetch request.
*
@@ -29,11 +27,6 @@ export function doGetJSON(url, retry) {
return jsonify
.then(result => Promise.reject(result));
})
.catch(error => {
logger.error('Error performing get:', url, error);
return Promise.reject(error);
});
if (retry) {

View File

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

View File

@@ -1,7 +1,5 @@
// @flow
import logger from './logger';
/**
* The app linking scheme.
* TODO: This should be read from the manifest files later.
@@ -133,7 +131,7 @@ function _objectToURLParamsArray(obj = {}) {
params.push(
`${key}=${encodeURIComponent(JSON.stringify(obj[key]))}`);
} catch (e) {
logger.warn(`Error encoding ${key}: ${e}`);
console.warn(`Error encoding ${key}: ${e}`);
}
}

View File

@@ -106,6 +106,7 @@ class AddPeopleDialog extends AbstractAddPeopleDialog<Props, State> {
this.state = this.defaultState;
this._keyExtractor = this._keyExtractor.bind(this);
this._renderInvitedItem = this._renderInvitedItem.bind(this);
this._renderItem = this._renderItem.bind(this);
this._renderSeparator = this._renderSeparator.bind(this);
this._onClearField = this._onClearField.bind(this);
@@ -138,7 +139,7 @@ class AddPeopleDialog extends AbstractAddPeopleDialog<Props, State> {
_addPeopleEnabled,
_dialOutEnabled
} = this.props;
const { inviteItems } = this.state;
const { inviteItems, selectableItems } = this.state;
let placeholderKey = 'searchPlaceholder';
@@ -187,14 +188,23 @@ class AddPeopleDialog extends AbstractAddPeopleDialog<Props, State> {
value = { this.state.fieldValue } />
{ this._renderAndroidClearButton() }
</View>
<FlatList
ItemSeparatorComponent = { this._renderSeparator }
data = { this.state.selectableItems }
extraData = { inviteItems }
keyExtractor = { this._keyExtractor }
keyboardShouldPersistTaps = 'always'
renderItem = { this._renderItem }
style = { styles.resultList } />
{ Boolean(inviteItems.length) && <View style = { styles.invitedList }>
<FlatList
data = { inviteItems }
horizontal = { true }
keyExtractor = { this._keyExtractor }
keyboardShouldPersistTaps = 'always'
renderItem = { this._renderInvitedItem } />
</View> }
<View style = { styles.resultList }>
<FlatList
ItemSeparatorComponent = { this._renderSeparator }
data = { selectableItems }
extraData = { inviteItems }
keyExtractor = { this._keyExtractor }
keyboardShouldPersistTaps = 'always'
renderItem = { this._renderItem } />
</View>
</SafeAreaView>
</KeyboardAvoidingView>
</SlidingView>
@@ -210,6 +220,33 @@ class AddPeopleDialog extends AbstractAddPeopleDialog<Props, State> {
this.setState(this.defaultState);
}
/**
* Returns an object capable of being rendered by an {@code AvatarListItem}.
*
* @param {Object} flatListItem - An item of the data array of the {@code FlatList}.
* @returns {?Object}
*/
_getRenderableItem(flatListItem) {
const { item } = flatListItem;
switch (item.type) {
case 'phone':
return {
avatar: 'icon://phone',
key: item.number,
title: item.number
};
case 'user':
return {
avatar: item.avatar,
key: item.id || item.user_id,
title: item.name
};
default:
return null;
}
}
_invite: Array<Object> => Promise<Array<Object>>
_isAddDisabled: () => boolean;
@@ -303,7 +340,7 @@ class AddPeopleDialog extends AbstractAddPeopleDialog<Props, State> {
});
} else {
// Item is not selected yet, need to add to the list.
const items: Array<*> = inviteItems.concat(item);
const items: Array<Object> = inviteItems.concat(item);
this.setState({
inviteItems: _.sortBy(items, [ 'name', 'number' ])
@@ -344,27 +381,8 @@ class AddPeopleDialog extends AbstractAddPeopleDialog<Props, State> {
*/
_performSearch(query) {
this._query(query).then(results => {
const { inviteItems } = this.state;
let selectableItems = results.filter(result => {
switch (result.type) {
case 'phone':
return result.allowed && result.number
&& !inviteItems.find(
_.matchesProperty('number', result.number));
case 'user':
return !inviteItems.find(
(result.user_id && _.matchesProperty('id', result.id))
|| (result.user_id && _.matchesProperty('user_id', result.user_id)));
default:
return false;
}
});
selectableItems = _.sortBy(selectableItems, [ 'name', 'number' ]);
this.setState({
selectableItems: this.state.inviteItems.concat(selectableItems)
selectableItems: _.sortBy(results, [ 'name', 'number' ])
});
})
.finally(() => {
@@ -378,8 +396,6 @@ class AddPeopleDialog extends AbstractAddPeopleDialog<Props, State> {
_query: (string) => Promise<Array<Object>>;
_renderItem: Object => ?React$Element<*>
/**
* Renders a button to clear the text field on Android.
*
@@ -405,8 +421,46 @@ class AddPeopleDialog extends AbstractAddPeopleDialog<Props, State> {
);
}
_renderInvitedItem: Object => ?React$Element<*>
/**
* Renders a single item in the {@code FlatList}.
* Renders a single item in the invited {@code FlatList}.
*
* @param {Object} flatListItem - An item of the data array of the
* {@code FlatList}.
* @param {number} index - The index of the currently rendered item.
* @returns {?React$Element<*>}
*/
_renderInvitedItem(flatListItem, index) {
const { item } = flatListItem;
const renderableItem = this._getRenderableItem(flatListItem);
return (
<TouchableOpacity onPress = { this._onPressItem(item) } >
<View
pointerEvents = 'box-only'
style = { styles.itemWrapper }>
<AvatarListItem
avatarOnly = { true }
avatarSize = { AVATAR_SIZE }
avatarStyle = { styles.avatar }
avatarTextStyle = { styles.avatarText }
item = { renderableItem }
key = { index }
linesStyle = { styles.itemLinesStyle }
titleStyle = { styles.itemText } />
<Icon
name = 'cancel'
style = { styles.unselectIcon } />
</View>
</TouchableOpacity>
);
}
_renderItem: Object => ?React$Element<*>
/**
* Renders a single item in the search result {@code FlatList}.
*
* @param {Object} flatListItem - An item of the data array of the
* {@code FlatList}.
@@ -417,28 +471,20 @@ class AddPeopleDialog extends AbstractAddPeopleDialog<Props, State> {
const { item } = flatListItem;
const { inviteItems } = this.state;
let selected = false;
let renderableItem;
const renderableItem = this._getRenderableItem(flatListItem);
if (!renderableItem) {
return null;
}
switch (item.type) {
case 'phone':
selected
= inviteItems.find(_.matchesProperty('number', item.number));
renderableItem = {
avatar: 'icon://phone',
key: item.number,
title: item.number
};
selected = inviteItems.find(_.matchesProperty('number', item.number));
break;
case 'user':
selected
= item.id
? inviteItems.find(_.matchesProperty('id', item.id))
: inviteItems.find(_.matchesProperty('user_id', item.user_id));
renderableItem = {
avatar: item.avatar,
key: item.id || item.user_id,
title: item.name
};
selected = item.id
? inviteItems.find(_.matchesProperty('id', item.id))
: inviteItems.find(_.matchesProperty('user_id', item.user_id));
break;
default:
return null;
@@ -449,11 +495,6 @@ class AddPeopleDialog extends AbstractAddPeopleDialog<Props, State> {
<View
pointerEvents = 'box-only'
style = { styles.itemWrapper }>
<Icon
name = { selected
? 'radio_button_checked'
: 'radio_button_unchecked' }
style = { styles.radioButton } />
<AvatarListItem
avatarSize = { AVATAR_SIZE }
avatarStyle = { styles.avatar }
@@ -462,6 +503,9 @@ class AddPeopleDialog extends AbstractAddPeopleDialog<Props, State> {
key = { index }
linesStyle = { styles.itemLinesStyle }
titleStyle = { styles.itemText } />
{ selected && <Icon
name = 'check'
style = { styles.selectedIcon } /> }
</View>
</TouchableOpacity>
);

View File

@@ -1,6 +1,6 @@
// @flow
import { ColorPalette } from '../../../../base/styles';
import { BoxModel, ColorPalette } from '../../../../base/styles';
export const AVATAR_SIZE = 40;
export const DARK_GREY = 'rgb(28, 32, 37)';
@@ -15,7 +15,7 @@ export default {
},
avatarText: {
color: 'rgb(28, 32, 37)',
color: DARK_GREY,
fontSize: 12
},
@@ -48,7 +48,12 @@ export default {
alignItems: 'stretch',
backgroundColor: ColorPalette.white,
flex: 1,
flexDirection: 'column'
flexDirection: 'column',
justifyContent: 'flex-start'
},
invitedList: {
padding: 3
},
itemLinesStyle: {
@@ -68,13 +73,8 @@ export default {
paddingLeft: 5
},
radioButton: {
color: DARK_GREY,
fontSize: 16,
padding: 2
},
resultList: {
flex: 1,
padding: 5
},
@@ -88,6 +88,13 @@ export default {
paddingVertical: 7
},
selectedIcon: {
color: DARK_GREY,
fontSize: 20,
marginRight: BoxModel.margin,
padding: 2
},
separator: {
borderBottomColor: LIGHT_GREY,
borderBottomWidth: 1,
@@ -115,5 +122,13 @@ export default {
flexDirection: 'row',
justifyContent: 'center',
width: ICON_SIZE + 16
},
unselectIcon: {
color: LIGHT_GREY,
fontSize: 16,
left: AVATAR_SIZE / -3,
position: 'relative',
top: AVATAR_SIZE / -3
}
};

View File

@@ -8,7 +8,7 @@ import { i18next } from '../../../base/i18n';
import { DialInSummary } from '../dial-in-summary';
import NoRoomError from './NoRoomError';
import { Platform } from '../../../base/react';
import Platform from '../../../base/react/Platform.web';
document.addEventListener('DOMContentLoaded', () => {
const { room } = parseURLParams(window.location, true, 'search');

View File

@@ -1,4 +1,4 @@
import logger from '../../logger';
import {
MAIN_THREAD_FINISH,
MAIN_THREAD_INIT,
@@ -262,7 +262,7 @@ class Encoder {
const errorNo
= Flac.FLAC__stream_encoder_get_state(this._encoderId);
logger.error('Error during encoding', FLAC_ERRORS[errorNo]);
console.error('Error during encoding', FLAC_ERRORS[errorNo]);
}
}
@@ -277,7 +277,7 @@ class Encoder {
const status = Flac.FLAC__stream_encoder_finish(this._encoderId);
logger.log('Flac encoding finished: ', status);
console.log('Flac encoding finished: ', status);
// free up resources
Flac.FLAC__stream_encoder_delete(this._encoderId);
@@ -371,8 +371,7 @@ self.onmessage = function(e) {
case MAIN_THREAD_NEW_DATA_ARRIVED:
if (encoder === null) {
logger.error('flacEncoderWorker received data when the encoder is'
+ 'not ready.');
console.error('flacEncoderWorker received data when the encoder is not ready.');
} else {
encoder.encode(e.data.buf);
}

View File

@@ -12,9 +12,15 @@ import {
isEnabled as isDropboxEnabled
} from '../../../dropbox';
import { RECORDING_TYPES } from '../../constants';
import { toggleRequestingSubtitles } from '../../../subtitles';
type Props = {
/**
* Requests subtitles when recording is turned on.
*/
_autoCaptionOnRecord: boolean,
/**
* The {@code JitsiConference} for the current conference.
*/
@@ -241,7 +247,7 @@ class AbstractStartRecordingDialog extends Component<Props, State> {
* @returns {boolean} - True (to note that the modal should be closed).
*/
_onSubmit() {
const { _conference, _isDropboxEnabled, _token } = this.props;
const { _autoCaptionOnRecord, _conference, _isDropboxEnabled, _token, dispatch } = this.props;
let appData;
const attributes = {};
@@ -276,6 +282,10 @@ class AbstractStartRecordingDialog extends Component<Props, State> {
appData
});
if (_autoCaptionOnRecord) {
dispatch(toggleRequestingSubtitles());
}
return true;
}
@@ -296,6 +306,7 @@ class AbstractStartRecordingDialog extends Component<Props, State> {
* @private
* @returns {{
* _appKey: string,
* _autoCaptionOnRecord: boolean,
* _conference: JitsiConference,
* _fileRecordingsServiceEnabled: boolean,
* _fileRecordingsServiceSharingEnabled: boolean,
@@ -305,6 +316,7 @@ class AbstractStartRecordingDialog extends Component<Props, State> {
*/
export function mapStateToProps(state: Object) {
const {
autoCaptionOnRecord = false,
fileRecordingsServiceEnabled = false,
fileRecordingsServiceSharingEnabled = false,
dropbox = {}
@@ -312,6 +324,7 @@ export function mapStateToProps(state: Object) {
return {
_appKey: dropbox.appKey,
_autoCaptionOnRecord: autoCaptionOnRecord,
_conference: state['features/base/conference'].conference,
_fileRecordingsServiceEnabled: fileRecordingsServiceEnabled,
_fileRecordingsServiceSharingEnabled: fileRecordingsServiceSharingEnabled,

View File

@@ -16,6 +16,9 @@ import { AppRegistry } from 'react-native';
import { App } from './features/app';
import { IncomingCallApp } from './features/mobile/incoming-call';
// It's crucial that the native loggers are created ASAP, not to lose any data.
import { _initLogging } from './features/base/logging/functions';
declare var __DEV__;
/**
@@ -51,6 +54,9 @@ class Root extends PureComponent<Props> {
}
}
// Initialize logging.
_initLogging();
// HORRIBLE HACK ALERT! React Native logs the initial props with `console.log`. Here we are quickly patching it
// to avoid logging potentially sensitive information.
if (!__DEV__) {

View File

@@ -1,6 +1,7 @@
/* global __dirname */
const process = require('process');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
/**
* The URL of the Jitsi Meet deployment to be proxy to in the context of
@@ -9,10 +10,24 @@ const process = require('process');
const devServerProxyTarget
= process.env.WEBPACK_DEV_SERVER_PROXY_TARGET || 'https://beta.meet.jit.si';
const analyzeBundle = process.argv.indexOf('--analyze-bundle') !== -1;
const minimize
= process.argv.indexOf('-p') !== -1
|| process.argv.indexOf('--optimize-minimize') !== -1;
/**
* Build a Performance configuration object for the given size.
* See: https://webpack.js.org/configuration/performance/
*/
function getPerformanceHints(size) {
return {
hints: minimize ? 'error' : false,
maxAssetSize: size,
maxEntrypointSize: size
};
}
// The base Webpack configuration to bundle the JavaScript artifacts of
// jitsi-meet such as app.bundle.js and external_api.js.
const config = {
@@ -123,6 +138,13 @@ const config = {
publicPath: '/libs/',
sourceMapFilename: `[name].${minimize ? 'min' : 'js'}.map`
},
plugins: [
analyzeBundle
&& new BundleAnalyzerPlugin({
analyzerMode: 'disabled',
generateStatsFile: true
})
].filter(Boolean),
resolve: {
alias: {
jquery: `jquery/dist/jquery${minimize ? '.min' : ''}.js`
@@ -143,27 +165,45 @@ const config = {
module.exports = [
Object.assign({}, config, {
entry: {
'app.bundle': './app.js',
'device_selection_popup_bundle':
'./react/features/settings/popup.js',
'alwaysontop':
'./react/features/always-on-top/index.js',
'dial_in_info_bundle': [
'./react/features/invite/components/dial-in-info-page'
],
'do_external_connect':
'./connection_optimization/do_external_connect.js',
'flacEncodeWorker':
'./react/features/local-recording/'
+ 'recording/flac/flacEncodeWorker.js',
'analytics-ga':
'./react/features/analytics/handlers/GoogleAnalyticsHandler.js'
}
'app.bundle': './app.js'
},
performance: getPerformanceHints(3 * 1024 * 1024)
}),
Object.assign({}, config, {
entry: {
'device_selection_popup_bundle': './react/features/settings/popup.js'
},
performance: getPerformanceHints(2.5 * 1024 * 1024)
}),
Object.assign({}, config, {
entry: {
'alwaysontop': './react/features/always-on-top/index.js'
},
performance: getPerformanceHints(400 * 1024)
}),
Object.assign({}, config, {
entry: {
'dial_in_info_bundle': './react/features/invite/components/dial-in-info-page'
},
performance: getPerformanceHints(500 * 1024)
}),
Object.assign({}, config, {
entry: {
'do_external_connect': './connection_optimization/do_external_connect.js'
},
performance: getPerformanceHints(5 * 1024)
}),
Object.assign({}, config, {
entry: {
'flacEncodeWorker': './react/features/local-recording/recording/flac/flacEncodeWorker.js'
},
performance: getPerformanceHints(5 * 1024)
}),
Object.assign({}, config, {
entry: {
'analytics-ga': './react/features/analytics/handlers/GoogleAnalyticsHandler.js'
},
performance: getPerformanceHints(5 * 1024)
}),
Object.assign({}, config, {
entry: {
@@ -172,11 +212,9 @@ module.exports = [
output: Object.assign({}, config.output, {
library: [ 'JitsiMeetJS', 'app', 'effects' ],
libraryTarget: 'window'
})
}),
performance: getPerformanceHints(1 * 1024 * 1024)
}),
// The Webpack configuration to bundle external_api.js (aka
// JitsiMeetExternalAPI).
Object.assign({}, config, {
entry: {
'external_api': './modules/API/external/index.js'
@@ -184,7 +222,8 @@ module.exports = [
output: Object.assign({}, config.output, {
library: 'JitsiMeetExternalAPI',
libraryTarget: 'umd'
})
}),
performance: getPerformanceHints(30 * 1024)
})
];