Compare commits

...

41 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
Leonard Kim
bc403adb46 feat(api): allow for explicit screenshare state toggling 2019-08-26 06:53:28 -07:00
Bettenbuk Zoltan
1941275f93 feat: mobile chat emojis 2019-08-26 15:37:58 +02:00
paweldomas
6ae9bbe0c5 feat: report analytics for the network connection
Will emit new 'network.info' action with the online/offline status and
extra details for native like the network type and
'isConnectionExpensive' flag.
2019-08-23 13:36:33 -05:00
Jip-Hop
2c70388a9e Get participant specific video element
* Get participant specific video element

We now have the ability to select the video element for specific participants. I'm tweaking the jitsi-meet-electron app for my use case. I need to open Always On Top windows for specific participants, so the current _getLargeVideo() wont suffice.

I made a post about this in the Developers section on the Jitsi Community Forum, but it got blocked by Akismet.

* Add dots at end of sentence.

* Fixed ESlint errors and add additional check for iframe.

* Use _myUserID instead of string.

* Return the local video by default if participantId is undefined.

* Fixed mistake in string template.
2019-08-23 08:35:10 -07:00
Saúl Ibarra Corretgé
e0815de2ad rn,welcome: fix accessing local participant
It need not always exist, since it's created asynchronousluy on app
initiualization. Make sure we are ready for it.

I've seen backtraces because of this.
2019-08-23 17:16:22 +02:00
Saúl Ibarra Corretgé
02e058370e logging: disable caller info globally 2019-08-23 17:11:29 +02:00
Saúl Ibarra Corretgé
8a7b795d37 deps: lib-jitsi-meet@latest 2019-08-23 17:11:29 +02:00
Saúl Ibarra Corretgé
d24ca796ad deps: jitsi-meet-logger@latest 2019-08-23 17:11:29 +02:00
Leonard Kim
af2c61fd96 fix(pinning): dynamically check auto-pin setting
Any overrides set on interfaceConfig are not
applied on module load. As such, call to get
the value of the auto pin setting, providing
time for the bootstrapping to set overrides.
Otherwise iframe api users cannot override
the setting.
2019-08-23 07:36:27 -07:00
Saúl Ibarra Corretgé
5a934c071a logging: use individual, names loggers
React Native doesn't define __filename nor __dirname so do it artisanally. In
addition, this helps with centralizing the configuration passed to loggers.
2019-08-23 10:57:38 +02:00
Saúl Ibarra Corretgé
bfe4237430 deps: update jitsi-meet-logger 2019-08-23 10:57:38 +02:00
205 changed files with 2604 additions and 689 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'
@@ -56,6 +57,7 @@ dependencies {
implementation project(':react-native-background-timer')
implementation project(':react-native-calendar-events')
implementation project(':react-native-community-async-storage')
implementation project(':react-native-community_netinfo')
implementation project(':react-native-immersive')
implementation project(':react-native-keep-awake')
implementation project(':react-native-linear-gradient')

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),
@@ -193,6 +195,7 @@ class ReactInstanceManagerHolder {
new com.oblador.vectoricons.VectorIconsPackage(),
new com.ocetnik.timer.BackgroundTimerPackage(),
new com.reactnativecommunity.asyncstorage.AsyncStoragePackage(),
new com.reactnativecommunity.netinfo.NetInfoPackage(),
new com.reactnativecommunity.webview.RNCWebViewPackage(),
new com.rnimmersive.RNImmersivePackage(),
new com.zmxv.RNSound.RNSoundPackage(),

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

@@ -7,6 +7,8 @@ include ':react-native-calendar-events'
project(':react-native-calendar-events').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-calendar-events/android')
include ':react-native-community-async-storage'
project(':react-native-community-async-storage').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/async-storage/android')
include ':react-native-community_netinfo'
project(':react-native-community_netinfo').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/netinfo/android')
include ':react-native-google-signin'
project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-google-signin/android')
include ':react-native-immersive'

View File

@@ -1457,7 +1457,9 @@ export default {
return this._switchToScreenSharing(options);
}
return this._untoggleScreenSharing();
return this._untoggleScreenSharing
? this._untoggleScreenSharing()
: Promise.resolve();
},
/**
@@ -2198,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

@@ -47,6 +47,7 @@ target 'JitsiMeet' do
pod 'react-native-background-timer', :path => '../node_modules/react-native-background-timer'
pod 'react-native-calendar-events', :path => '../node_modules/react-native-calendar-events'
pod 'react-native-keep-awake', :path => '../node_modules/react-native-keep-awake'
pod 'react-native-netinfo', :path => '../node_modules/@react-native-community/netinfo'
pod 'react-native-webview', :path => '../node_modules/react-native-webview'
pod 'react-native-webrtc', :path => '../node_modules/react-native-webrtc'
pod 'BVLinearGradient', :path => '../node_modules/react-native-linear-gradient'
@@ -60,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)
@@ -139,7 +142,9 @@ PODS:
- React
- react-native-keep-awake (4.0.0):
- React
- react-native-webrtc (1.69.2):
- react-native-netinfo (4.1.5):
- React
- react-native-webrtc (1.75.0):
- React
- react-native-webview (5.8.1):
- React
@@ -185,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)
@@ -203,6 +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-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`)
@@ -226,6 +233,7 @@ SPEC REPOS:
https://github.com/cocoapods/specs.git:
- Amplitude-iOS
- boost-for-react-native
- CocoaLumberjack
- Crashlytics
- Fabric
- Firebase
@@ -271,6 +279,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-calendar-events"
react-native-keep-awake:
:path: "../node_modules/react-native-keep-awake"
react-native-netinfo:
:path: "../node_modules/@react-native-community/netinfo"
react-native-webrtc:
:path: "../node_modules/react-native-webrtc"
react-native-webview:
@@ -312,6 +322,7 @@ SPEC CHECKSUMS:
Amplitude-iOS: 2ad4d7270c99186236c1272a3a9425463b1ae1a7
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
CocoaLumberjack: 2f44e60eb91c176d471fdba43b9e3eae6a721947
Crashlytics: 07fb167b1694128c1c9a5a5cc319b0e9c3ca0933
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
Fabric: f988e33c97f08930a413e08123064d2e5f68d655
@@ -340,7 +351,8 @@ SPEC CHECKSUMS:
react-native-background-timer: 0d34748e53a972507c66963490c775321a88f6f2
react-native-calendar-events: 2fe35a9294af05de0ed819d3a1b5dac048d2c010
react-native-keep-awake: eba3137546b10003361b37c761f6c429b59814ae
react-native-webrtc: 1415d2a54b2246dd85ba95eb3e4bf2b66533f951
react-native-netinfo: 8d8db463bcc5db66a8ac5c48a7d86beb3b92f61a
react-native-webrtc: c5e3d631179a933548a8e49bddbd8fad02586095
react-native-webview: a95842e3f351a6d2c8bc8bcc9eab689c7e7e5ad4
React-RCTActionSheet: b0f1ea83f4bf75fb966eae9bfc47b78c8d3efd90
React-RCTAnimation: 359ba1b5690b1e87cc173558a78e82d35919333e
@@ -359,6 +371,6 @@ SPEC CHECKSUMS:
RNWatch: 09738b339eceb66e4d80a2371633ca5fb380fa42
yoga: 312528f5bbbba37b4dcea5ef00e8b4033fdd9411
PODFILE CHECKSUM: 6b6e260b4be4e86f9d05c0d7dab40f60118bb355
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));
@@ -116,9 +125,19 @@ function initCommands() {
sendAnalytics(createApiEvent('chat.toggled'));
APP.UI.toggleChat();
},
'toggle-share-screen': () => {
/**
* Callback to invoke when the "toggle-share-screen" command is received.
*
* @param {Object} options - Additional details of how to perform
* the action. Note this parameter is undocumented and experimental.
* @param {boolean} options.enable - Whether trying to enable screen
* sharing or to turn it off.
* @returns {void}
*/
'toggle-share-screen': (options = {}) => {
sendAnalytics(createApiEvent('screen.sharing.toggled'));
toggleScreenSharing();
toggleScreenSharing(options.enable);
},
'toggle-tile-view': () => {
sendAnalytics(createApiEvent('tile-view.toggled'));
@@ -242,13 +261,17 @@ function shouldBeEnabled() {
/**
* Executes on toggle-share-screen command.
*
* @param {boolean} [enable] - Whether this toggle is to explicitly enable or
* disable screensharing. If not defined, the application will automatically
* attempt to toggle between enabled and disabled. This boolean is useful for
* explicitly setting desired screensharing state.
* @returns {void}
*/
function toggleScreenSharing() {
function toggleScreenSharing(enable) {
if (APP.conference.isDesktopSharingEnabled) {
// eslint-disable-next-line no-empty-function
APP.conference.toggleScreenSharing().catch(() => {});
APP.conference.toggleScreenSharing(enable).catch(() => {});
} else {
initialScreenSharingState = !initialScreenSharingState;
}

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',
@@ -366,6 +365,30 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
return iframe.contentWindow.document.getElementById('largeVideo');
}
/**
* Getter for participant specific video element in Jitsi Meet.
*
* @param {string|undefined} participantId - Id of participant to return the video for.
*
* @returns {HTMLElement|undefined} - The requested video. Will return the local video
* by default if participantId is undefined.
*/
_getParticipantVideo(participantId) {
const iframe = this.getIFrame();
if (!iframe
|| !iframe.contentWindow
|| !iframe.contentWindow.document) {
return;
}
if (typeof participantId === 'undefined' || participantId === this._myUserID) {
return iframe.contentWindow.document.getElementById('localVideo_container');
}
return iframe.contentWindow.document.querySelector(`#participant_${participantId} video`);
}
/**
* Sets the size of the iframe element.
*
@@ -593,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

330
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"
}
@@ -3055,6 +3055,11 @@
}
}
},
"@react-native-community/netinfo": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/@react-native-community/netinfo/-/netinfo-4.1.5.tgz",
"integrity": "sha512-lagdZr9UiVAccNXYfTEj+aUcPCx9ykbMe9puffeIyF3JsRuMmlu3BjHYx1klUHX7wNRmFNC8qVP0puxUt1sZ0A=="
},
"@segment/top-domain": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@segment/top-domain/-/top-domain-3.0.0.tgz",
@@ -3439,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",
@@ -4408,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",
@@ -4830,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",
@@ -6078,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",
@@ -6137,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",
@@ -7215,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",
@@ -8095,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",
@@ -8249,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",
@@ -8301,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"
}
@@ -8320,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",
@@ -8424,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",
@@ -9300,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",
@@ -9352,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",
@@ -9396,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",
@@ -9451,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"
}
@@ -10284,8 +10374,8 @@
"integrity": "sha512-+f/4OLeqY8RAmXnonI1ffeY1DR8kMNJPhv5WMFehchf7U71cjMQVKkOz1n6asz6kfVoAqKNWJz1A/18i18AcXA=="
},
"jitsi-meet-logger": {
"version": "github:jitsi/jitsi-meet-logger#6fff754a77a56ab52499f3559105a15886942a1e",
"from": "github:jitsi/jitsi-meet-logger#6fff754a77a56ab52499f3559105a15886942a1e"
"version": "github:jitsi/jitsi-meet-logger#a885cc98688ef2c3972284bda901596a26ffee52",
"from": "github:jitsi/jitsi-meet-logger#a885cc98688ef2c3972284bda901596a26ffee52"
},
"jquery": {
"version": "3.4.0",
@@ -10549,14 +10639,14 @@
}
},
"lib-jitsi-meet": {
"version": "github:jitsi/lib-jitsi-meet#503d47f3639cbd313489d2845d8dba96fc7b0ba5",
"from": "github:jitsi/lib-jitsi-meet#503d47f3639cbd313489d2845d8dba96fc7b0ba5",
"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#6fff754a77a56ab52499f3559105a15886942a1e",
"jitsi-meet-logger": "github:jitsi/jitsi-meet-logger#a885cc98688ef2c3972284bda901596a26ffee52",
"js-utils": "github:jitsi/js-utils#446497893023aa8dec403e0e4e35a22cae6bc87d",
"lodash.isequal": "4.5.0",
"sdp-transform": "2.3.0",
@@ -12027,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"
}
}
}
},
@@ -12280,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",
@@ -12341,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",
@@ -13761,9 +13936,9 @@
}
},
"react-emoji-render": {
"version": "0.4.6",
"resolved": "https://registry.npmjs.org/react-emoji-render/-/react-emoji-render-0.4.6.tgz",
"integrity": "sha512-ARB8E4j/dndQxC7Bn4b+Oymt7pqhh9GjP87NYcxC8KONejysnXD5O9KpnJeW/U3Ke3+XsWrWAr9K5riVA6emfg==",
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/react-emoji-render/-/react-emoji-render-1.0.0.tgz",
"integrity": "sha512-14iNQ1bOqijkIwfmuYMnG0lew2GJhRmSEPEYi7Dc3RDgklaXXwbLB0bmJF/0LUpDH1hy3I1H3EyrKb//FdwCmg==",
"requires": {
"classnames": "^2.2.5",
"emoji-regex": "^6.4.1",
@@ -14085,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",
@@ -14179,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",
@@ -14189,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=="
}
}
},
@@ -17014,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",
@@ -17334,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": {
@@ -17840,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

@@ -35,6 +35,7 @@
"@atlaskit/tooltip": "12.1.13",
"@microsoft/microsoft-graph-client": "1.1.0",
"@react-native-community/async-storage": "1.3.4",
"@react-native-community/netinfo": "4.1.5",
"@tensorflow-models/body-pix": "^1.0.1",
"@tensorflow/tfjs": "^1.1.2",
"@webcomponents/url": "0.7.1",
@@ -46,7 +47,7 @@
"i18next-browser-languagedetector": "3.0.1",
"i18next-xhr-backend": "3.0.0",
"jQuery-Impromptu": "github:trentrichardson/jQuery-Impromptu#v6.0.0",
"jitsi-meet-logger": "github:jitsi/jitsi-meet-logger#6fff754a77a56ab52499f3559105a15886942a1e",
"jitsi-meet-logger": "github:jitsi/jitsi-meet-logger#a885cc98688ef2c3972284bda901596a26ffee52",
"jquery": "3.4.0",
"jquery-contextmenu": "2.4.5",
"jquery-i18next": "1.2.1",
@@ -54,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#503d47f3639cbd313489d2845d8dba96fc7b0ba5",
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#486c61e2a91eeb3d9b6f179ea0c82044e321dccf",
"libflacjs": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d",
"lodash": "4.17.13",
"moment": "2.19.4",
@@ -62,12 +63,12 @@
"postis": "2.2.0",
"react": "16.8.6",
"react-dom": "16.8.6",
"react-emoji-render": "0.4.6",
"react-emoji-render": "1.0.0",
"react-i18next": "10.11.4",
"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",
@@ -77,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",
@@ -85,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"
@@ -122,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

@@ -6,7 +6,6 @@ import AbstractAudioMuteButton from '../base/toolbox/components/AbstractAudioMut
import type { Props } from '../base/toolbox/components/AbstractButton';
const { api } = window.alwaysOnTop;
const logger = require('jitsi-meet-logger').getLogger(__filename);
/**
* The type of the React {@code Component} state of {@link AudioMuteButton}.
@@ -71,7 +70,7 @@ export default class AudioMuteButton
audioAvailable,
audioMuted
}))
.catch(logger.error);
.catch(console.error);
}
/**

View File

@@ -6,7 +6,6 @@ import AbstractVideoMuteButton from '../base/toolbox/components/AbstractVideoMut
import type { Props } from '../base/toolbox/components/AbstractButton';
const { api } = window.alwaysOnTop;
const logger = require('jitsi-meet-logger').getLogger(__filename);
/**
* The type of the React {@code Component} state of {@link VideoMuteButton}.
@@ -71,7 +70,7 @@ export default class VideoMuteButton
videoAvailable,
videoMuted
}))
.catch(logger.error);
.catch(console.error);
}
/**

View File

@@ -271,6 +271,27 @@ export function createInviteDialogEvent(
};
}
/**
* Creates an event which reports about the current network information reported by the operating system.
*
* @param {boolean} isOnline - Tells whether or not the internet is reachable.
* @param {string} [networkType] - Network type, see {@code NetworkInfo} type defined by the 'base/net-info' feature.
* @param {Object} [details] - Extra info, see {@code NetworkInfo} type defined by the 'base/net-info' feature.
* @returns {Object}
*/
export function createNetworkInfoEvent({ isOnline, networkType, details }) {
const attributes = { isOnline };
// Do no include optional stuff or Amplitude handler will log warnings.
networkType && (attributes.networkType = networkType);
details && (attributes.details = details);
return {
action: 'network.info',
attributes
};
}
/**
* Creates an "offer/answer failure" event.
*

View File

@@ -7,8 +7,7 @@ import JitsiMeetJS, {
import { getJitsiMeetGlobalNS, loadScript } from '../base/util';
import { AmplitudeHandler } from './handlers';
const logger = require('jitsi-meet-logger').getLogger(__filename);
import logger from './logger';
/**
* Sends an event through the lib-jitsi-meet AnalyticsAdapter interface.
@@ -64,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,
@@ -77,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

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

View File

@@ -6,6 +6,7 @@ import {
SET_ROOM
} from '../base/conference';
import { SET_CONFIG } from '../base/config';
import { SET_NETWORK_INFO } from '../base/net-info';
import { MiddlewareRegistry } from '../base/redux';
import {
getLocalAudioTrack,
@@ -16,7 +17,7 @@ import {
} from '../base/tracks';
import { UPDATE_LOCAL_TRACKS_DURATION } from './actionTypes';
import { createLocalTracksDurationEvent } from './AnalyticsEvents';
import { createLocalTracksDurationEvent, createNetworkInfoEvent } from './AnalyticsEvents';
import { initAnalytics, resetAnalytics, sendAnalytics } from './functions';
/**
@@ -127,6 +128,14 @@ MiddlewareRegistry.register(store => next => action => {
});
break;
}
case SET_NETWORK_INFO:
sendAnalytics(
createNetworkInfoEvent({
isOnline: action.isOnline,
details: action.details,
networkType: action.networkType
}));
break;
case SET_ROOM: {
initAnalytics(store);
break;

View File

@@ -25,8 +25,7 @@ import {
getDefaultURL,
getName
} from './functions';
const logger = require('jitsi-meet-logger').getLogger(__filename);
import logger from './logger';
declare var APP: Object;

View File

@@ -27,13 +27,12 @@ import '../../mobile/proximity';
import '../../mobile/wake-lock';
import '../../mobile/watchos';
import logger from '../logger';
import { AbstractApp } from './AbstractApp';
import type { Props as AbstractAppProps } from './AbstractApp';
declare var __DEV__;
const logger = require('jitsi-meet-logger').getLogger(__filename);
/**
* The type of React {@code Component} props of {@link App}.
*/

View File

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

View File

@@ -16,8 +16,7 @@ import {
WAIT_FOR_OWNER
} from './actionTypes';
import { LoginDialog, WaitForOwnerDialog } from './components';
const logger = require('jitsi-meet-logger').getLogger(__filename);
import logger from './logger';
/**
* Initiates authenticating and upgrading the role of the local participant to

View File

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

View File

@@ -17,8 +17,7 @@ import { SoundCollection } from '../../sounds';
import { PersistenceRegistry } from '../../storage';
import { appWillMount, appWillUnmount } from '../actions';
const logger = require('jitsi-meet-logger').getLogger(__filename);
import logger from '../logger';
declare var APP: Object;

View File

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

View File

@@ -1,18 +1,15 @@
// @flow
import { getLogger } from 'jitsi-meet-logger';
import UIEvents from '../../../../service/UI/UIEvents';
import { createAudioOnlyChangedEvent, sendAnalytics } from '../../analytics';
import { SET_AUDIO_ONLY } from './actionTypes';
import logger from './logger';
import type { Dispatch } from 'redux';
declare var APP: Object;
const logger = getLogger('features/base/audio-only');
/**
* Sets the audio-only flag for the current JitsiConference.

View File

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

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

@@ -1,5 +1,7 @@
// @flow
import type { Dispatch } from 'redux';
import {
createStartMutedConfigurationEvent,
sendAnalytics
@@ -35,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,
@@ -58,9 +61,7 @@ import {
getCurrentConference,
sendLocalParticipant
} from './functions';
import type { Dispatch } from 'redux';
const logger = require('jitsi-meet-logger').getLogger(__filename);
import logger from './logger';
declare var APP: Object;
@@ -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

@@ -19,8 +19,7 @@ import {
JITSI_CONFERENCE_URL_KEY,
VIDEO_QUALITY_LEVELS
} from './constants';
const logger = require('jitsi-meet-logger').getLogger(__filename);
import logger from './logger';
/**
* Attach a set of local tracks to a conference.

View File

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

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';
@@ -41,8 +45,7 @@ import {
forEachConference,
getCurrentConference
} from './functions';
const logger = require('jitsi-meet-logger').getLogger(__filename);
import logger from './logger';
declare var APP: Object;
@@ -87,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);
@@ -187,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));
@@ -200,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;
}
@@ -437,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

@@ -4,6 +4,7 @@ import _ from 'lodash';
import { _CONFIG_STORE_PREFIX } from './constants';
import parseURLParams from './parseURLParams';
import logger from './logger';
declare var $: Object;
@@ -147,8 +148,6 @@ const WHITELISTED_KEYS = [
'webrtcIceUdpDisable'
];
const logger = require('jitsi-meet-logger').getLogger(__filename);
// XXX The functions getRoomName and parseURLParams are split out of
// functions.js because they are bundled in both app.bundle and
// do_external_connect, webpack 1 does not support tree shaking, and we don't

View File

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

View File

@@ -19,8 +19,7 @@ import {
SET_LOCATION_URL
} from './actionTypes';
import { JITSI_CONNECTION_URL_KEY } from './constants';
const logger = require('jitsi-meet-logger').getLogger(__filename);
import logger from './logger';
/**
* The error structure passed to the {@link connectionFailed} action.

View File

@@ -5,8 +5,6 @@ import type { Dispatch } from 'redux';
declare var APP: Object;
declare var config: Object;
const logger = require('jitsi-meet-logger').getLogger(__filename);
import { configureInitialDevices } from '../devices';
export {
@@ -14,6 +12,7 @@ export {
connectionFailed,
setLocationURL
} from './actions.native';
import logger from './logger';
/**
* Opens new connection.

View File

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

View File

@@ -20,8 +20,7 @@ import {
getDevicesFromURL,
setAudioOutputDeviceId
} from './functions';
const logger = require('jitsi-meet-logger').getLogger(__filename);
import logger from './logger';
/**
* Maps the WebRTC string for device type to the keys used to store configure,

View File

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

View File

@@ -21,8 +21,7 @@ import {
import { showNotification, showWarningNotification } from '../../notifications';
import { updateSettings } from '../settings';
import { setAudioOutputDeviceId } from './functions';
const logger = require('jitsi-meet-logger').getLogger(__filename);
import logger from './logger';
const JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP = {
microphone: {

View File

@@ -6,7 +6,7 @@ import React, { Component } from 'react';
import { StatelessDialog } from '../../../dialog';
import { translate } from '../../../i18n';
const logger = require('jitsi-meet-logger').getLogger(__filename);
import logger from '../../logger';
/**
* The type of the React {@code Component} props of {@link DialogWithTabs}.

View File

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

View File

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

View File

@@ -1,7 +1,5 @@
// @flow
import { getLogger } from 'jitsi-meet-logger';
import { SET_FILMSTRIP_ENABLED } from '../../filmstrip/actionTypes';
import { SELECT_LARGE_VIDEO_PARTICIPANT } from '../../large-video/actionTypes';
import { APP_STATE_CHANGED } from '../../mobile/background/actionTypes';
@@ -12,8 +10,9 @@ import { CONFERENCE_JOINED } from '../conference/actionTypes';
import { getParticipantById } from '../participants/functions';
import { MiddlewareRegistry } from '../redux';
import logger from './logger';
declare var APP: Object;
const logger = getLogger('features/base/lastn');
MiddlewareRegistry.register(store => next => action => {

View File

@@ -4,14 +4,13 @@ import { toState } from '../redux';
import { loadScript } from '../util';
import JitsiMeetJS from './_';
import logger from './logger';
declare var APP: Object;
const JitsiConferenceErrors = JitsiMeetJS.errors.conference;
const JitsiConnectionErrors = JitsiMeetJS.errors.connection;
const logger = require('jitsi-meet-logger').getLogger(__filename);
/**
* Creates a {@link JitsiLocalTrack} model from the given device id.
*

View File

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

View File

@@ -3,7 +3,7 @@
import { NativeModules } from 'react-native';
import { RTCPeerConnection, RTCSessionDescription } from 'react-native-webrtc';
const logger = require('jitsi-meet-logger').getLogger(__filename);
import logger from '../logger';
/* eslint-disable no-unused-vars */

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

@@ -0,0 +1,44 @@
// @flow
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
* almost always empty anyway.
*/
const DEFAULT_OPTS = {};
const DEFAULT_RN_OPTS = { disableCallerInfo: true };
/**
* Gets a logger for the given id.
*
* @param {string} id - Name for the logger.
* @returns {Object} - The logger object.
*/
export function getLogger(id: string) {
const opts = navigator.product === 'ReactNative' ? DEFAULT_RN_OPTS : DEFAULT_OPTS;
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);
});

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