mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-05-26 11:07:46 +00:00
Compare commits
50 Commits
4315
...
jibri-queu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7cb719be0 | ||
|
|
e6676bb09a | ||
|
|
8e9a51f742 | ||
|
|
004c1b65ad | ||
|
|
eabcc078ef | ||
|
|
5b1f852783 | ||
|
|
5cf9a76f9e | ||
|
|
3f33adc5d0 | ||
|
|
d9250aa986 | ||
|
|
5b10d8f5ef | ||
|
|
02885ea716 | ||
|
|
7e70a57eb3 | ||
|
|
dbaa1168b3 | ||
|
|
b1d691ca07 | ||
|
|
10a4612230 | ||
|
|
21767fa7cf | ||
|
|
0bd100f027 | ||
|
|
f14a595462 | ||
|
|
5e4b8c747c | ||
|
|
11ee71a51c | ||
|
|
c998d83f34 | ||
|
|
1a957ed85b | ||
|
|
1dbb47b84f | ||
|
|
4adaa6f1fd | ||
|
|
b3b561f27a | ||
|
|
a6a19a3002 | ||
|
|
1426a5b4bc | ||
|
|
858ee557d4 | ||
|
|
bd64c14aaa | ||
|
|
ce286f9be8 | ||
|
|
cc9cb6a874 | ||
|
|
168dbd6276 | ||
|
|
400c86ad5e | ||
|
|
b0650b8448 | ||
|
|
027cc1be96 | ||
|
|
9b32811ff2 | ||
|
|
a67d0fbf6c | ||
|
|
af5d4c850b | ||
|
|
7bfb2fc219 | ||
|
|
b814827df1 | ||
|
|
240b033e76 | ||
|
|
00b41dbb41 | ||
|
|
2689be5d24 | ||
|
|
f3da009d61 | ||
|
|
ddc2b4f26e | ||
|
|
b106e51a10 | ||
|
|
0cef706b6a | ||
|
|
b9c20a3fd4 | ||
|
|
23507da59a | ||
|
|
4bfc80ecb9 |
@@ -1,6 +1,7 @@
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.jitsi.meet">
|
||||
package="org.jitsi.meet"
|
||||
android:installLocation="auto">
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
|
||||
@@ -23,7 +23,6 @@ import android.content.IntentFilter;
|
||||
import android.content.RestrictionEntry;
|
||||
import android.content.RestrictionsManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
@@ -96,7 +95,7 @@ public class MainActivity extends JitsiMeetActivity {
|
||||
// In Debug builds React needs permission to write over other apps in
|
||||
// order to display the warning and error overlays.
|
||||
if (BuildConfig.DEBUG) {
|
||||
if (canRequestOverlayPermission() && !Settings.canDrawOverlays(this)) {
|
||||
if (!Settings.canDrawOverlays(this)) {
|
||||
Intent intent
|
||||
= new Intent(
|
||||
Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
|
||||
@@ -186,8 +185,7 @@ public class MainActivity extends JitsiMeetActivity {
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == OVERLAY_PERMISSION_REQUEST_CODE
|
||||
&& canRequestOverlayPermission()) {
|
||||
if (requestCode == OVERLAY_PERMISSION_REQUEST_CODE) {
|
||||
if (Settings.canDrawOverlays(this)) {
|
||||
initialize();
|
||||
return;
|
||||
@@ -210,6 +208,18 @@ public class MainActivity extends JitsiMeetActivity {
|
||||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
|
||||
super.onPictureInPictureModeChanged(isInPictureInPictureMode);
|
||||
|
||||
Log.d(TAG, "Is in picture-in-picture mode: " + isInPictureInPictureMode);
|
||||
|
||||
if (!isInPictureInPictureMode) {
|
||||
this.startActivity(new Intent(this, getClass())
|
||||
.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT));
|
||||
}
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
//
|
||||
|
||||
@@ -220,10 +230,4 @@ public class MainActivity extends JitsiMeetActivity {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canRequestOverlayPermission() {
|
||||
return
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
||||
&& getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.M;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,10 +142,10 @@ allprojects {
|
||||
}
|
||||
|
||||
ext {
|
||||
buildToolsVersion = "28.0.3"
|
||||
compileSdkVersion = 28
|
||||
minSdkVersion = 21
|
||||
targetSdkVersion = 28
|
||||
buildToolsVersion = "29.0.3"
|
||||
compileSdkVersion = 29
|
||||
minSdkVersion = 23
|
||||
targetSdkVersion = 29
|
||||
supportLibVersion = "28.0.0"
|
||||
|
||||
// The Maven artifact groupdId of the third-party react-native modules which
|
||||
|
||||
5
android/scripts/run-packager-helper.command
Executable file
5
android/scripts/run-packager-helper.command
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
THIS_DIR=$(cd -P "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOURCE[0]}")")" && pwd)
|
||||
|
||||
exec ${THIS_DIR}/../../node_modules/react-native/scripts/launchPackager.command --reset-cache
|
||||
@@ -8,7 +8,7 @@ THIS_DIR=$(cd -P "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOUR
|
||||
export RCT_METRO_PORT="${RCT_METRO_PORT:=8081}"
|
||||
echo "export RCT_METRO_PORT=${RCT_METRO_PORT}" > "${THIS_DIR}/../../node_modules/react-native/scripts/.packager.env"
|
||||
|
||||
adb reverse tcp:8081 tcp:8081
|
||||
adb reverse tcp:$RCT_METRO_PORT tcp:$RCT_METRO_PORT
|
||||
|
||||
if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then
|
||||
if ! curl -s "http://localhost:${RCT_METRO_PORT}/status" | grep -q "packager-status:running" ; then
|
||||
@@ -16,11 +16,10 @@ if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then
|
||||
exit 2
|
||||
fi
|
||||
else
|
||||
CMD="${THIS_DIR}/../../node_modules/react-native/scripts/launchPackager.command"
|
||||
CMD="$THIS_DIR/run-packager-helper.command"
|
||||
if [[ `uname` == "Darwin" ]]; then
|
||||
open -g "${CMD}" || echo "Can't start packager automatically"
|
||||
else
|
||||
xdg-open "${CMD}" || echo "Can't start packager automatically"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -16,11 +16,8 @@
|
||||
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.AudioDeviceInfo;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@@ -34,7 +31,6 @@ import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
* default it's only used on versions < O, since versions >= O use ConnectionService, but it
|
||||
* can be disabled.
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.M)
|
||||
class AudioDeviceHandlerGeneric implements
|
||||
AudioModeModule.AudioDeviceHandlerInterface,
|
||||
AudioManager.OnAudioFocusChangeListener {
|
||||
|
||||
@@ -1,230 +0,0 @@
|
||||
/*
|
||||
* Copyright @ 2017-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 android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.AudioManager;
|
||||
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
|
||||
/**
|
||||
* {@link AudioModeModule.AudioDeviceHandlerInterface} module implementing device handling for
|
||||
* legacy (pre-M) Android versions.
|
||||
*/
|
||||
class AudioDeviceHandlerLegacy implements
|
||||
AudioModeModule.AudioDeviceHandlerInterface,
|
||||
AudioManager.OnAudioFocusChangeListener,
|
||||
BluetoothHeadsetMonitor.Listener {
|
||||
|
||||
private final static String TAG = AudioDeviceHandlerLegacy.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Reference to the main {@code AudioModeModule}.
|
||||
*/
|
||||
private AudioModeModule module;
|
||||
|
||||
/**
|
||||
* Indicator that we have lost audio focus.
|
||||
*/
|
||||
private boolean audioFocusLost = false;
|
||||
|
||||
/**
|
||||
* {@link AudioManager} instance used to interact with the Android audio
|
||||
* subsystem.
|
||||
*/
|
||||
private AudioManager audioManager;
|
||||
|
||||
/**
|
||||
* {@link BluetoothHeadsetMonitor} for detecting Bluetooth device changes in
|
||||
* old (< M) Android versions.
|
||||
*/
|
||||
private BluetoothHeadsetMonitor bluetoothHeadsetMonitor;
|
||||
|
||||
public AudioDeviceHandlerLegacy(AudioManager audioManager) {
|
||||
this.audioManager = audioManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to trigger an audio route update when Bluetooth devices are
|
||||
* connected / disconnected.
|
||||
*/
|
||||
@Override
|
||||
public void onBluetoothDeviceChange(final boolean deviceAvailable) {
|
||||
module.runInAudioThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (deviceAvailable) {
|
||||
module.addDevice(AudioModeModule.DEVICE_BLUETOOTH);
|
||||
} else {
|
||||
module.removeDevice(AudioModeModule.DEVICE_BLUETOOTH);
|
||||
}
|
||||
|
||||
module.updateAudioRoute();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to trigger an audio route update when a headset is plugged
|
||||
* or unplugged.
|
||||
*/
|
||||
private void onHeadsetDeviceChange() {
|
||||
module.runInAudioThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// XXX: isWiredHeadsetOn is not deprecated when used just for
|
||||
// knowing if there is a wired headset connected, regardless of
|
||||
// audio being routed to it.
|
||||
//noinspection deprecation
|
||||
if (audioManager.isWiredHeadsetOn()) {
|
||||
module.addDevice(AudioModeModule.DEVICE_HEADPHONES);
|
||||
} else {
|
||||
module.removeDevice(AudioModeModule.DEVICE_HEADPHONES);
|
||||
}
|
||||
|
||||
module.updateAudioRoute();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link AudioManager.OnAudioFocusChangeListener} interface method. Called
|
||||
* when the audio focus of the system is updated.
|
||||
*
|
||||
* @param focusChange - The type of focus change.
|
||||
*/
|
||||
@Override
|
||||
public void onAudioFocusChange(final int focusChange) {
|
||||
module.runInAudioThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
switch (focusChange) {
|
||||
case AudioManager.AUDIOFOCUS_GAIN: {
|
||||
JitsiMeetLogger.d(TAG + " Audio focus gained");
|
||||
// Some other application potentially stole our audio focus
|
||||
// temporarily. Restore our mode.
|
||||
if (audioFocusLost) {
|
||||
module.updateAudioRoute();
|
||||
}
|
||||
audioFocusLost = false;
|
||||
break;
|
||||
}
|
||||
case AudioManager.AUDIOFOCUS_LOSS:
|
||||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
|
||||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: {
|
||||
JitsiMeetLogger.d(TAG + " Audio focus lost");
|
||||
audioFocusLost = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to set the output route to a Bluetooth device.
|
||||
*
|
||||
* @param enabled true if Bluetooth should use used, false otherwise.
|
||||
*/
|
||||
private void setBluetoothAudioRoute(boolean enabled) {
|
||||
if (enabled) {
|
||||
audioManager.startBluetoothSco();
|
||||
audioManager.setBluetoothScoOn(true);
|
||||
} else {
|
||||
audioManager.setBluetoothScoOn(false);
|
||||
audioManager.stopBluetoothSco();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(AudioModeModule audioModeModule) {
|
||||
JitsiMeetLogger.i("Using " + TAG + " as the audio device handler");
|
||||
|
||||
module = audioModeModule;
|
||||
Context context = module.getContext();
|
||||
|
||||
// Setup runtime device change detection.
|
||||
//
|
||||
|
||||
// Detect changes in wired headset connections.
|
||||
IntentFilter wiredHeadSetFilter = new IntentFilter(AudioManager.ACTION_HEADSET_PLUG);
|
||||
BroadcastReceiver wiredHeadsetReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
JitsiMeetLogger.d(TAG + " Wired headset added / removed");
|
||||
onHeadsetDeviceChange();
|
||||
}
|
||||
};
|
||||
context.registerReceiver(wiredHeadsetReceiver, wiredHeadSetFilter);
|
||||
|
||||
// Detect Bluetooth device changes.
|
||||
bluetoothHeadsetMonitor = new BluetoothHeadsetMonitor(context, this);
|
||||
|
||||
// On Android < M, detect if we have an earpiece.
|
||||
PackageManager pm = context.getPackageManager();
|
||||
if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
|
||||
module.addDevice(AudioModeModule.DEVICE_EARPIECE);
|
||||
}
|
||||
|
||||
// Always assume there is a speaker.
|
||||
module.addDevice(AudioModeModule.DEVICE_SPEAKER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
bluetoothHeadsetMonitor.stop();
|
||||
bluetoothHeadsetMonitor = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAudioRoute(String device) {
|
||||
// Turn speaker on / off
|
||||
audioManager.setSpeakerphoneOn(device.equals(AudioModeModule.DEVICE_SPEAKER));
|
||||
|
||||
// Turn bluetooth on / off
|
||||
setBluetoothAudioRoute(device.equals(AudioModeModule.DEVICE_BLUETOOTH));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setMode(int mode) {
|
||||
if (mode == AudioModeModule.DEFAULT) {
|
||||
audioFocusLost = false;
|
||||
audioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
audioManager.abandonAudioFocus(this);
|
||||
audioManager.setSpeakerphoneOn(false);
|
||||
setBluetoothAudioRoute(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
|
||||
audioManager.setMicrophoneMute(false);
|
||||
|
||||
if (audioManager.requestAudioFocus(this, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN)
|
||||
== AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
|
||||
JitsiMeetLogger.w(TAG + " Audio focus request failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -222,10 +222,8 @@ class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
|
||||
if (useConnectionService()) {
|
||||
audioDeviceHandler = new AudioDeviceHandlerConnectionService(audioManager);
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
audioDeviceHandler = new AudioDeviceHandlerGeneric(audioManager);
|
||||
} else {
|
||||
audioDeviceHandler = new AudioDeviceHandlerLegacy(audioManager);
|
||||
audioDeviceHandler = new AudioDeviceHandlerGeneric(audioManager);
|
||||
}
|
||||
|
||||
audioDeviceHandler.start(this);
|
||||
@@ -427,15 +425,6 @@ class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Needed on the legacy handler...
|
||||
*
|
||||
* @return Context for the application.
|
||||
*/
|
||||
Context getContext() {
|
||||
return getReactApplicationContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for the modules implementing the actual audio device management.
|
||||
*/
|
||||
|
||||
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* Copyright @ 2017-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 android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothHeadset;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.media.AudioManager;
|
||||
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
/**
|
||||
* Helper class to detect and handle Bluetooth device changes. It monitors
|
||||
* Bluetooth headsets being connected / disconnected and notifies the module
|
||||
* about device changes when this occurs.
|
||||
*/
|
||||
class BluetoothHeadsetMonitor {
|
||||
private final static String TAG = BluetoothHeadsetMonitor.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* The {@link Context} in which this module executes.
|
||||
*/
|
||||
private final Context context;
|
||||
|
||||
/**
|
||||
* Reference to the {@link BluetoothAdapter} object, used to access Bluetooth functionality.
|
||||
*/
|
||||
private BluetoothAdapter adapter;
|
||||
|
||||
/**
|
||||
* Reference to a proxy object which allows us to query connected devices.
|
||||
*/
|
||||
private BluetoothHeadset headset;
|
||||
|
||||
/**
|
||||
* receiver registered for receiving Bluetooth connection state changes.
|
||||
*/
|
||||
private BroadcastReceiver receiver;
|
||||
|
||||
/**
|
||||
* Listener for receiving Bluetooth device change events.
|
||||
*/
|
||||
private Listener listener;
|
||||
|
||||
public BluetoothHeadsetMonitor(Context context, Listener listener) {
|
||||
this.context = context;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
private boolean getBluetoothHeadsetProfileProxy() {
|
||||
adapter = BluetoothAdapter.getDefaultAdapter();
|
||||
|
||||
if (adapter == null) {
|
||||
JitsiMeetLogger.w(TAG + " Device doesn't support Bluetooth");
|
||||
return false;
|
||||
}
|
||||
|
||||
// XXX: The profile listener listens for system services of the given
|
||||
// type being available to the application. That is, if our Bluetooth
|
||||
// adapter has the "headset" profile.
|
||||
BluetoothProfile.ServiceListener listener
|
||||
= new BluetoothProfile.ServiceListener() {
|
||||
@Override
|
||||
public void onServiceConnected(int profile, BluetoothProfile proxy) {
|
||||
if (profile == BluetoothProfile.HEADSET) {
|
||||
headset = (BluetoothHeadset) proxy;
|
||||
updateDevices();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(int profile) {
|
||||
// The logic is the same as the logic of onServiceConnected.
|
||||
onServiceConnected(profile, /* proxy */ null);
|
||||
}
|
||||
};
|
||||
|
||||
return adapter.getProfileProxy(context, listener, BluetoothProfile.HEADSET);
|
||||
}
|
||||
|
||||
private void onBluetoothReceiverReceive(Context context, Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
|
||||
if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
|
||||
// XXX: This action will be fired when a Bluetooth headset is
|
||||
// connected or disconnected to the system. This is not related to
|
||||
// audio routing.
|
||||
int state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, -99);
|
||||
|
||||
switch (state) {
|
||||
case BluetoothHeadset.STATE_CONNECTED:
|
||||
case BluetoothHeadset.STATE_DISCONNECTED:
|
||||
JitsiMeetLogger.d(TAG + " BT headset connection state changed: " + state);
|
||||
updateDevices();
|
||||
break;
|
||||
}
|
||||
} else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)) {
|
||||
// XXX: This action will be fired when the connection established
|
||||
// with a Bluetooth headset (called a SCO connection) changes state.
|
||||
// When the SCO connection is active we route audio to it.
|
||||
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -99);
|
||||
|
||||
switch (state) {
|
||||
case AudioManager.SCO_AUDIO_STATE_CONNECTED:
|
||||
case AudioManager.SCO_AUDIO_STATE_DISCONNECTED:
|
||||
JitsiMeetLogger.d(TAG + " BT SCO connection state changed: " + state);
|
||||
updateDevices();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void registerBluetoothReceiver() {
|
||||
receiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
onBluetoothReceiverReceive(context, intent);
|
||||
}
|
||||
};
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
|
||||
filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
|
||||
|
||||
context.registerReceiver(receiver, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects if there are new devices connected / disconnected and fires the
|
||||
* {@link Listener} registered event.
|
||||
*/
|
||||
private void updateDevices() {
|
||||
boolean headsetAvailable = (headset != null) && !headset.getConnectedDevices().isEmpty();
|
||||
listener.onBluetoothDeviceChange(headsetAvailable);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
||||
|
||||
if (!audioManager.isBluetoothScoAvailableOffCall()) {
|
||||
JitsiMeetLogger.w(TAG + " Bluetooth SCO is not available");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!getBluetoothHeadsetProfileProxy()) {
|
||||
JitsiMeetLogger.w(TAG + " Couldn't get BT profile proxy");
|
||||
return;
|
||||
}
|
||||
|
||||
registerBluetoothReceiver();
|
||||
|
||||
// Initial detection.
|
||||
updateDevices();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (receiver != null) {
|
||||
context.unregisterReceiver(receiver);
|
||||
}
|
||||
|
||||
if (adapter != null && headset != null) {
|
||||
adapter.closeProfileProxy(BluetoothProfile.HEADSET, headset);
|
||||
}
|
||||
|
||||
receiver = null;
|
||||
headset = null;
|
||||
adapter = null;
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
void onBluetoothDeviceChange(boolean deviceAvailable);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright @ 2019-present 8x8, Inc.
|
||||
* Copyright @ 2018 Atlassian Pty Ltd
|
||||
* Copyright @ 2018-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.
|
||||
@@ -17,10 +16,8 @@
|
||||
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
import com.facebook.react.bridge.Callback;
|
||||
@@ -178,7 +175,6 @@ public class JitsiMeetActivityDelegate {
|
||||
};
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
public static void requestPermissions(Activity activity, String[] permissions, int requestCode, PermissionListener listener) {
|
||||
permissionListener = listener;
|
||||
activity.requestPermissions(permissions, requestCode);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright @ 2017-present Atlassian Pty Ltd
|
||||
* Copyright @ 2017-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.
|
||||
@@ -33,21 +33,10 @@ import com.facebook.react.module.annotations.ReactModule;
|
||||
* is used with the conference audio-only mode.
|
||||
*/
|
||||
@ReactModule(name = ProximityModule.NAME)
|
||||
class ProximityModule
|
||||
extends ReactContextBaseJavaModule {
|
||||
class ProximityModule extends ReactContextBaseJavaModule {
|
||||
|
||||
public static final String NAME = "Proximity";
|
||||
|
||||
/**
|
||||
* This type of wake lock (the one activated by the proximity sensor) has
|
||||
* been available for a while, but the constant was only exported in API
|
||||
* level 21 (Android Marshmallow) so make no assumptions and use its value
|
||||
* directly.
|
||||
*
|
||||
* TODO: Remove when we bump the API level to 21.
|
||||
*/
|
||||
private static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32;
|
||||
|
||||
/**
|
||||
* {@link WakeLock} instance.
|
||||
*/
|
||||
@@ -71,7 +60,7 @@ class ProximityModule
|
||||
try {
|
||||
wakeLock
|
||||
= powerManager.newWakeLock(
|
||||
PROXIMITY_SCREEN_OFF_WAKE_LOCK,
|
||||
PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK,
|
||||
"jitsi:"+NAME);
|
||||
} catch (Throwable ignored) {
|
||||
wakeLock = null;
|
||||
|
||||
@@ -1588,10 +1588,6 @@ export default {
|
||||
if (didHaveVideo) {
|
||||
promise = promise.then(() => createLocalTracksF({ devices: [ 'video' ] }))
|
||||
.then(([ stream ]) => this.useVideoStream(stream))
|
||||
.then(() => {
|
||||
sendAnalytics(createScreenSharingEvent('stopped'));
|
||||
logger.log('Screen sharing stopped.');
|
||||
})
|
||||
.catch(error => {
|
||||
logger.error('failed to switch back to local video', error);
|
||||
|
||||
@@ -1608,6 +1604,8 @@ export default {
|
||||
return promise.then(
|
||||
() => {
|
||||
this.videoSwitchInProgress = false;
|
||||
sendAnalytics(createScreenSharingEvent('stopped'));
|
||||
logger.info('Screen sharing stopped.');
|
||||
},
|
||||
error => {
|
||||
this.videoSwitchInProgress = false;
|
||||
|
||||
35
config.js
35
config.js
@@ -123,6 +123,10 @@ var config = {
|
||||
// Sets the preferred resolution (height) for local video. Defaults to 720.
|
||||
// resolution: 720,
|
||||
|
||||
// How many participants while in the tile view mode, before the receiving video quality is reduced from HD to SD.
|
||||
// Use -1 to disable.
|
||||
// maxFullResolutionParticipants: 2
|
||||
|
||||
// w3c spec-compliant video constraints to use for video capture. Currently
|
||||
// used by browsers that return true from lib-jitsi-meet's
|
||||
// util#browser#usesNewGumFlow. The constraints are independent from
|
||||
@@ -212,6 +216,37 @@ var config = {
|
||||
// Default value for the channel "last N" attribute. -1 for unlimited.
|
||||
channelLastN: -1,
|
||||
|
||||
// Provides a way to use different "last N" values based on the number of participants in the conference.
|
||||
// The keys in an Object represent number of participants and the values are "last N" to be used when number of
|
||||
// participants gets to or above the number.
|
||||
//
|
||||
// For the given example mapping, "last N" will be set to 20 as long as there are at least 5, but less than
|
||||
// 29 participants in the call and it will be lowered to 15 when the 30th participant joins. The 'channelLastN'
|
||||
// will be used as default until the first threshold is reached.
|
||||
//
|
||||
// lastNLimits: {
|
||||
// 5: 20,
|
||||
// 30: 15,
|
||||
// 50: 10,
|
||||
// 70: 5,
|
||||
// 90: 2
|
||||
// },
|
||||
|
||||
// Specify the settings for video quality optimizations on the client.
|
||||
// videoQuality: {
|
||||
//
|
||||
// // Provides a way to configure the maximum bitrates that will be enforced on the simulcast streams for
|
||||
// // video tracks. The keys in the object represent the type of the stream (LD, SD or HD) and the values
|
||||
// // are the max.bitrates to be set on that particular type of stream. The actual send may vary based on
|
||||
// // the available bandwidth calculated by the browser, but it will be capped by the values specified here.
|
||||
// // This is currently not implemented on app based clients on mobile.
|
||||
// maxBitratesVideo: {
|
||||
// low: 200000,
|
||||
// standard: 500000,
|
||||
// high: 1500000
|
||||
// }
|
||||
// },
|
||||
|
||||
// // Options for the recording limit notification.
|
||||
// recordingLimit: {
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Move the @atlaskit/flag container up a little bit so it does not cover the
|
||||
* toolbar with the first notification.
|
||||
*/
|
||||
.cjMOOK{
|
||||
.jIMojv{
|
||||
bottom: calc(#{$newToolbarSizeWithPadding}) !important;
|
||||
}
|
||||
|
||||
|
||||
74
css/_notifications.scss
Normal file
74
css/_notifications.scss
Normal file
@@ -0,0 +1,74 @@
|
||||
@include keyframes(exiting) {
|
||||
from {
|
||||
opacity: 1;
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translate(-200px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.notificationsContainer {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
flex-direction: column;
|
||||
width: 400px;
|
||||
left: 80px;
|
||||
|
||||
.topContainer {
|
||||
padding-bottom: 16px;
|
||||
// transition: height 0.4s ease-in-out;
|
||||
|
||||
.notification {
|
||||
width: 400px;
|
||||
z-index: 5;
|
||||
|
||||
&:nth-child(n+2) {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
&.exiting {
|
||||
animation-name: exiting;
|
||||
animation-duration: 0.4s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottomContainer {
|
||||
margin-bottom: 64px;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
|
||||
.notification {
|
||||
width: 400px;
|
||||
bottom: 0px;
|
||||
|
||||
&:nth-child(1) {
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
&:nth-child(n+2) {
|
||||
transition: transform 0.4s ease-in-out;
|
||||
z-index: 4;
|
||||
position: absolute;
|
||||
transform: translateY(100%) translateY(16px);
|
||||
}
|
||||
|
||||
|
||||
&:nth-child(n+4) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.exiting {
|
||||
animation-name: exiting;
|
||||
animation-duration: 0.4s;
|
||||
}
|
||||
|
||||
&.exiting+.notification {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,3 +115,19 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.jibri-queue-info {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
|
||||
.footer {
|
||||
background: #a4b8a4D1;
|
||||
border-radius: 3px;
|
||||
font-weight: bold;
|
||||
color: #5e6d7a;
|
||||
padding: 5px;
|
||||
margin-right: 30px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
70
css/_responsive.scss
Normal file
70
css/_responsive.scss
Normal file
@@ -0,0 +1,70 @@
|
||||
@media only screen and (max-width: $smallScreen) {
|
||||
.watermark {
|
||||
width: 20%;
|
||||
height: 20%;
|
||||
}
|
||||
|
||||
.new-toolbox {
|
||||
.toolbox-content {
|
||||
.button-group-center, .button-group-left, .button-group-right {
|
||||
.toolbox-button {
|
||||
.toolbox-icon {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
svg {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
.toolbox-icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: $verySmallScreen) {
|
||||
#videoResolutionLabel {
|
||||
display: none;
|
||||
}
|
||||
.desktop-browser {
|
||||
.vertical-filmstrip .filmstrip {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.new-toolbox {
|
||||
.toolbox-content {
|
||||
.button-group-center, .button-group-left, .button-group-right {
|
||||
.settings-button-small-icon {
|
||||
display: none;
|
||||
}
|
||||
.toolbox-button {
|
||||
.toolbox-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
svg {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
.toolbox-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.chrome-extension-banner {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -164,6 +164,9 @@ $unsupportedDesktopBrowserTextFontSize: 21px;
|
||||
$watermarkWidth: 186px;
|
||||
$watermarkHeight: 74px;
|
||||
|
||||
$welcomePageWatermarkWidth: 186px;
|
||||
$welcomePageWatermarkHeight: 74px;
|
||||
|
||||
/**
|
||||
* Welcome page variables.
|
||||
*/
|
||||
@@ -178,9 +181,12 @@ $welcomePageHeaderBackgroundPosition: none;
|
||||
$welcomePageHeaderBackgroundRepeat: none;
|
||||
$welcomePageHeaderBackgroundSize: none;
|
||||
$welcomePageHeaderPaddingBottom: 0px;
|
||||
$welcomePageHeaderMinHeight: fit-content;
|
||||
|
||||
$welcomePageHeaderTextMarginTop: 35px;
|
||||
$welcomePageHeaderTextMarginBottom: 35px;
|
||||
$welcomePageHeaderTextDisplay: flex;
|
||||
$welcomePageHeaderTextWidth: 650px;
|
||||
|
||||
$welcomePageHeaderTextTitleMarginBottom: 16px;
|
||||
$welcomePageHeaderTextTitleFontSize: 2.5rem;
|
||||
@@ -195,6 +201,7 @@ $welcomePageHeaderTextDescriptionLineHeight: 24px;
|
||||
$welcomePageHeaderTextDescriptionMarginBottom: 20px;
|
||||
$welcomePageHeaderTextDescriptionAlignSelf: inherit;
|
||||
|
||||
$welcomePageEnterRoomDisplay: flex;
|
||||
$welcomePageEnterRoomWidth: 680px;
|
||||
$welcomePageEnterRoomPadding: 25px 30px;
|
||||
$welcomePageEnterRoomBorderRadius: 0px;
|
||||
@@ -269,3 +276,9 @@ $chromeExtensionBannerTop: 80px;
|
||||
$chromeExtensionBannerRight: 16px;
|
||||
$chromeExtensionBannerTopInMeeting: 10px;
|
||||
$chromeExtensionBannerRightInMeeeting: 10px;
|
||||
|
||||
/**
|
||||
* media type thresholds
|
||||
*/
|
||||
$smallScreen: 700px;
|
||||
$verySmallScreen: 500px;
|
||||
|
||||
@@ -21,18 +21,18 @@ body.welcome-page {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: fit-content;
|
||||
min-height: $welcomePageHeaderMinHeight;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
|
||||
.header-text {
|
||||
display: flex;
|
||||
display: $welcomePageHeaderTextDisplay;
|
||||
flex-direction: column;
|
||||
margin-top: $watermarkHeight + $welcomePageHeaderTextMarginTop;
|
||||
margin-bottom: $welcomePageHeaderTextMarginBottom;
|
||||
max-width: calc(100% - 40px);
|
||||
width: 650px;
|
||||
width: $welcomePageHeaderTextWidth;
|
||||
z-index: $zindex2;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ body.welcome-page {
|
||||
}
|
||||
|
||||
#enter_room {
|
||||
display: flex;
|
||||
display: $welcomePageEnterRoomDisplay;
|
||||
align-items: center;
|
||||
max-width: calc(100% - 40px);
|
||||
width: $welcomePageEnterRoomWidth;
|
||||
@@ -211,5 +211,10 @@ body.welcome-page {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.watermark.leftwatermark {
|
||||
width: $welcomePageWatermarkWidth;
|
||||
height: $welcomePageWatermarkHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,5 +101,7 @@ $flagsImagePath: "../images/";
|
||||
@import 'modals/security/security';
|
||||
@import 'premeeting-screens';
|
||||
@import 'e2ee';
|
||||
@import 'responsive';
|
||||
@import 'notifications';
|
||||
|
||||
/* Modules END */
|
||||
|
||||
@@ -48,6 +48,7 @@ var interfaceConfig = {
|
||||
DEFAULT_LOCAL_DISPLAY_NAME: 'me',
|
||||
DEFAULT_LOGO_URL: 'images/watermark.png',
|
||||
DEFAULT_REMOTE_DISPLAY_NAME: 'Fellow Jitster',
|
||||
DEFAULT_WELCOME_PAGE_LOGO_URL: 'images/watermark.png',
|
||||
|
||||
DISABLE_DOMINANT_SPEAKER_INDICATOR: false,
|
||||
|
||||
@@ -101,6 +102,11 @@ var interfaceConfig = {
|
||||
|
||||
GENERATE_ROOMNAMES_ON_WELCOME_PAGE: true,
|
||||
|
||||
/**
|
||||
* Hide the logo on the deep linking pages.
|
||||
*/
|
||||
HIDE_DEEP_LINKING_LOGO: false,
|
||||
|
||||
/**
|
||||
* Hide the invite prompt in the header when alone in the meeting.
|
||||
*/
|
||||
|
||||
5
ios/scripts/run-packager-helper.command
Executable file
5
ios/scripts/run-packager-helper.command
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
THIS_DIR=$(cd -P "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOURCE[0]}")")" && pwd)
|
||||
|
||||
exec ${THIS_DIR}/../../node_modules/react-native/scripts/launchPackager.command --reset-cache
|
||||
@@ -3,6 +3,8 @@
|
||||
# This script is executed from Xcode to start the React packager for Debug
|
||||
# targets.
|
||||
|
||||
THIS_DIR=$(cd -P "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOURCE[0]}")")" && pwd)
|
||||
|
||||
export RCT_METRO_PORT="${RCT_METRO_PORT:=8081}"
|
||||
echo "export RCT_METRO_PORT=${RCT_METRO_PORT}" > "${SRCROOT}/../../node_modules/react-native/scripts/.packager.env"
|
||||
|
||||
@@ -13,7 +15,6 @@ if [[ "$CONFIGURATION" = "Debug" ]]; then
|
||||
exit 2
|
||||
fi
|
||||
else
|
||||
open -g "$SRCROOT/../../node_modules/react-native/scripts/launchPackager.command" || echo "Can't start packager automatically"
|
||||
open -g "$THIS_DIR/run-packager-helper.command" || echo "Can't start packager automatically"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
9
jest.config.js
Normal file
9
jest.config.js
Normal file
@@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
moduleFileExtensions: [
|
||||
'js'
|
||||
],
|
||||
testMatch: [
|
||||
'<rootDir>/react/**/?(*.)+(test)?(.web).js?(x)'
|
||||
],
|
||||
verbose: true
|
||||
};
|
||||
@@ -25,6 +25,7 @@
|
||||
"id": "Indonesian",
|
||||
"it": "Italian",
|
||||
"ja": "Japanese",
|
||||
"kab": "Kabyle",
|
||||
"ko": "Korean",
|
||||
"lt": "Lithuanian",
|
||||
"nl": "Dutch",
|
||||
|
||||
@@ -534,7 +534,7 @@
|
||||
"selectCamera": "Kamera",
|
||||
"selectMic": "Mikrofon",
|
||||
"startAudioMuted": "Při připojení všem zlumit zvuk",
|
||||
"startVideoMuted": "Všechny připojovat jako skrýté",
|
||||
"startVideoMuted": "Všechny připojovat jako skryté",
|
||||
"title": "Nastavení",
|
||||
"speakers": "Reproduktory",
|
||||
"microphones": "Mikrofony"
|
||||
@@ -567,7 +567,7 @@
|
||||
"name": "Řečník",
|
||||
"seconds": "",
|
||||
"speakerStats": "Statistika řečníků",
|
||||
"speakerTime": "Mluvil již"
|
||||
"speakerTime": "Mluvil(a) již"
|
||||
},
|
||||
"startupoverlay": {
|
||||
"policyText": " ",
|
||||
@@ -638,7 +638,7 @@
|
||||
"openChat": "",
|
||||
"pip": "",
|
||||
"profile": "Upravit váš profil",
|
||||
"raiseHand": "Příhlásit / Odhlásit se o slovo",
|
||||
"raiseHand": "Přihlásit / Odhlásit se o slovo",
|
||||
"raiseYourHand": "",
|
||||
"Settings": "Nastavení",
|
||||
"sharedvideo": "Sdílet obraz YouTube videa",
|
||||
|
||||
@@ -3,14 +3,15 @@
|
||||
"add": "Einladen",
|
||||
"addContacts": "Laden Sie Ihre Kontakte ein",
|
||||
"copyInvite": "Sitzungseinladung kopieren",
|
||||
"copyLink": "Meeting-Link kopieren",
|
||||
"copyStream": "Live-Streaming-Link kopieren",
|
||||
"copyLink": "Konferenzlink kopieren",
|
||||
"copyStream": "Livestreaminglink kopieren",
|
||||
"countryNotSupported": "Wir unterstützen dieses Land noch nicht.",
|
||||
"countryReminder": "Telefonnummer nicht in den USA? Bitte sicherstellen, dass die Telefonnummer mit dem Ländercode beginnt.",
|
||||
"defaultEmail": "Ihre Standard-E-Mail",
|
||||
"disabled": "Sie können keine Teilnehmer einladen.",
|
||||
"failedToAdd": "Fehler beim Hinzufügen von Teilnehmern",
|
||||
"footerText": "Abgehender Ruf ist deaktiviert.",
|
||||
"googleEmail": "Google-E-Mail",
|
||||
"inviteMoreHeader": "Sie sind alleine in der Sitzung",
|
||||
"inviteMoreMailSubject": "An {{appName}} Meeting teilnehmen",
|
||||
"inviteMorePrompt": "Mehr Leute einladen",
|
||||
@@ -20,14 +21,16 @@
|
||||
"loadingPeople": "Suche nach einzuladenden Teilnehmern",
|
||||
"noResults": "Keine passenden Ergebnisse",
|
||||
"noValidNumbers": "Telefonnummer eingeben",
|
||||
"outlookEmail": "Outlook-E-Mail",
|
||||
"searchNumbers": "Telefonnummern hinzufügen",
|
||||
"searchPeople": "Nach Teilnehmern suchen",
|
||||
"searchPeopleAndNumbers": "Nach Teilnehmen suchen oder deren Telefonnummern hinzufügen",
|
||||
"shareInvite": "Einladung zur Versammlung teilen",
|
||||
"shareLink": "Teilen Sie den Meeting-Link, um andere einzuladen",
|
||||
"shareStream": "Den Live-Streaming-Link freigeben",
|
||||
"shareLink": "Teilen Sie den Konferenzlink, um andere einzuladen",
|
||||
"shareStream": "Den Livestreaminglink freigeben",
|
||||
"telephone": "Telefon: {{number}}",
|
||||
"title": "Teilnehmer zu dieser Konferenz einladen"
|
||||
"title": "Teilnehmer zu dieser Konferenz einladen",
|
||||
"yahooEmail": "Yahoo-E-Mail"
|
||||
},
|
||||
"audioDevices": {
|
||||
"bluetooth": "Bluetooth",
|
||||
@@ -40,7 +43,7 @@
|
||||
"audioOnly": "Geringe Bandbreite"
|
||||
},
|
||||
"calendarSync": {
|
||||
"addMeetingURL": "Meeting-Link hinzufügen",
|
||||
"addMeetingURL": "Konferenzlink hinzufügen",
|
||||
"confirmAddLink": "Möchten Sie einen Jitsi-Link zu diesem Termin hinzufügen?",
|
||||
"error": {
|
||||
"appConfiguration": "Kalenderintegration ist nicht richtig konfiguriert.",
|
||||
@@ -89,9 +92,9 @@
|
||||
"DISCONNECTED": "Getrennt",
|
||||
"DISCONNECTING": "Verbindung wird getrennt",
|
||||
"ERROR": "Fehler",
|
||||
"FETCH_SESSION_ID": "Sitzungs-ID erhalten...",
|
||||
"FETCH_SESSION_ID": "Sitzungs-ID abrufen …",
|
||||
"GET_SESSION_ID_ERROR": "Sitzungs-ID-Fehler erhalten: {{code}}",
|
||||
"GOT_SESSION_ID": "Sitzungs-ID erhalten... Beendet",
|
||||
"GOT_SESSION_ID": "Sitzungs-ID abrufen … beendet",
|
||||
"LOW_BANDWIDTH": "Video für {{displayName}} wurde ausgeschaltet, um Bandbreite einzusparen"
|
||||
},
|
||||
"connectionindicator": {
|
||||
@@ -107,6 +110,7 @@
|
||||
"localaddress_plural": "Lokale Adressen:",
|
||||
"localport": "Lokaler Port:",
|
||||
"localport_plural": "Lokale Ports:",
|
||||
"maxEnabledResolution": "max. senden",
|
||||
"more": "Mehr anzeigen",
|
||||
"packetloss": "Paketverlust:",
|
||||
"quality": {
|
||||
@@ -139,7 +143,7 @@
|
||||
"ifHaveApp": "Wenn Sie die App bereits haben:",
|
||||
"joinInApp": "An dem Meeting teilnehmen mit der App",
|
||||
"launchWebButton": "Im Web öffnen",
|
||||
"title": "Die Konferenz wird in {{app}} geöffnet...",
|
||||
"title": "Die Konferenz wird in {{app}} geöffnet …",
|
||||
"tryAgainButton": "Erneut mit der nativen Applikation versuchen"
|
||||
},
|
||||
"defaultLink": "Bsp.: {{url}}",
|
||||
@@ -160,6 +164,7 @@
|
||||
"accessibilityLabel": {
|
||||
"liveStreaming": "Livestream"
|
||||
},
|
||||
"add": "Hinzufügen",
|
||||
"allow": "Erlauben",
|
||||
"alreadySharedVideoMsg": "Ein anderer Teilnehmer gibt bereits ein Video weiter. Bei dieser Konferenz ist jeweils nur ein geteiltes Video möglich.",
|
||||
"alreadySharedVideoTitle": "Nur ein geteiltes Video gleichzeitig",
|
||||
@@ -174,9 +179,9 @@
|
||||
"cameraUnsupportedResolutionError": "Die Kamera unterstützt die erforderliche Auflösung nicht.",
|
||||
"Cancel": "Abbrechen",
|
||||
"close": "Schließen",
|
||||
"conferenceDisconnectMsg": "Prüfen Sie allenfalls Ihre Netzwerkverbindung. Verbinde in {{seconds}} Sekunden...",
|
||||
"conferenceDisconnectMsg": "Prüfen Sie allenfalls Ihre Netzwerkverbindung. Verbinde in {{seconds}} Sekunden …",
|
||||
"conferenceDisconnectTitle": "Ihre Verbindung ist getrennt worden.",
|
||||
"conferenceReloadMsg": "Wir versuchen das zu beheben. Verbinde in {{seconds}} Sekunden...",
|
||||
"conferenceReloadMsg": "Wir versuchen das zu beheben. Verbinde in {{seconds}} Sekunden …",
|
||||
"conferenceReloadTitle": "Leider ist etwas schiefgegangen.",
|
||||
"confirm": "Bestätigen",
|
||||
"confirmNo": "Nein",
|
||||
@@ -185,21 +190,25 @@
|
||||
"connectErrorWithMsg": "Oh! Es hat etwas nicht geklappt und der Konferenz konnte nicht beigetreten werden: {{msg}}",
|
||||
"connecting": "Verbindung wird hergestellt",
|
||||
"contactSupport": "Support kontaktieren",
|
||||
"copied": "Kopiert",
|
||||
"copy": "Kopieren",
|
||||
"dismiss": "OK",
|
||||
"displayNameRequired": "Hallo! Wie ist Ihr Name?",
|
||||
"done": "Fertig",
|
||||
"e2eeDescription": "Ende-zu-Ende-Verschlüsselung ist derzeit noch EXPERIMENTELL. Bitte beachten Sie, dass das Aktivieren der Ende-zu-Ende-Verschlüsselung diverse serverseitige Funktionen deaktiviert: Aufnahmen, Livestreaming und Telefoneinwahl. Bitte beachten Sie außerdem, dass der Konferenz dann nur noch mit Browsern beigetreten werden kann, die Insertable Streams unterstützen.",
|
||||
"e2eeLabel": "E2EE-Schlüssel",
|
||||
"e2eeNoKey": "Keiner",
|
||||
"e2eeToggleSet": "Schlüssel festlegen",
|
||||
"e2eeSet": "Setzen",
|
||||
"e2eeWarning": "WARNUNG: Nicht alle Teilnehmer dieser Konferenz scheinen Ende-zu-Ende-Verschlüsselung zu unterstützen. Wenn Sie diese aktivieren, können die entsprechenden Teilnehmer nichts mehr sehen oder hören.",
|
||||
"enterDisplayName": "Bitte geben Sie hier Ihren Namen ein",
|
||||
"error": "Fehler",
|
||||
"externalInstallationMsg": "Die Bildschirmfreigabe-Erweiterung muss installiert werden.",
|
||||
"externalInstallationTitle": "Erweiterung erforderlich",
|
||||
"goToStore": "Zum Store",
|
||||
"gracefulShutdown": "Der Dienst steht momentan wegen Wartungsarbeiten nicht zur Verfügung. Bitte versuchen Sie es später noch einmal.",
|
||||
"grantModeratorDialog": "Möchten Sie diesen Teilnehmer wirklich zum Moderator machen?",
|
||||
"grantModeratorTitle": "Zum Moderator machen",
|
||||
"IamHost": "Ich bin der Organisator",
|
||||
"incorrectRoomLockPassword": "Falsches Passwort",
|
||||
"incorrectPassword": "Benutzername oder Passwort ungültig",
|
||||
"inlineInstallationMsg": "Die Bildschirmfreigabe-Erweiterung muss installiert werden.",
|
||||
"inlineInstallExtension": "Jetzt installieren",
|
||||
"internalError": "Oh! Es hat etwas nicht funktioniert. Der folgende Fehler ist aufgetreten: {{error}}",
|
||||
"internalErrorTitle": "Interner Fehler",
|
||||
"kickMessage": "Sie können sich für mehr Details an {{participantDisplayName}} wenden.",
|
||||
@@ -208,10 +217,11 @@
|
||||
"kickParticipantTitle": "Teilnehmer entfernen?",
|
||||
"kickTitle": "Autsch! {{participantDisplayName}} hat Sie aus dem Meeting geworfen",
|
||||
"liveStreaming": "Livestreaming",
|
||||
"liveStreamingDisabledBecauseOfActiveRecordingTooltip": "Während einer Aufnahme nicht möglich",
|
||||
"liveStreamingDisabledForGuestTooltip": "Gäste können kein Livestreaming starten.",
|
||||
"liveStreamingDisabledTooltip": "Starten des Livestreams deaktiviert.",
|
||||
"lockMessage": "Die Konferenz konnte nicht gesperrt werden.",
|
||||
"lockRoom": "Meeting-$t(lockRoomPasswordUppercase) hinzufügen",
|
||||
"lockRoom": "Konferenz$t(lockRoomPassword) hinzufügen",
|
||||
"lockTitle": "Sperren fehlgeschlagen",
|
||||
"logoutQuestion": "Sind Sie sicher, dass Sie sich abmelden und die Konferenz verlassen möchten?",
|
||||
"logoutTitle": "Abmelden",
|
||||
@@ -234,13 +244,15 @@
|
||||
"muteParticipantDialog": "Wollen Sie diesen Teilnehmer wirklich stummschalten? Sie können die Stummschaltung nicht wieder aufheben, der Teilnehmer kann dies aber jederzeit selbst tun.",
|
||||
"muteParticipantTitle": "Teilnehmer stummschalten?",
|
||||
"Ok": "OK",
|
||||
"passwordLabel": "Dieses Meeting wurde von einem Teilnehmer gesichert. Bitte geben Sie das $t(lockRoomPassword) ein, um dem Meeting beizutreten.",
|
||||
"passwordNotSupported": "Das Festlegen von einem $t(lockRoomPassword) für das Meeting wird nicht unterstützt.",
|
||||
"passwordLabel": "Dieses Meeting wurde von einem Teilnehmer gesichert. Bitte geben Sie das $t(lockRoomPasswordUppercase) ein, um dem Meeting beizutreten.",
|
||||
"passwordNotSupported": "Das Festlegen eines Konferenzpassworts wird nicht unterstützt.",
|
||||
"passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) nicht unterstützt",
|
||||
"passwordRequired": "$t(lockRoomPasswordUppercase) erforderlich",
|
||||
"popupError": "Ihr Browser blockiert Pop-ups von dieser Website. Bitte aktivieren Sie Pop-ups in den Sicherheitseinstellungen des Browsers und versuchen Sie es erneut.",
|
||||
"popupErrorTitle": "Pop-up blockiert",
|
||||
"readMore": "mehr",
|
||||
"recording": "Aufnahme",
|
||||
"recordingDisabledBecauseOfActiveLiveStreamingTooltip": "Während eines Livestreams nicht möglich",
|
||||
"recordingDisabledForGuestTooltip": "Gäste können keine Aufzeichnungen starten.",
|
||||
"recordingDisabledTooltip": "Start der Aufzeichnung deaktiviert.",
|
||||
"rejoinNow": "Jetzt erneut beitreten",
|
||||
@@ -252,17 +264,16 @@
|
||||
"remoteControlStopMessage": "Die Fernsteuerung wurde beendet!",
|
||||
"remoteControlTitle": "Fernsteuerung",
|
||||
"Remove": "Entfernen",
|
||||
"removePassword": "$t(lockRoomPassword) entfernen",
|
||||
"removePassword": "$t(lockRoomPasswordUppercase) entfernen",
|
||||
"removeSharedVideoMsg": "Sind Sie sicher, dass Sie das geteilte Video entfernen möchten?",
|
||||
"removeSharedVideoTitle": "Freigegebenes Video entfernen",
|
||||
"reservationError": "Fehler im Reservierungssystem",
|
||||
"reservationErrorMsg": "Fehler, Nummer: {{code}}, Nachricht: {{msg}}",
|
||||
"retry": "Wiederholen",
|
||||
"screenSharingFailedToInstall": "Oh! Die Erweiterung für die Bildschirmfreigabe konnte nicht installiert werden.",
|
||||
"screenSharingFailedToInstallTitle": "Bildschirmfreigabe-Erweiterung konnte nicht installiert werden",
|
||||
"screenSharingFirefoxPermissionDeniedError": "Die Bildschirmfreigabe ist leider fehlgeschlagen. Bitte stellen Sie sicher, dass die Berechtigung für die Bildschirmfreigabe im Browser erteilt wurde. ",
|
||||
"screenSharingFirefoxPermissionDeniedTitle": "Die Bildschirmfreigabe konnte nicht gestartet werden!",
|
||||
"screenSharingPermissionDeniedError": "Oh! Beim Anfordern der Bildschirmfreigabe-Berechtigungen hat etwas nicht funktioniert. Bitte aktualisieren und erneut versuchen.",
|
||||
"screenSharingAudio": "Audio teilen",
|
||||
"screenSharingFailed": "Ups! Beim Teilen des Bildschirms ist etwas schiefgegangen!",
|
||||
"screenSharingFailedTitle": "Bildschirmfreigabe fehlgeschlagen!",
|
||||
"screenSharingPermissionDeniedError": "Ups! Etwas stimmt nicht mit Ihren Berechtigungen zur Bildschirmfreigabe. Bitte neu laden und erneut versuchen.",
|
||||
"sendPrivateMessage": "Sie haben kürzlich eine private Nachricht erhalten. Hatten Sie die Absicht, darauf privat zu antworten, oder wollen Sie Ihre Nachricht an die Gruppe senden?",
|
||||
"sendPrivateMessageCancel": "An die Gruppe senden",
|
||||
"sendPrivateMessageOk": "Privat antworten",
|
||||
@@ -275,13 +286,13 @@
|
||||
"shareYourScreen": "Bildschirm freigeben",
|
||||
"shareYourScreenDisabled": "Bildschirmfreigabe deaktiviert.",
|
||||
"shareYourScreenDisabledForGuest": "Gäste können den Bildschirm nicht freigeben.",
|
||||
"startLiveStreaming": "Einen Livestream starten",
|
||||
"startLiveStreaming": "Livestream starten",
|
||||
"startRecording": "Aufnahme starten",
|
||||
"startRemoteControlErrorMessage": "Beim Versuch, die Fernsteuerung zu starten, ist ein Fehler aufgetreten!",
|
||||
"stopLiveStreaming": "Livestreaming stoppen",
|
||||
"stopLiveStreaming": "Livestream stoppen",
|
||||
"stopRecording": "Aufnahme stoppen",
|
||||
"stopRecordingWarning": "Sind Sie sicher, dass Sie die Aufnahme stoppen möchten?",
|
||||
"stopStreamingWarning": "Sind Sie sicher, dass Sie das Livestreaming stoppen möchten?",
|
||||
"stopStreamingWarning": "Sind Sie sicher, dass Sie den Livestream stoppen möchten?",
|
||||
"streamKey": "Streamschlüssel",
|
||||
"Submit": "OK",
|
||||
"thankYou": "Danke für die Verwendung von {{appName}}!",
|
||||
@@ -289,14 +300,13 @@
|
||||
"tokenAuthFailed": "Sie sind nicht berechtigt, dieser Konferenz beizutreten.",
|
||||
"tokenAuthFailedTitle": "Authentifizierung fehlgeschlagen",
|
||||
"transcribing": "Wird transkribiert",
|
||||
"unlockRoom": "Meeting-$t(lockRoomPassword) entfernen",
|
||||
"unlockRoom": "Konferenz$t(lockRoomPassword) entfernen",
|
||||
"userPassword": "Benutzerpasswort",
|
||||
"WaitForHostMsg": "Die Konferenz <b>{{room}}</b> wurde noch nicht gestartet. Wenn Sie der Organisator sind, authentifizieren Sie sich. Warten Sie andernfalls, bis der Organisator erscheint.",
|
||||
"WaitForHostMsgWOk": "Die Konferenz <b>{{room}}</b> wurde noch nicht gestartet. Wenn Sie der Organisator sind, drücken Sie zum Authentifizieren auf OK. Warten Sie andernfalls, bis der Organisator erscheint.",
|
||||
"WaitingForHost": "Warten auf den Organisator...",
|
||||
"WaitingForHost": "Warten auf den Organisator …",
|
||||
"Yes": "Ja",
|
||||
"yourEntireScreen": "Ganzer Bildschirm",
|
||||
"screenSharingAudio": "Audio austauschen"
|
||||
"yourEntireScreen": "Ganzer Bildschirm"
|
||||
},
|
||||
"dialOut": {
|
||||
"statusMessage": "ist jetzt {{status}}"
|
||||
@@ -304,6 +314,12 @@
|
||||
"documentSharing": {
|
||||
"title": "Freigegebenes Dokument"
|
||||
},
|
||||
"e2ee": {
|
||||
"labelToolTip": "Audio- und Videodaten dieser Unterhaltung sind jetzt zwischen den Teilnehmern verschlüsselt"
|
||||
},
|
||||
"embedMeeting": {
|
||||
"title": "Diese Konferenz einbetten"
|
||||
},
|
||||
"feedback": {
|
||||
"average": "Durchschnittlich",
|
||||
"bad": "Schlecht",
|
||||
@@ -322,8 +338,8 @@
|
||||
},
|
||||
"info": {
|
||||
"accessibilityLabel": "Informationen anzeigen",
|
||||
"addPassword": "$t(lockRoomPassword) hinzufügen",
|
||||
"cancelPassword": "$t(lockRoomPassword) löschen",
|
||||
"addPassword": "$t(lockRoomPasswordUppercase) hinzufügen",
|
||||
"cancelPassword": "$t(lockRoomPasswordUppercase) löschen",
|
||||
"conferenceURL": "Link:",
|
||||
"country": "Land",
|
||||
"dialANumber": "Um am Meeting teilzunehmen, müssen Sie eine dieser Nummern wählen und dann die PIN eingeben.",
|
||||
@@ -335,7 +351,7 @@
|
||||
"genericError": "Es ist leider etwas schiefgegangen.",
|
||||
"inviteLiveStream": "Klicken Sie auf {{url}}, um den Livestream dieser Konferenz zu öffnen",
|
||||
"invitePhone": "Wenn Sie stattdessen per Telefon beitreten möchten, wählen sie: {{number}},,{{conferenceID}}#\n",
|
||||
"invitePhoneAlternatives": "Suchen Sie nach einer anderen Einwahlnummer ?\nMeeting-Einwahlnummern anzeigen: {{url}}\n\n\nWenn Sie sich auch über ein Raumtelefon einwählen, nehmen Sie teil, ohne sich mit dem Ton zu verbinden: {{silentUrl}}",
|
||||
"invitePhoneAlternatives": "Suchen Sie nach einer anderen Einwahlnummer ?\nEinwahlnummern der Konferenz anzeigen: {{url}}\n\n\nWenn Sie sich auch über ein Raumtelefon einwählen, nehmen Sie teil, ohne sich mit dem Ton zu verbinden: {{silentUrl}}",
|
||||
"inviteURLFirstPartGeneral": "Sie wurden zur Teilnahme an einem Meeting eingeladen.",
|
||||
"inviteURLFirstPartPersonal": "{{name}} lädt Sie zu einem Meeting ein.\n",
|
||||
"inviteURLSecondPart": "\nAm Meeting teilnehmen:\n{{url}}\n",
|
||||
@@ -348,7 +364,7 @@
|
||||
"password": "$t(lockRoomPasswordUppercase):",
|
||||
"title": "Teilen",
|
||||
"tooltip": "Freigabe-Link und Einwahlinformationen für dieses Meeting",
|
||||
"label": "Meeting-Informationen"
|
||||
"label": "Konferenzinformationen"
|
||||
},
|
||||
"inviteDialog": {
|
||||
"alertText": "Die Einladung einiger Teilnehmer ist fehlgeschlagen.",
|
||||
@@ -382,6 +398,8 @@
|
||||
"videoQuality": "Anrufqualität verwalten"
|
||||
},
|
||||
"liveStreaming": {
|
||||
"limitNotificationDescriptionWeb": "Wegen hoher Nachfrage ist Ihr Stream auf {{limit}} min. begrenzt. Für unlimitiertes Streaming nutzen Sie bitte <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"limitNotificationDescriptionNative": "Ihr Stream ist begrenzt auf {{limit}} min. Für unlimitiertes Streaming, nutzen Sie bitte {{app}}.",
|
||||
"busy": "Es werden Ressourcen zum Streamen bereitgestellt. Bitte in ein paar Minuten erneut versuchen.",
|
||||
"busyTitle": "Alle Streaming-Instanzen sind in Gebrauch",
|
||||
"changeSignIn": "Konten wechseln.",
|
||||
@@ -391,17 +409,17 @@
|
||||
"error": "Das Livestreaming ist fehlgeschlagen. Bitte versuchen Sie es erneut.",
|
||||
"errorAPI": "Beim Abrufen der YouTube-Livestreams ist ein Fehler aufgetreten. Bitte versuchen Sie, sich erneut anzumelden.",
|
||||
"errorLiveStreamNotEnabled": "Livestreaming ist für {{email}} nicht aktiviert. Aktivieren Sie das Livestreaming oder melden Sie sich bei einem Konto mit aktiviertem Livestreaming an.",
|
||||
"expandedOff": "Livestreaming wurde angehalten",
|
||||
"expandedOff": "Livestream wurde angehalten",
|
||||
"expandedOn": "Das Meeting wird momentan an YouTube gestreamt.",
|
||||
"expandedPending": "Livestreaming wird gestartet...",
|
||||
"failedToStart": "Livestreaming konnte nicht gestartet werden",
|
||||
"expandedPending": "Livestream wird gestartet …",
|
||||
"failedToStart": "Livestream konnte nicht gestartet werden",
|
||||
"getStreamKeyManually": "Wir waren nicht in der Lage, Livestreams abzurufen. Versuchen Sie, Ihren Livestream-Schlüssel von YouTube zu erhalten.",
|
||||
"invalidStreamKey": "Der Livestream-Schlüssel ist u. U. falsch.",
|
||||
"off": "Livestreaming gestoppt",
|
||||
"offBy": "{{name}} stoppte das Livestreaming",
|
||||
"on": "Livestreaming",
|
||||
"onBy": "{{name}} startete das Livestreaming",
|
||||
"pending": "Livestream wird gestartet...",
|
||||
"off": "Livestream gestoppt",
|
||||
"offBy": "{{name}} stoppte den Livestream",
|
||||
"on": "Livestream",
|
||||
"onBy": "{{name}} startete den Livestream",
|
||||
"pending": "Livestream wird gestartet …",
|
||||
"serviceName": "Livestreaming-Dienst",
|
||||
"signedInAs": "Sie sind derzeit angemeldet als:",
|
||||
"signIn": "Mit Google anmelden",
|
||||
@@ -442,7 +460,7 @@
|
||||
"stop": "Aufnahme stoppen",
|
||||
"yes": "Ja"
|
||||
},
|
||||
"lockRoomPassword": "Passwort",
|
||||
"lockRoomPassword": "passwort",
|
||||
"lockRoomPasswordUppercase": "Passwort",
|
||||
"me": "ich",
|
||||
"notify": {
|
||||
@@ -474,11 +492,51 @@
|
||||
"unmute": "Stummschaltung aufheben",
|
||||
"newDeviceCameraTitle": "Neue Kamera erkannt",
|
||||
"newDeviceAudioTitle": "Neues Audiogerät erkannt",
|
||||
"newDeviceAction": "Verwenden"
|
||||
"newDeviceAction": "Verwenden",
|
||||
"OldElectronAPPTitle": "Sicherheitslücke!",
|
||||
"oldElectronClientDescription1": "Sie scheinen eine alte Version des Jitsi-Meet-Clients zu nutzen. Diese hat bekannte Schwachstellen. Bitte aktualisieren Sie auf unsere ",
|
||||
"oldElectronClientDescription2": "aktuelle Version",
|
||||
"oldElectronClientDescription3": "!"
|
||||
},
|
||||
"passwordSetRemotely": "von einem anderen Teilnehmer gesetzt",
|
||||
"passwordDigitsOnly": "Bis zu {{number}} Ziffern",
|
||||
"poweredby": "Betrieben von",
|
||||
"prejoin": {
|
||||
"audioAndVideoError": "Audio- und Videofehler:",
|
||||
"audioOnlyError": "Audiofehler:",
|
||||
"audioTrackError": "Audiotrack konnte nicht erstellt werden.",
|
||||
"calling": "Rufaufbau",
|
||||
"callMe": "Mich anrufen",
|
||||
"callMeAtNumber": "Mich unter dieser Nummer anrufen:",
|
||||
"configuringDevices": "Geräte werden eingerichtet …",
|
||||
"connectedWithAudioQ": "Sie sind mit Audio verbunden?",
|
||||
"copyAndShare": "Konferenzlink kopieren & teilen",
|
||||
"dialInMeeting": "Telefoneinwahl",
|
||||
"dialInPin": "In die Konferenz einwählen und PIN eingeben:",
|
||||
"dialing": "Wählen",
|
||||
"doNotShow": "Nicht mehr anzeigen",
|
||||
"errorDialOut": "Anruf fehlgeschlagen",
|
||||
"errorDialOutDisconnected": "Anruf fehlgeschlagen. Verbindungsabbruch",
|
||||
"errorDialOutFailed": "Anruf fehlgeschlagen. Anruf fehlgeschlagen",
|
||||
"errorDialOutStatus": "Fehler beim Abrufen des Anrufstatus",
|
||||
"errorStatusCode": "Anruf fehlgeschlagen. Statuscode: {{status}}",
|
||||
"errorValidation": "Nummerverifikation fehlgeschlagen",
|
||||
"iWantToDialIn": "Ich möchte mich einwählen",
|
||||
"joinAudioByPhone": "Per Telefon teilnehmen",
|
||||
"joinMeeting": "Konferenz beitreten",
|
||||
"joinWithoutAudio": "Ohne Ton beitreten",
|
||||
"initiated": "Anruf gestartet",
|
||||
"linkCopied": "Link in die Zwischenablage kopiert",
|
||||
"lookGood": "Ihr Mikrofon scheint zu funktionieren.",
|
||||
"or": "oder",
|
||||
"premeeting": "Vorraum",
|
||||
"showScreen": "Konferenzvorraum aktivieren",
|
||||
"startWithPhone": "Mit Telefonaudio starten",
|
||||
"screenSharingError": "Fehler bei Bildschirmfreigabe:",
|
||||
"videoOnlyError": "Videofehler:",
|
||||
"videoTrackError": "Videotrack konnte nicht erstellt werden.",
|
||||
"viewAllNumbers": "alle Nummern anzeigen"
|
||||
},
|
||||
"presenceStatus": {
|
||||
"busy": "Beschäftigt",
|
||||
"calling": "Wird angerufen …",
|
||||
@@ -501,6 +559,8 @@
|
||||
},
|
||||
"raisedHand": "Ich möchte sprechen",
|
||||
"recording": {
|
||||
"limitNotificationDescriptionWeb": "Wegen hoher Nachfrage ist Ihre Aufnahme auf {{limit}} min. begrenzt. Für unlimitierte Aufnahmen nutzen Sie bitte <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"limitNotificationDescriptionNative": "Wegen hoher Nachfrage ist Ihre Aufnahme auf {{limit}} min begrenzt. Für unlimitierte Aufnahmen nutzen Sie bitte <3>{{app}}</3>.",
|
||||
"authDropboxText": "In Dropbox hochladen",
|
||||
"availableSpace": "Verfügbarer Speicherplatz: {{spaceLeft}} MB (ca. {{duration}} Minuten Aufzeichnung)",
|
||||
"beta": "BETA",
|
||||
@@ -511,7 +571,7 @@
|
||||
"expandedOn": "Das Meeting wird momentan aufgezeichnet.",
|
||||
"expandedPending": "Aufzeichnung wird gestartet…",
|
||||
"failedToStart": "Die Aufnahme konnte nicht gestartet werden",
|
||||
"fileSharingdescription": "Aufzeichnung mit Meeting-Teilnehmer teilen",
|
||||
"fileSharingdescription": "Aufzeichnung mit Konferenzteilnehmer teilen",
|
||||
"live": "LIVE",
|
||||
"loggedIn": "Als {{userName}} angemeldet",
|
||||
"off": "Aufnahme gestoppt",
|
||||
@@ -531,7 +591,8 @@
|
||||
"pullToRefresh": "Ziehen, um zu aktualisieren"
|
||||
},
|
||||
"security": {
|
||||
"about": "Sie können einen Passwort zu Ihrer Sitzung hinzufügen. Die Teilnehmer müssen dieses ebenfalls eingeben, bevor sie an der Sitzung teilnehmen dürfen",
|
||||
"about": "Sie können Ihre Konferenz mit einem Passwort sichern. Teilnehmer müssen dieses eingeben, bevor sie an der Sitzung teilnehmen dürfen.",
|
||||
"aboutReadOnly": "Moderatoren können die Konferenz mit einem Passwort sichern. Teilnehmer müssen dieses eingeben, bevor sie an der Sitzung teilnehmen dürfen.",
|
||||
"insecureRoomNameWarning": "Der Raumname ist unsicher. Unerwünschte Teilnehmer könnten Ihrer Konferenz beitreten",
|
||||
"securityOptions": "Sicherheitsoptionen"
|
||||
},
|
||||
@@ -563,12 +624,15 @@
|
||||
"settingsView": {
|
||||
"advanced": "Erweitert",
|
||||
"alertOk": "OK",
|
||||
"alertCancel": "Abbrechen",
|
||||
"alertTitle": "Warnung",
|
||||
"alertURLText": "Die angegebene Server-URL ist ungültig",
|
||||
"buildInfoSection": "Build-Informationen",
|
||||
"conferenceSection": "Konferenz",
|
||||
"disableCallIntegration": "Native Anrufintegration deaktivieren",
|
||||
"disableP2P": "Ende-zu-Ende-Modus deaktivieren",
|
||||
"disableCrashReporting": "Absturzberichte deaktivieren",
|
||||
"disableCrashReportingWarning": "Möchten Sie die Absturzberichte wirklich deaktivieren? Diese Einstellung wird nach einem Neustart der App wirksam.",
|
||||
"displayName": "Anzeigename",
|
||||
"email": "E-Mail",
|
||||
"header": "Einstellungen",
|
||||
@@ -610,14 +674,18 @@
|
||||
"chat": "Chatfenster ein-/ausblenden",
|
||||
"document": "Geteiltes Dokument schließen",
|
||||
"download": "Unsere Apps herunterladen",
|
||||
"embedMeeting": "Konferenz einbetten",
|
||||
"e2ee": "Ende-zu-Ende-Verschlüsselung",
|
||||
"feedback": "Feedback hinterlassen",
|
||||
"fullScreen": "Vollbildmodus aktivieren/deaktivieren",
|
||||
"fullScreen": "Vollbildmodus ein-/ausschalten",
|
||||
"grantModerator": "Zum Moderator machen",
|
||||
"hangup": "Anruf beenden",
|
||||
"help": "Hilfe",
|
||||
"invite": "Teilnehmer einladen",
|
||||
"kick": "Teilnehmer entfernen",
|
||||
"lobbyButton": "Lobbymodus ein-/ausschalten",
|
||||
"localRecording": "Lokale Aufzeichnungssteuerelemente ein-/ausschalten",
|
||||
"lockRoom": "Meeting-Passwort ein-/auschalten",
|
||||
"lockRoom": "Konferenzpasswort ein-/auschalten",
|
||||
"moreActions": "Menü „Weitere Aktionen“ ein-/ausschalten",
|
||||
"moreActionsMenu": "Menü „Weitere Aktionen“",
|
||||
"moreOptions": "Menü „Weitere Optionen“",
|
||||
@@ -639,6 +707,7 @@
|
||||
"speakerStats": "Sprecherstatistik ein-/ausblenden",
|
||||
"tileView": "Kachelansicht ein-/ausschalten",
|
||||
"toggleCamera": "Kamera wechseln",
|
||||
"toggleFilmstrip": "Miniaturansichten ein-/ausschalten",
|
||||
"videomute": "„Video stummschalten“ ein-/ausschalten",
|
||||
"videoblur": "Video-Unschärfe ein-/ausschalten"
|
||||
},
|
||||
@@ -653,6 +722,8 @@
|
||||
"documentClose": "Geteiltes Dokument schließen",
|
||||
"documentOpen": "Geteiltes Dokument öffnen",
|
||||
"download": "Unsere Apps herunterladen",
|
||||
"e2ee": "Ende-zu-Ende-Verschlüsselung",
|
||||
"embedMeeting": "Konferenz einbetten",
|
||||
"enterFullScreen": "Vollbildmodus",
|
||||
"enterTileView": "Kachelansicht einschalten",
|
||||
"exitFullScreen": "Vollbildmodus verlassen",
|
||||
@@ -661,6 +732,8 @@
|
||||
"hangup": "Verlassen",
|
||||
"help": "Hilfe",
|
||||
"invite": "Teilnehmer einladen",
|
||||
"lobbyButtonDisable": "Lobbymodus deaktivieren",
|
||||
"lobbyButtonEnable": "Lobbymodus aktivieren",
|
||||
"login": "Anmelden",
|
||||
"logout": "Abmelden",
|
||||
"lowerYourHand": "Hand senken",
|
||||
@@ -755,6 +828,7 @@
|
||||
"domute": "Stummschalten",
|
||||
"domuteOthers": "Alle anderen stummschalten",
|
||||
"flip": "Spiegeln",
|
||||
"grantModerator": "Zum Moderator machen",
|
||||
"kick": "Hinauswerfen",
|
||||
"moderator": "Moderator",
|
||||
"mute": "Teilnehmer ist stumm geschaltet",
|
||||
@@ -768,7 +842,7 @@
|
||||
"join": "Zum Teilnehmen tippen",
|
||||
"roomname": "Konferenzname eingeben"
|
||||
},
|
||||
"appDescription": "Auf geht's! Starten Sie eine Videokonferenz mit dem ganzen Team. Oder besser noch: Laden Sie alle ein, die Sie kennen. {{app}} ist eine vollständig verschlüsselte, aus 100 % Open-Source-Software bestehende Videokonferenzlösung, die Sie den ganzen Tag kostenlos verwenden können — ohne Registrierung.",
|
||||
"appDescription": "Auf geht's! Starten Sie eine Videokonferenz mit ihrem Team oder besser noch: Laden Sie alle ein, die Sie kennen. {{app}} ist eine vollständig verschlüsselte und 100 % quelloffene Videokonferenzlösung, die Sie immer und überall kostenlos verwenden können – ohne Registrierung.",
|
||||
"audioVideoSwitch": {
|
||||
"audio": "Audio",
|
||||
"video": "Video"
|
||||
@@ -777,24 +851,62 @@
|
||||
"connectCalendarButton": "Kalender verbinden",
|
||||
"connectCalendarText": "Verbinden Sie Ihren Kalender, um all Ihre Meetings in {{app}} anzuzeigen. Fügen Sie zudem {{provider}}-Meetings in Ihren Kalender ein und starten Sie sie mit nur einem Klick.",
|
||||
"enterRoomTitle": "Neues Meeting starten",
|
||||
"roomNameAllowedChars": "Der Meeting-Name sollte keines der folgenden Zeichen enthalten: ?, &, :, ', \", %, #.",
|
||||
"getHelp": "Hilfe",
|
||||
"go": "Los",
|
||||
"goSmall": "Los",
|
||||
"join": "Beitreten",
|
||||
"info": "Informationen",
|
||||
"join": "ERSTELLEN / BEITRETEN",
|
||||
"moderatedMessage": "Oder <a href=\"{{url}}\" rel=\"noopener noreferrer\" target=\"_blank\">reservieren Sie sich eine Konferenz-URL</a>, unter der Sie der einzige Moderator sind.",
|
||||
"privacy": "Datenschutz",
|
||||
"recentList": "Letzte",
|
||||
"recentList": "Verlauf",
|
||||
"recentListDelete": "Löschen",
|
||||
"recentListEmpty": "Die Liste „Letzte“ ist momentan leer. Chatten Sie mit Ihrem Team. Sie finden all Ihre letzten Meetings hier.",
|
||||
"recentListEmpty": "Ihr Konferenzverlauf ist derzeit leer. Reden Sie mit Ihrem Team und Ihre vergangenen Konferenzen landen hier.",
|
||||
"reducedUIText": "Willkommen bei {{app}}!",
|
||||
"roomNameAllowedChars": "Der Konferenzname sollte keines der folgenden Zeichen enthalten: ?, &, :, ', \", %, #.",
|
||||
"roomname": "Konferenzname eingeben",
|
||||
"roomnameHint": "Name oder URL der Konferenz, der Sie beitreten möchten. Sie können einen Namen erfinden, er muss nur den anderen Teilnehmern übermittelt werden, damit diese der gleichen Konferenz beitreten.",
|
||||
"sendFeedback": "Feedback senden",
|
||||
"terms": "AGB",
|
||||
"title": "Sichere, mit umfassenden Funktionen ausgestattete und vollkommen kostenlose Videokonferenzen"
|
||||
"title": "Sichere, voll funktionale und komplett kostenlose Videokonferenzen"
|
||||
},
|
||||
"lonelyMeetingExperience": {
|
||||
"button": "Andere einladen",
|
||||
"youAreAlone": "Nur Sie sind in diesem Meeting"
|
||||
"youAreAlone": "Sie sind alleine in dieser Konferenz"
|
||||
},
|
||||
"helpView": {
|
||||
"header": "Hilfecenter"
|
||||
},
|
||||
"lobby": {
|
||||
"knockingParticipantList": "Liste anklopfender Teilnehmer",
|
||||
"allow": "Annehmen",
|
||||
"backToKnockModeButton": "Kein Passwort, stattdessen Beitritt anfragen",
|
||||
"dialogTitle": "Lobbymodus",
|
||||
"disableDialogContent": "Lobbymodus derzeit deaktiviert. Diese Funktion stellt sicher, dass unerwünschte Personen Ihrer Konferenz nicht beitreten können. Funktion aktivieren?",
|
||||
"disableDialogSubmit": "Deaktivieren",
|
||||
"emailField": "E-Mail-Adresse eingeben",
|
||||
"enableDialogPasswordField": "Passwort setzen (optional)",
|
||||
"enableDialogSubmit": "Aktivieren",
|
||||
"enableDialogText": "Mit dem Lobbymodus schützen Sie Ihre Konferenz, da nur von einem Moderator angenommene Teilnehmer beitreten können.",
|
||||
"enterPasswordButton": "Konferenzpasswort eingeben",
|
||||
"enterPasswordTitle": "Passwort zum Beitreten benutzen",
|
||||
"invalidPassword": "Ungültiges Passwort",
|
||||
"joiningMessage": "Sie treten der Konferenz bei, sobald jemand Ihre Anfrage annimmt.",
|
||||
"joinWithPasswordMessage": "Beitrittsversuch mit Passwort, bitte warten …",
|
||||
"joinRejectedMessage": "Ihr Beitrittsanfrage wurde von einem Moderator abgelehnt.",
|
||||
"joinTitle": "Konferenz beitreten",
|
||||
"joiningTitle": "Beitritt anfragen …",
|
||||
"joiningWithPasswordTitle": "Mit Passwort beitreten …",
|
||||
"knockButton": "Beitritt anfragen",
|
||||
"knockTitle": "Jemand möchte der Konferenz beitreten",
|
||||
"nameField": "Geben Sie Ihren Namen ein",
|
||||
"notificationLobbyAccessDenied": "{{targetParticipantName}} wurde von {{originParticipantName}} der Zutritt verwehrt",
|
||||
"notificationLobbyAccessGranted": "{{targetParticipantName}} wurde von {{originParticipantName}} der Zutritt gestattet",
|
||||
"notificationLobbyDisabled": "{{originParticipantName}} hat die Lobby deaktiviert",
|
||||
"notificationLobbyEnabled": "{{originParticipantName}} hat die Lobby aktiviert",
|
||||
"notificationTitle": "Lobby",
|
||||
"passwordField": "Konferenzpasswort eingeben",
|
||||
"passwordJoinButton": "Beitreten",
|
||||
"reject": "Ablehnen",
|
||||
"toggleLabel": "Lobby aktivieren"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,7 +580,7 @@
|
||||
},
|
||||
"security": {
|
||||
"about": "Usted puede agregar una contraseña a la reunión. Los participantes necesitaran la contraseña para unirse a la reunión.",
|
||||
"insecureRoomNameWarning": "El nombre de la sala es inseguro. Participantes no desseados pueden llegar a unirse a la reunión.",
|
||||
"insecureRoomNameWarning": "El nombre de la sala es inseguro. Participantes no deseados pueden llegar a unirse a la reunión.",
|
||||
"securityOptions": "Opciones de seguridad"
|
||||
},
|
||||
"settings": {
|
||||
|
||||
@@ -578,7 +578,7 @@
|
||||
},
|
||||
"security": {
|
||||
"about": "Usted puede agregar una contraseña a la reunión. Los participantes necesitaran la contraseña para unirse a la reunión.",
|
||||
"insecureRoomNameWarning": "El nombre de la sala es inseguro. Participantes no desseados pueden llegar a unirse a la reunión.",
|
||||
"insecureRoomNameWarning": "El nombre de la sala es inseguro. Participantes no deseados pueden llegar a unirse a la reunión.",
|
||||
"securityOptions": "Opciones de seguridad"
|
||||
},
|
||||
"settings": {
|
||||
|
||||
@@ -194,6 +194,8 @@
|
||||
"done": "Terminé",
|
||||
"enterDisplayName": "Merci de saisir votre nom ici",
|
||||
"error": "Erreur",
|
||||
"grantModeratorDialog": "Êtes vous sûr de vouloir rendre ce participant modérateur?",
|
||||
"grantModeratorTitle": "Nommer modérateur",
|
||||
"externalInstallationMsg": "Vous devez installer notre extension de partage de bureau.",
|
||||
"externalInstallationTitle": "Extension requise",
|
||||
"goToStore": "Aller sur le webstore",
|
||||
@@ -788,6 +790,7 @@
|
||||
"domute": "Couper le micro",
|
||||
"domuteOthers": "Couper le micro de tous les autres",
|
||||
"flip": "Balancer",
|
||||
"grantModerator": "Nommer modérateur",
|
||||
"kick": "Exclure",
|
||||
"moderator": "Modérateur",
|
||||
"mute": "Un participant a coupé son micro",
|
||||
|
||||
@@ -325,7 +325,7 @@
|
||||
"keyboardShortcuts": "キーボードショートカット",
|
||||
"localRecording": "ローカル録画コントロールの表示/非表示",
|
||||
"mute": "マイクの消音 ( ミュート )",
|
||||
"pushToTalk": "話すために押す",
|
||||
"pushToTalk": "プッシュ・トゥ・トーク",
|
||||
"raiseHand": "手を上げる/下げる",
|
||||
"showSpeakerStats": "演説者のデータを表示",
|
||||
"toggleChat": "チャットを表示/非表示",
|
||||
@@ -566,7 +566,7 @@
|
||||
"shortcuts": "ショートカットに切り替える",
|
||||
"show": "",
|
||||
"speakerStats": "スピーカー統計に切り替える",
|
||||
"tileView": "",
|
||||
"tileView": "タイルビュー",
|
||||
"toggleCamera": "カメラを切り替える",
|
||||
"videomute": "ミュートビデオに切り替える",
|
||||
"videoblur": ""
|
||||
@@ -582,9 +582,9 @@
|
||||
"documentClose": "共有ドキュメントを閉じる",
|
||||
"documentOpen": "共有ドキュメントを開く",
|
||||
"enterFullScreen": "フルスクリーン表示",
|
||||
"enterTileView": "タイトルビューを開始",
|
||||
"enterTileView": "タイルビューを開始",
|
||||
"exitFullScreen": "フルスクリーンを終了",
|
||||
"exitTileView": "タイトルビューを終了",
|
||||
"exitTileView": "タイルビューを終了",
|
||||
"feedback": "フィードバックを残す",
|
||||
"hangup": "退出",
|
||||
"invite": "メンバーを招待する",
|
||||
@@ -609,7 +609,7 @@
|
||||
"stopSubtitles": "字幕停止",
|
||||
"stopSharedVideo": "YouTube動画を停止する",
|
||||
"talkWhileMutedPopup": "話そうとしていますか? あなたはミュートされています。",
|
||||
"tileViewToggle": "",
|
||||
"tileViewToggle": "タイルビューを切り替え",
|
||||
"toggleCamera": "カメラを切り替える",
|
||||
"videomute": "カメラの開始 / 停止",
|
||||
"startvideoblur": "",
|
||||
|
||||
@@ -2,35 +2,35 @@
|
||||
"addPeople": {
|
||||
"add": "Zaproś",
|
||||
"addContacts": "Zaproś kontakty",
|
||||
"copyInvite": "Skopiuj zaproszenie",
|
||||
"copyLink": "Skopiuj odnośnik do spotkania",
|
||||
"copyStream": "Skopiuj odnośnik do transmisji",
|
||||
"copyInvite": "Kopiuj zaproszenie na spotkanie",
|
||||
"copyLink": "Kopiuj link spotkania",
|
||||
"copyStream": "Kopiuj link transmisji na żywo",
|
||||
"countryNotSupported": "Nie obsługujemy jeszcze tej lokalizacji.",
|
||||
"countryReminder": "Dzwonisz spoza USA? Upewnij się, że zaczynasz od kodu kraju!",
|
||||
"defaultEmail": "Domyślny klient email",
|
||||
"defaultEmail": "Domyślna poczta",
|
||||
"disabled": "Nie możesz zapraszać ludzi.",
|
||||
"failedToAdd": "Błąd dodawania uczestników",
|
||||
"footerText": "Wybieranie numeru jest wyłączone.",
|
||||
"googleEmail": "Google",
|
||||
"inviteMoreHeader": "Jesteś jedynym uczestnikiem spotkania",
|
||||
"inviteMoreMailSubject": "Dołącz do spotkania w {{appName}}",
|
||||
"inviteMorePrompt": "Zaproś kolejne osoby",
|
||||
"linkCopied": "Skopiowano odnośnik do schowka",
|
||||
"googleEmail": "Poczta Google",
|
||||
"inviteMoreHeader": "Jesteś jedynym uczestnikiem tego spotkania",
|
||||
"inviteMoreMailSubject": "Dołącz do spotkania {{appName}}",
|
||||
"inviteMorePrompt": "Zaproś innych uczestników",
|
||||
"linkCopied": "Link skopiowany do schowka",
|
||||
"loading": "Szukaj ludzi i numerów telefonów",
|
||||
"loadingNumber": "Weryfikacja numeru telefonu",
|
||||
"loadingPeople": "Wyszukiwanie osób do zaproszenia",
|
||||
"noResults": "Brak pasujących wyników wyszukiwania",
|
||||
"noValidNumbers": "Proszę wpisać numer telefonu",
|
||||
"outlookEmail": "Outlook",
|
||||
"outlookEmail": "Poczta Outlook",
|
||||
"searchNumbers": "Dodaj numery telefonów",
|
||||
"searchPeople": "Szukaj ludzi",
|
||||
"searchPeopleAndNumbers": "Wyszukaj osoby i dodaj ich numery telefonu",
|
||||
"shareInvite": "Udostępnij zaproszenie",
|
||||
"shareLink": "Udostępnij odnośnik do spotkania",
|
||||
"shareStream": "Udostępnij odnośnik do transmisji na żywo",
|
||||
"shareInvite": "Udostępnij zaproszenie na spotkanie",
|
||||
"shareLink": "Udostępnij link do spotkania, aby zaprosić innych uczestników",
|
||||
"shareStream": "Udostępnij link transmisji na żywo",
|
||||
"telephone": "Telefon: {{number}}",
|
||||
"title": "Zaproś inne osoby do tego spotkania",
|
||||
"yahooEmail": "Yahoo"
|
||||
"title": "Zaproś uczestników na to spotkanie",
|
||||
"yahooEmail": "Poczta Yahoo"
|
||||
},
|
||||
"audioDevices": {
|
||||
"bluetooth": "Bluetooth",
|
||||
@@ -62,10 +62,10 @@
|
||||
},
|
||||
"chat": {
|
||||
"error": "Błąd: Twoja wiadomość nie została wysłana. Powód: {{error}}",
|
||||
"fieldPlaceHolder": "",
|
||||
"fieldPlaceHolder": "Wpisz wiadomość tutaj",
|
||||
"messagebox": "Wpisz wiadomość",
|
||||
"messageTo": "Prywatna wiadomość do {{recipient}}",
|
||||
"noMessagesMessage": "",
|
||||
"noMessagesMessage": "Aktualnie brak wiadomości w tym spotkaniu. Rozpocznij konwersację!",
|
||||
"nickname": {
|
||||
"popover": "Wybierz swój nick",
|
||||
"title": "Wpisz swoją nazwę, aby użyć rozmowy"
|
||||
@@ -74,8 +74,13 @@
|
||||
"title": "Rozmowa",
|
||||
"you": "Ty"
|
||||
},
|
||||
"connectingOverlay": {
|
||||
"joiningRoom": "Łączenie z Twoim spotkaniem…"
|
||||
"chromeExtensionBanner": {
|
||||
"installExtensionText": "Zainstaluj rozszerzenie integrujące Kalendarz Google i Office 365",
|
||||
"buttonText": "Zainstaluj rozszerzenie Chrome",
|
||||
"dontShowAgain": "Nie pokazuj ponownie"
|
||||
},
|
||||
"connectingOverlay": {
|
||||
"joiningRoom": "Łączenie ze spotkaniem…"
|
||||
},
|
||||
"connection": {
|
||||
"ATTACHED": "Załącznik",
|
||||
@@ -87,11 +92,10 @@
|
||||
"DISCONNECTED": "Rozłączony",
|
||||
"DISCONNECTING": "Rozłączanie",
|
||||
"ERROR": "Błąd",
|
||||
"RECONNECTING": "Wystąpił problem sieciowy. Ponowienie połączenia...",
|
||||
"FETCH_SESSION_ID": "Pobieranie identyfikators sesji...",
|
||||
"GET_SESSION_ID_ERROR": "Błąd pobierania identyfikatora sesji: {{code}}",
|
||||
"GOT_SESSION_ID": "Pobieranie identyfikators sesji... ok",
|
||||
"LOW_BANDWIDTH": "Wideo dla {{displayName}} zostało wyłączone z powodu ograniczonej przepustowości"
|
||||
"FETCH_SESSION_ID": "Uzyskiwanie id sesji...",
|
||||
"GET_SESSION_ID_ERROR": "Nie można uzyskać id sesji. Błąd: {{code}}",
|
||||
"GOT_SESSION_ID": "Uzyskiwanie id sesji... Gotowe",
|
||||
"LOW_BANDWIDTH": "Wideo {{displayName}} zostało wyłączone w celu oszczędności zasobów"
|
||||
},
|
||||
"connectionindicator": {
|
||||
"address": "Adres:",
|
||||
@@ -99,14 +103,14 @@
|
||||
"bitrate": "Szybkość transmisji:",
|
||||
"bridgeCount": "Liczba serwerów: ",
|
||||
"connectedTo": "Podłączone do:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Klatek na sekundę:",
|
||||
"less": "Pokaż mniej",
|
||||
"localaddress_0": "Adres lokalny:",
|
||||
"localaddress_1": "Adresy lokalne:",
|
||||
"localaddress_2": "Adresy lokalne:",
|
||||
"localport_0": "Port lokalny:",
|
||||
"localport_1": "Porty lokalne:",
|
||||
"localport_2": "Porty lokalne:",
|
||||
"localaddress": "Adres lokalny:",
|
||||
"localaddress_plural": "Adresy lokalne:",
|
||||
"localport": "Port lokalny:",
|
||||
"localport_plural": "Porty lokalne:",
|
||||
"maxEnabledResolution": "send max",
|
||||
"more": "Pokaż więcej",
|
||||
"packetloss": "Utrata pakietów:",
|
||||
"quality": {
|
||||
@@ -116,17 +120,14 @@
|
||||
"nonoptimal": "Nieoptymalne",
|
||||
"poor": "Słabe"
|
||||
},
|
||||
"remoteaddress_0": "Adres zdalny:",
|
||||
"remoteaddress_1": "Adresy zdalne:",
|
||||
"remoteaddress_2": "Adresy zdalne:",
|
||||
"remoteport_0": "Port zdalny:",
|
||||
"remoteport_1": "Porty zdalne:",
|
||||
"remoteport_2": "Porty zdalne:",
|
||||
"remoteaddress": "Adres zdalny:",
|
||||
"remoteaddress_plural": "Adresy zdalne:",
|
||||
"remoteport": "Port zdalny:",
|
||||
"remoteport_plural": "Porty zdalne:",
|
||||
"resolution": "Rozdzielczość:",
|
||||
"status": "Połączenie:",
|
||||
"transport_0": "Transport:",
|
||||
"transport_1": "Transporty:",
|
||||
"transport_2": "Transporty:"
|
||||
"transport": "Transport:",
|
||||
"transport_plural": "Transporty:"
|
||||
},
|
||||
"dateUtils": {
|
||||
"earlier": "Wcześniej",
|
||||
@@ -138,8 +139,10 @@
|
||||
"description": "Nic się nie wydarzyło? Spróbowaliśmy uruchomić Twoje spotkanie w aplikacji stacjonarnej {{app}}. Spróbuj ponownie lub uruchom spotkanie w aplikacji webowej {{app}}.",
|
||||
"descriptionWithoutWeb": "Nic się nie wydarzyło? Spróbowaliśmy uruchomić Twoje spotkanie w aplikacji stacjonarnej {{app}}.",
|
||||
"downloadApp": "Pobierz aplikację",
|
||||
"ifDoNotHaveApp": "Jeśli nie masz jeszcze aplikacji:",
|
||||
"ifHaveApp": "Jeśli już masz aplikację:",
|
||||
"joinInApp": "Dołącz do spotkania używając aplikacji",
|
||||
"launchWebButton": "Uruchom przez przeglądarkę",
|
||||
"openApp": "Kontynuuj w aplikacji",
|
||||
"title": "Trwa uruchamianie Twojego spotkania w {{app}}…",
|
||||
"tryAgainButton": "Spróbuj ponownie w aplikacji stacjonarnej"
|
||||
},
|
||||
@@ -161,6 +164,7 @@
|
||||
"accessibilityLabel": {
|
||||
"liveStreaming": "Transmisja na żywo"
|
||||
},
|
||||
"add": "Dodaj",
|
||||
"allow": "Pozwól",
|
||||
"alreadySharedVideoMsg": "Inny użytkownik już prezentuje wideo. Ta konferencja pozwala tylko na prezentację jednego wideo w tym samym czasie.",
|
||||
"alreadySharedVideoTitle": "Tylko jedna prezentacja wideo jest dozwolona w tym samym czasie",
|
||||
@@ -187,26 +191,24 @@
|
||||
"connecting": "Nawiązywanie połączenia",
|
||||
"contactSupport": "Skontaktuj się ze wsparciem",
|
||||
"copy": "Kopiuj",
|
||||
"copied": "Skopiowano",
|
||||
"dismiss": "Odrzuć",
|
||||
"displayNameRequired": "Cześć! Jak się nazywasz?",
|
||||
"done": "Zrobione",
|
||||
"e2eeDescription": "Wsparcie dla szyfrowania End-to-End jest obecnie EKSPERYMENTALNE. Włączenie opcji szyfrowania end-to-end uniemożliwi korzystanie z takich usług jak: nagrywanie, transmisja na żywo czy połączenia telefoniczne. Spotkanie będzie działać prawidłowo jedynie dla użytkowników posiadających przeglądarki ze wsparciem dla tego rodzaju szyfrowania.",
|
||||
"e2eeDescription": "Szyfrowanie End-to-End jest aktualnie w fazie EKSPERYMENTALNEJ. Proszę mieć na uwadze fakt, że szyfrowanie end-to-end wyłączy oferowane przez serwer usługi takie jak: nagrywanie, streaming na żywo i dołączanie uczestników przez telefon. Proszę mieć również na uwadze fakt, że takie spotkanie zadziałą tylko dla uczestników korzystających z przeglądarek wspierających wstawiane strumienie.",
|
||||
"e2eeLabel": "Klucz E2EE",
|
||||
"e2eeNoKey": "Brak klucza",
|
||||
"e2eeNoKey": "brak",
|
||||
"e2eeToggleSet": "Ustaw klucz",
|
||||
"e2eeSet": "Ustaw",
|
||||
"e2eeWarning": "UWAGA: Nie wszyscy uczestnicy tego spotkania posiadają wsparcie dla szyfrowania End-to-End. Po włączeniu tej opcji nie będa oni w stanie Cię widzieć ani słyszeć.",
|
||||
"e2eeWarning": "UWAGA: Niektórzy uczestnicy tego spotkania nie mają włączonej obsługi szyfrowania E2EE. Jeśli włączysz tą funkcję ci uczestnicy nie będą mieli z tobą kontaktu.",
|
||||
"enterDisplayName": "Wpisz tutaj swoje imię",
|
||||
"error": "Błąd",
|
||||
"externalInstallationMsg": "Zainstaluj rozszerzenie naszego współdzielenia ekranu.",
|
||||
"externalInstallationTitle": "Wymagane rozszerzenie",
|
||||
"goToStore": "Idź do sklepu",
|
||||
"gracefulShutdown": "Aktualnie serwis jest konserwowany. Prosze spróbować później.",
|
||||
"gracefulShutdown": "Usługa aktualnie jest niedostępna. Prosze spróbować później.",
|
||||
"grantModeratorDialog": "Czy na pewno chcesz przyznać temu uczestnikowi prawa moderatora?",
|
||||
"grantModeratorTitle": "Przyznaj prawa moderatora",
|
||||
"IamHost": "Jestem gospodarzem",
|
||||
"incorrectRoomLockPassword": "Hasło nieprawidłowe",
|
||||
"incorrectPassword": "Niepoprawna nazwa użytkownika lub hasło",
|
||||
"inlineInstallationMsg": "Zainstaluj rozszerzenie naszego współdzielenia ekranu.",
|
||||
"inlineInstallExtension": "Zainstaluj teraz",
|
||||
"internalError": "Ups! Coś poszło nie tak. Wystąpił następujący błąd: {{error}}",
|
||||
"internalErrorTitle": "Błąd wewnętrzny",
|
||||
"kickMessage": "Możesz skontaktować się z {{participantDisplayName}}, aby uzyskać więcej szczegółów.",
|
||||
@@ -214,7 +216,8 @@
|
||||
"kickParticipantDialog": "Czy na pewno chcesz usunąć tego uczestnika?",
|
||||
"kickParticipantTitle": "Usunąć tego uczestnika?",
|
||||
"kickTitle": "Ups! {{participantDisplayName}} usunął Cię z tego spotkania",
|
||||
"liveStreaming": "Strumień live",
|
||||
"liveStreaming": "Strumień na żywo",
|
||||
"liveStreamingDisabledBecauseOfActiveRecordingTooltip": "Nie możliwe podczas aktywnego nagrywania",
|
||||
"liveStreamingDisabledForGuestTooltip": "Goście nie mogą używać transmisji na żywo.",
|
||||
"liveStreamingDisabledTooltip": "Rozpoczęcie transmisji na żywo jest wyłączone.",
|
||||
"lockMessage": "Zabezpieczenie konferencji nie powiodło się.",
|
||||
@@ -230,6 +233,12 @@
|
||||
"micNotSendingDataTitle": "Twój mikrofon jest wyciszony przez ustawienia systemowe",
|
||||
"micPermissionDeniedError": "Nie udzieliłeś pozwolenia na użycie twojego mikrofonu. Nadal możesz uczestniczyc w konferencji ale inni nie będą cię słyszeli. Użyj przycisku kamera aby to naprawić.",
|
||||
"micUnknownError": "Z nieznanej przyczyny nie można użyć mikrofonu.",
|
||||
"muteEveryoneElseDialog": "Gdy wyciszysz wszystkich nie będziesz miał możliwości wyłączyć ich wyciszenia, ale oni będą mogli samodzielnie wyłączyć wyciszenie w dowolnym momencie.",
|
||||
"muteEveryoneElseTitle": "Wyciszyć wszystkich za wyjątkiem {{whom}}?",
|
||||
"muteEveryoneDialog": "Czy na pewno wyciszyć wszystkich? Nie będziesz miał możliwości wyłączyć ich wyciszenia, ale oni będą mogli samodzielnie wyłączyć wyciszenie w dowolnym momencie.",
|
||||
"muteEveryoneTitle": "Wyciszyć wszystkich?",
|
||||
"muteEveryoneSelf": "siebie",
|
||||
"muteEveryoneStartMuted": "Od tego momentu wszyscy są wyciszeni",
|
||||
"muteParticipantBody": "Nie możesz wyłączyć ich wyciszenia, ale oni mogą samodzielnie wyłączyć wyciszenie w dowolnym momencie.",
|
||||
"muteParticipantButton": "Wyciszenie",
|
||||
"muteParticipantDialog": "Czy na pewno wyciszyć tego uczestnika? Nie będziesz mógł wyłączyć wyciszenia uczestników, ale oni mogą samodzielnie wyłączyć wyciszenie w dowolnym momencie.",
|
||||
@@ -241,9 +250,11 @@
|
||||
"passwordRequired": "$t(lockRoomPasswordUppercase) jest wymagane",
|
||||
"popupError": "Twoja przeglądarka blokuje wyskakujące okienka pochodzące z tej witryny. Włącz wyświetlanie wyskakujących okienek w ustawieniach bezpieczeństwa Twojej przeglądarki i spróbuj ponownie.",
|
||||
"popupErrorTitle": "Wyskakujące okienko zostało zablokowane",
|
||||
"readMore": "więcej",
|
||||
"recording": "Nagrywanie",
|
||||
"recordingDisabledForGuestTooltip": "Goście nie mogą rozpocząć nagrywania.",
|
||||
"recordingDisabledTooltip": "Rozpoczęcie nagrywania wyłączone.",
|
||||
"recordingDisabledBecauseOfActiveLiveStreamingTooltip": "Nie możliwe podczas aktywnej transmisji na żywo",
|
||||
"recordingDisabledForGuestTooltip": "Goście nie mogą uruchamiać nagrywania.",
|
||||
"recordingDisabledTooltip": "Start recording disabled.",
|
||||
"rejoinNow": "Połącz ponownie teraz",
|
||||
"remoteControlAllowedMessage": "{{user}} zaakceptował Twoją prośbę o kontrolę zdalną!",
|
||||
"remoteControlDeniedMessage": "{{user}} odrzucił Twoją prośbę o kontrolę zdalną!",
|
||||
@@ -254,27 +265,26 @@
|
||||
"remoteControlTitle": "Zdalna kontrola komputera",
|
||||
"Remove": "Usuń",
|
||||
"removePassword": "Usuń $t(lockRoomPassword)",
|
||||
"removeSharedVideoMsg": "Na pewno chcesz usunąć współdzielone wideo?",
|
||||
"removeSharedVideoTitle": "Usuń wideo współdzielone",
|
||||
"removeSharedVideoMsg": "Na pewno chcesz usunąć udostępnione wideo?",
|
||||
"removeSharedVideoTitle": "Usuń wideo udostępnione",
|
||||
"reservationError": "Błąd systemu rezerwacji",
|
||||
"reservationErrorMsg": "Kod błędu: {{code}}, treść: {{msg}}",
|
||||
"retry": "Ponów",
|
||||
"screenSharingFailedToInstall": "Ups! Nie udało się zainstalować wtyczki do współdzielenia ekranu.",
|
||||
"screenSharingFailedToInstallTitle": "Nie udało się zainstalować wtyczki do współdzielenia ekranu",
|
||||
"screenSharingFirefoxPermissionDeniedError": "Coś poszło nie tak podczas próby współdzielenia Twojego ekranu. Upewnij się, że udzieliłeś zgody na tą próbę. ",
|
||||
"screenSharingFirefoxPermissionDeniedTitle": "Ups! Nie byliśmy w stanie rozpocząć współdzielenia ekranu!",
|
||||
"screenSharingPermissionDeniedError": "Ups! Coś poszło nie tak z prawami dostępu do wtyczki współdzielenia ekranu. Wczytaj ponownie i spróbuj jeszcze raz.",
|
||||
"screenSharingAudio": "Udostępnianie audio",
|
||||
"screenSharingFailed": "Oops! Coś poszło nie tak. Nie można uruchomić udostępniania ekranu!",
|
||||
"screenSharingFailedTitle": "Niepowodzenie udostępniania ekranu!",
|
||||
"screenSharingPermissionDeniedError": "Oops! Coś poszło nie tak z uprawnieniami udostępniania ekranu. Odśwież stronę i spróbuj ponownie.",
|
||||
"sendPrivateMessage": "Niedawno otrzymałeś prywatną wiadomość. Czy zamierzałeś odpowiedzieć na nią prywatnie, czy chcesz wysłać wiadomość do grupy?",
|
||||
"sendPrivateMessageCancel": "Wyślij do grupy",
|
||||
"sendPrivateMessageOk": "Wyślij prywatnie",
|
||||
"sendPrivateMessageTitle": "Wysłać prywatnie?",
|
||||
"serviceUnavailable": "Usługa jest niedostępna",
|
||||
"sessTerminated": "Połączenie przerwane",
|
||||
"Share": "Współdziel",
|
||||
"Share": "Udostępnij",
|
||||
"shareVideoLinkError": "Podaj proszę prawidłowy link youtube.",
|
||||
"shareVideoTitle": "Współdziel wideo",
|
||||
"shareYourScreen": "Włącz współdzielenie ekranu",
|
||||
"shareYourScreenDisabled": "Współdzielenie ekranu wyłączone.",
|
||||
"shareVideoTitle": "Udostępnij wideo",
|
||||
"shareYourScreen": "Włącz udostępnianie ekranu",
|
||||
"shareYourScreenDisabled": "Udostępnianie ekranu wyłączone.",
|
||||
"shareYourScreenDisabledForGuest": "Goście nie mogą współdzielić ekranu.",
|
||||
"startLiveStreaming": "Rozpocznij transmisję na żywo",
|
||||
"startRecording": "Rozpocznij nagrywanie",
|
||||
@@ -292,8 +302,8 @@
|
||||
"transcribing": "Transkrypcja",
|
||||
"unlockRoom": "Usuń spotkanie $t(lockRoomPassword)",
|
||||
"userPassword": "hasło użytkownika",
|
||||
"WaitForHostMsg": "Konferencja <b>{{room}}</b> jeszcze się nie rozpoczęła. Jeśli jesteś gospodarzem, prosimy o uwierzytelnienie. Jeśli nie, prosimy czekać na przybycie gospodarza.",
|
||||
"WaitForHostMsgWOk": "Konferencja <b>{{room}}</b> jeszcze się nie zaczęła. Jeśli jesteś jej gospodarzem, wybierz Ok, aby się uwierzytelnić. Jeśli nie, prosimy czekać na przybycie gospodarza.",
|
||||
"WaitForHostMsg": "Spotkanie <b>{{room}}</b> jeszcze się nie rozpoczęło. Jeśli jesteś gospodarzem, prosimy o uwierzytelnienie. Jeśli nie, prosimy czekać na przybycie gospodarza.",
|
||||
"WaitForHostMsgWOk": "Spotkanie <b>{{room}}</b> jeszcze się nie rozoczęło. Jeśli jesteś jej gospodarzem, wybierz Ok, aby się uwierzytelnić. Jeśli nie, prosimy czekać na przybycie gospodarza.",
|
||||
"WaitingForHost": "Oczekiwanie na gospodarza…",
|
||||
"Yes": "Tak",
|
||||
"yourEntireScreen": "Cały Twój ekran"
|
||||
@@ -302,10 +312,13 @@
|
||||
"statusMessage": "jest teraz {{status}}"
|
||||
},
|
||||
"documentSharing": {
|
||||
"title": "Współdzielony dokument"
|
||||
"title": "Udostępniony dokument"
|
||||
},
|
||||
"e2ee": {
|
||||
"labelToolTip": "Komunikacja audio i wideo dla tej rozmowy jest szyfrowana end-to-end"
|
||||
"labelToolTip": "To połączenie audio i wideo jest szyfrowane"
|
||||
},
|
||||
"embedMeeting": {
|
||||
"title": "Osadź to spotkanie"
|
||||
},
|
||||
"feedback": {
|
||||
"average": "Średnio",
|
||||
@@ -349,7 +362,7 @@
|
||||
"noRoom": "Nie podano pokoju do wdzwonienia.",
|
||||
"numbers": "Numery do wdzwonienia",
|
||||
"password": "$t(lockRoomPasswordUppercase):",
|
||||
"title": "Współdziel",
|
||||
"title": "Udostępnij",
|
||||
"tooltip": "Udostępnij odnośnik i informacje do wdzwonienia się na to spotkanie",
|
||||
"label": "Poinformuj o spotkaniu"
|
||||
},
|
||||
@@ -377,7 +390,7 @@
|
||||
"pushToTalk": "Naciśnij, aby mówić",
|
||||
"raiseHand": "Podnieś lub opuść rękę",
|
||||
"showSpeakerStats": "Pokaż statystyki mówcy",
|
||||
"toggleChat": "Otwórz lub zamknij rozmowę",
|
||||
"toggleChat": "Otwórz lub zamknij czat",
|
||||
"toggleFilmstrip": "Wyświetl lub ukryj miniaturki video",
|
||||
"toggleScreensharing": "Przełącz pomiędzy kamerą i wspóldzieleniem ekranu",
|
||||
"toggleShortcuts": "Wyświetl lub ukryj skróty klawiaturowe",
|
||||
@@ -385,6 +398,8 @@
|
||||
"videoQuality": "Zarządzanie jakością połączeń"
|
||||
},
|
||||
"liveStreaming": {
|
||||
"limitNotificationDescriptionWeb": "Ze względu na duże zapotrzebowanie twoje strumieniowanie będzie ograniczone do {{limit}} minut. Aby strumieniować bez ograniczeń wybróbuj <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"limitNotificationDescriptionNative": "Twoje strumieniowanie będzie ograniczone do {{limit}} minut. Aby strumieniować bez ograniczeń wybróbuj {{app}}.",
|
||||
"busy": "Pracujemy nad zwolnieniem zasobów transmisyjnych. Spróbuj ponownie za kilka minut.",
|
||||
"busyTitle": "Wszyscy transmitujący są aktualnie zajęci",
|
||||
"changeSignIn": "Przełącz konta.",
|
||||
@@ -393,7 +408,7 @@
|
||||
"enterStreamKey": "Wpisz tutaj swój klucz transmisji na żywo YouTube.",
|
||||
"error": "Transmitowanie na żywo nie powiodło się. Spróbuj ponownie.",
|
||||
"errorAPI": "Wystąpił błąd podczas uzyskiwania dostępu do transmisji w YouTube. Proszę spróbować zalogować się ponownie.",
|
||||
"errorLiveStreamNotEnabled": "",
|
||||
"errorLiveStreamNotEnabled": "Strumieniowanie na żywo nie jest włączone dla {{email}}. Proszę włączyć strumieniowanie na żywo lub zalogować się na konto z włączoną funkcją strumieniowania.",
|
||||
"expandedOff": "Transmisja na żywo została zatrzymana",
|
||||
"expandedOn": "Spotkanie jest obecnie transmitowane na YouTube.",
|
||||
"expandedPending": "Transmisja na żywo rozpoczyna się…",
|
||||
@@ -412,7 +427,9 @@
|
||||
"signOut": "Wyloguj się",
|
||||
"start": "Rozpocznij transmisję na żywo",
|
||||
"streamIdHelp": "Co to jest?",
|
||||
"unavailableTitle": "Transmisja na żywo jest niedostępna"
|
||||
"unavailableTitle": "Transmisja na żywo jest niedostępna",
|
||||
"youtubeTerms": "Warunki użytkowania YouTube",
|
||||
"googlePrivacyPolicy": "Polityka prywatności Google"
|
||||
},
|
||||
"localRecording": {
|
||||
"clientState": {
|
||||
@@ -424,17 +441,17 @@
|
||||
"duration": "Długość",
|
||||
"durationNA": "N/D",
|
||||
"encoding": "Kodowanie",
|
||||
"label": "",
|
||||
"label": "LOR",
|
||||
"labelToolTip": "Nagrywanie lokalne jest włączone",
|
||||
"localRecording": "Nagrywanie lokalne",
|
||||
"me": "To ja",
|
||||
"messages": {
|
||||
"engaged": "Włączono nagrywanie lokalne.",
|
||||
"finished": "",
|
||||
"finishedModerator": "",
|
||||
"finished": "Sesja nagrywania {{token}} została zakończona. Proszę przesłać nagrane pliki do moderatora.",
|
||||
"finishedModerator": "Sesja nagrywania {{token}} została zakończona. Nagranie lokalnej ścieżki zostało zapisane. Poproś pozostałych uczestników, aby przesłali swoje nagrania.",
|
||||
"notModerator": "Nie jesteś moderatorem. Nie możesz rozpoczynać i zatrzymywać lokalnego nagrywania."
|
||||
},
|
||||
"moderator": "Moderujący",
|
||||
"moderator": "Moderator",
|
||||
"no": "Nie",
|
||||
"participant": "Uczestnik",
|
||||
"participantStats": "Statystyki uczestników",
|
||||
@@ -450,10 +467,10 @@
|
||||
"connectedOneMember": "{{name}} dołączył do spotkania",
|
||||
"connectedThreePlusMembers": "{{name}} i {{count}} innych osób dołączyło do spotkania",
|
||||
"connectedTwoMembers": "{{first}} i {{second}} dołączyli do spotkania",
|
||||
"disconnected": "rozłączone",
|
||||
"disconnected": "Rozłączono",
|
||||
"focus": "Fokus konferencji",
|
||||
"focusFail": "{{component}} jest niedostępny - ponowienie w ciągu {{ms}} sec",
|
||||
"grantedTo": "Prawa moderatora przyznane {{to}}!",
|
||||
"grantedTo": "Prawa moderatora przyznane dla {{to}}!",
|
||||
"invitedOneMember": "{{name}} został zaproszony",
|
||||
"invitedThreePlusMembers": "{{name}} i {{count}} innych osób zostało zaproszone",
|
||||
"invitedTwoMembers": "{{first}} i {{second}} zostali zaproszeni",
|
||||
@@ -470,55 +487,55 @@
|
||||
"somebody": "Ktoś",
|
||||
"startSilentTitle": "Dołączyłeś bez wyjścia dźwiękowego!",
|
||||
"startSilentDescription": "Ponownie dołącz do spotkania, aby włączyć dźwięk",
|
||||
"suboptimalBrowserWarning": "",
|
||||
"suboptimalBrowserWarning": "Obawiamy się, że Twoje wrażenia ze spotkania nie będą zbyt dobre. Staramy się poprawić tą sytuację, a póki co użyj do spotkania jednej z <a href='{{recommendedBrowserPageLink}}' target='_blank'>przeglądarek w pełni obsługiwanych</a>.",
|
||||
"suboptimalExperienceTitle": "Ostrzeżenie przeglądarki",
|
||||
"unmute": "Wyłącz wyciszenie",
|
||||
"newDeviceCameraTitle": "Wykryto nową kamerę",
|
||||
"newDeviceAudioTitle": "Wykryto nowe urządzenie dźwiękowe",
|
||||
"newDeviceAction": "Użyj",
|
||||
"OldElectronAPPTitle": "Zagrożenie bezpieczeństwa!",
|
||||
"oldElectronClientDescription1": "Używasz starej wersji klienta Jitsi Meet, który posiada znane problemy bezpieczeństwa. Zaktualizuj klienta do naszej ",
|
||||
"OldElectronAPPTitle": "Luka bezpieczeństwa!",
|
||||
"oldElectronClientDescription1": "Najprawdopodobniej używasz starej wersji klienta Jitsi Meet, który jest podatny na luki bezpieczeństwa. Proszę zaktualizować do ",
|
||||
"oldElectronClientDescription2": "najnowszej wersji",
|
||||
"oldElectronClientDescription3": " teraz!"
|
||||
},
|
||||
"passwordSetRemotely": "wybrane przez innego uczestnika",
|
||||
"passwordDigitsOnly": "",
|
||||
"passwordDigitsOnly": "Do {{number}} cyfr",
|
||||
"poweredby": "napędzane dzięki",
|
||||
"prejoin": {
|
||||
"audioAndVideoError": "Błąd audio i wideo:",
|
||||
"audioOnlyError": "Błąd audio:",
|
||||
"audioTrackError": "Nie można utworzyć ścieżki audio.",
|
||||
"calling": "Dzwonię",
|
||||
"calling": "Wybieranie",
|
||||
"callMe": "Zadzwoń do mnie",
|
||||
"callMeAtNumber": "Zadzwoń do mnie pod tym numerem:",
|
||||
"callMeAtNumber": "Zadzwoń do mnie pod ten numer:",
|
||||
"configuringDevices": "Konfigurowanie urządzeń...",
|
||||
"connectedWithAudioQ": "Jesteś podłączony z audio?",
|
||||
"copyAndShare": "Skopiuj i udostępnij link spotkania",
|
||||
"dialInMeeting": "Wdzwoń się do spotkania",
|
||||
"dialInPin": "Wdzwoń się do spotkania i podej PIN:",
|
||||
"dialing": "Wdzwanianie",
|
||||
"connectedWithAudioQ": "Jesteś połączony głosowo?",
|
||||
"copyAndShare": "Kopiuj i udostępnij link spotkania",
|
||||
"dialInMeeting": "Wdzwoń się na spotkanie",
|
||||
"dialInPin": "Wdzwoń się na spotkanie i wprowadź kod PIN:",
|
||||
"dialing": "Wybieranie",
|
||||
"doNotShow": "Nie pokazuj ponownie",
|
||||
"errorDialOut": "Nie można wybrać numeru",
|
||||
"errorDialOutDisconnected": "Nie można wybrać numeru. Rozłączono",
|
||||
"errorDialOutFailed": "Nie można wybrać numeru. Błąd połączenia",
|
||||
"errorDialOutStatus": "Błąd pobierania statusu połączenia",
|
||||
"errorStatusCode": "Błąd połączenia, status: {{status}}",
|
||||
"errorValidation": "Numer jest nieprawidłowy",
|
||||
"iWantToDialIn": "Chce się wdzwonić",
|
||||
"joinAudioByPhone": "Dołącz z audio telefonu",
|
||||
"errorDialOut": "Nie udało się wybrać numeru",
|
||||
"errorDialOutDisconnected": "Nie udało się wybrać numeru. Rozłączono",
|
||||
"errorDialOutFailed": "Nie udało się wybrać numeru. Połączenie nieudane",
|
||||
"errorDialOutStatus": "Błąd podczas uzyskiwania stanu połączenia",
|
||||
"errorStatusCode": "Błąd wybierania, kod statusu: {{status}}",
|
||||
"errorValidation": "Weryfikacja numeru zakończona niepowodzeniem",
|
||||
"iWantToDialIn": "Chcę się wdzwonić",
|
||||
"joinAudioByPhone": "Dołącz przez telefon",
|
||||
"joinMeeting": "Dołącz do spotkania",
|
||||
"joinWithoutAudio": "Dołącz bez audio",
|
||||
"initiated": "Rozmowa rozpoczęta",
|
||||
"linkCopied": "Skopiowano link do schowka",
|
||||
"joinWithoutAudio": "Dołącz bez dzwięku",
|
||||
"initiated": "Połączenie zainicjowane",
|
||||
"linkCopied": "Link skopiowany do schowka",
|
||||
"lookGood": "Wygląda na to, że Twój mikrofon działa poprawnie",
|
||||
"or": "albo",
|
||||
"or": "lub",
|
||||
"premeeting": "Przed spotkaniem",
|
||||
"showScreen": "Włącz konfigurację przed spotkaniem",
|
||||
"startWithPhone": "Rozpocznij z audio telefonu",
|
||||
"screenSharingError": "Błąd współdzielenia ekranu:",
|
||||
"showScreen": "Włącz ekran Przed spotkaniem",
|
||||
"startWithPhone": "Uruchom przez telefon",
|
||||
"screenSharingError": "Błąd udostępniania ekranu:",
|
||||
"videoOnlyError": "Błąd wideo:",
|
||||
"videoTrackError": "Nie można utworzyć ścieżki wideo.",
|
||||
"viewAllNumbers": "pokaż wszystkie numery"
|
||||
"viewAllNumbers": "zobacz numery"
|
||||
},
|
||||
"presenceStatus": {
|
||||
"busy": "Zajęte",
|
||||
@@ -542,10 +559,10 @@
|
||||
},
|
||||
"raisedHand": "Chcesz się odezwać ?",
|
||||
"recording": {
|
||||
"limitNotificationDescriptionWeb": "Ze względu na duże zapotrzebowanie twoje nagranie zostanie ograniczone do {{limit}} min. Dla nieograniczonych nagrań spróbuj <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"limitNotificationDescriptionNative": "Ze względu na duże zapotrzebowanie twoje nagranie zostanie ograniczone do {{limit}} min. Dla nieograniczonych nagrań spróbuj <3>{{app}}</3>.",
|
||||
"limitNotificationDescriptionWeb": "Ze względu na duże zapotrzebowanie twoje nagrywanie będzie ograniczone do {{limit}} minut. Aby strumieniować bez ograniczeń wybróbuj <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"limitNotificationDescriptionNative": "Ze względu na duże zapotrzebowanie twoje nagrywanie będzie ograniczone do {{limit}} minut. Aby strumieniować bez ograniczeń wybróbuj <3>{{app}}</3>.",
|
||||
"authDropboxText": "Prześlij na Dropbox",
|
||||
"availableSpace": "",
|
||||
"availableSpace": "Dostępna przestrzeń: {{spaceLeft}} MB (około {{duration}} minut nagrania)",
|
||||
"beta": "BETA",
|
||||
"busy": "Pracujemy nad uwolnieniem zasobów nagrywania. Proszę spróbować ponownie za kilka minut.",
|
||||
"busyTitle": "Wszystkie urządzenia nagrywania są obecnie zajete",
|
||||
@@ -554,7 +571,7 @@
|
||||
"expandedOn": "Spotkanie jest obecnie nagrywane.",
|
||||
"expandedPending": "Nagrywanie się rozpoczyna…",
|
||||
"failedToStart": "Nagrywanie nie jest możliwe",
|
||||
"fileSharingdescription": "Współdziel nagranie z uczestnikami spotkania",
|
||||
"fileSharingdescription": "Udostępnij nagranie uczestnikom spotkania",
|
||||
"live": "NA ŻYWO",
|
||||
"loggedIn": "Zalogowano jako {{userName}}",
|
||||
"off": "Nagrywanie zatrzymane",
|
||||
@@ -567,30 +584,31 @@
|
||||
"serviceName": "Usługa nagrywania",
|
||||
"signIn": "Zaloguj się",
|
||||
"signOut": "Wyloguj się",
|
||||
"unavailable": "",
|
||||
"unavailable": "Ups! {{serviceName}} w tej chwili niedostępny. Próbujemy rozwiązać ten problem. Spróbuj ponownie później.",
|
||||
"unavailableTitle": "Nagrywanie niedostępne"
|
||||
},
|
||||
"sectionList": {
|
||||
"pullToRefresh": "Przeciągnij, aby odświeżyć"
|
||||
},
|
||||
"security": {
|
||||
"about": "Możesz ustawić $t(lockRoomPassword) do spotkania. Uczestnicy będą musieli podać $t(lockRoomPassword), aby do niego dołączyć.",
|
||||
"aboutReadOnly": "Moderatorzy mogą ustawić $t(lockRoomPassword) do spotkania. Uczestnicy będą musieli podać $t(lockRoomPassword), aby do niego dołączyć.",
|
||||
"insecureRoomNameWarning": "Pokój nie jest zabezpieczony. Niechciani uczestnicy mogą dołączyć do spotkania. Rozważ zabezpieczenie swojego pokoju w opcjach bezpieczeństwa.",
|
||||
"securityOptions": "Opcje bezpieczeństwa"
|
||||
"about": "Możesz dodać a $t(lockRoomPassword) do spotkania. Uczestnicy będą musieli wprowadzić $t(lockRoomPassword) zanim zostaną dołączeni do spotkania.",
|
||||
"aboutReadOnly": "Uczestnicy posiadający uprawnienia do moderacji mogą ustawić $t(lockRoomPassword) do spotkania. Uczestnicy będą musieli wprowadzić $t(lockRoomPassword) zanim zostaną dołączeni do spotkania.",
|
||||
"insecureRoomNameWarning": "Nazwa pokoju nie jest bezpieczna. Niepowołaniu uczestnicy mogą dołączyć do spotkania. Proszę rozważyć ustawienie hasła spotkania używając przycisku Opcje zabezpieczeń.",
|
||||
"securityOptions": "Opcje zabezpieczeń"
|
||||
},
|
||||
"settings": {
|
||||
"calendar": {
|
||||
"about": "",
|
||||
"about": "{{appName}} integracji kalendarza służy do bezpiecznego dostępu do kalendarza, aby można było odczytywać nadchodzące wydarzenia.",
|
||||
"disconnect": "Rozłącz",
|
||||
"microsoftSignIn": "Zaloguj się z Microsoft",
|
||||
"signedIn": "",
|
||||
"signedIn": "Dostęp do wydarzeń kalendarza dla {{email}}. Kliknij poniższy przycisk Rozłącz aby zatrzymać dostęp do wydarzeń kalendarza.",
|
||||
"title": "Kalendarz"
|
||||
},
|
||||
"devices": "Urządzenia",
|
||||
"followMe": "Wszyscy widzą mnie",
|
||||
"language": "Język",
|
||||
"loggedIn": "Zalogowano jako {{name}}",
|
||||
"microphones": "Mikrofony",
|
||||
"moderator": "Moderacja",
|
||||
"more": "Więcej",
|
||||
"name": "Nazwa",
|
||||
@@ -598,47 +616,49 @@
|
||||
"selectAudioOutput": "Wyjście audio",
|
||||
"selectCamera": "Kamera",
|
||||
"selectMic": "Mikrofon",
|
||||
"speakers": "Głośniki",
|
||||
"startAudioMuted": "Wycisz wszystkich dołączających",
|
||||
"startVideoMuted": "Ukryj wszystkich dołączających",
|
||||
"title": "Ustawienia"
|
||||
},
|
||||
"settingsView": {
|
||||
"advanced": "",
|
||||
"advanced": "Zaawansowane",
|
||||
"alertOk": "OK",
|
||||
"alertCancel": "Anuluj",
|
||||
"alertTitle": "Uwaga",
|
||||
"alertURLText": "Wprowadzony adres URL serwera jest nieprawidłowy",
|
||||
"buildInfoSection": "Informacja o kompilacji",
|
||||
"conferenceSection": "Konferencja",
|
||||
"disableCallIntegration": "Wyłącz natywne rozmowy",
|
||||
"disableP2P": "Wyłącz tryb Peer-to-Peer",
|
||||
"disableCrashReporting": "Wyłącz raportowanie awarii",
|
||||
"disableCrashReportingWarning": "Jesteś pewien, że chcesz wyłączyć raportowanie awarii? Ta zmiana zostanie zastosowana po zrestartowaniu aplikacji.",
|
||||
"disableCallIntegration": "Wyłącz natywną integrację połczeń tel.",
|
||||
"disableP2P": "Wyłącz tryb Peer-To-Peer",
|
||||
"disableCrashReporting": "Wyłącz raportowanie błędów",
|
||||
"disableCrashReportingWarning": "Czy na pewno chcesz wyłączyć raportowanie błędów? Ustawienie zacznie funkcjonować po restarcie aplikacji.",
|
||||
"displayName": "Wyświetlana nazwa",
|
||||
"email": "E-mail",
|
||||
"header": "Ustawienia",
|
||||
"profileSection": "Profil",
|
||||
"serverURL": "Adres URL serwera",
|
||||
"showAdvanced": "Zaawansowane ustawienia",
|
||||
"showAdvanced": "Pokaż ustawienia zawansowane",
|
||||
"startWithAudioMuted": "Rozpocznij z wyciszonym dźwiękiem",
|
||||
"startWithVideoMuted": "Rozpocznij z wyłączonym obrazem",
|
||||
"version": "Wersja"
|
||||
},
|
||||
"share": {
|
||||
"dialInfoText": "",
|
||||
"dialInfoText": "\n\n=====\n\nChcesz wdzwonić się ze swojego telefonu?\n\n{{defaultDialInNumber}}Kliknij w ten link aby zobaczyć numery wdzwaniania na to spotkanie\n{{dialInfoPageUrl}}",
|
||||
"mainText": "Kliknij na poniższy odnośnik, aby dołączyć do spotkania:\n{{roomUrl}}"
|
||||
},
|
||||
"speaker": "Głośnik",
|
||||
"speaker": "Mówca",
|
||||
"speakerStats": {
|
||||
"hours": "{{count}} godz.",
|
||||
"minutes": "{{count}} min.",
|
||||
"name": "Nazwa",
|
||||
"seconds": "{{count}} sek.",
|
||||
"speakerStats": "Statystyki mówców",
|
||||
"speakerTime": ""
|
||||
"speakerTime": "Czas mówcy"
|
||||
},
|
||||
"startupoverlay": {
|
||||
"policyText": " ",
|
||||
"title": "{{app}} potrzebuje używać Twojego mikrofonu i kamery."
|
||||
"title": "{{app}} potrzebuje używać Twój mikrofon i kamerę."
|
||||
},
|
||||
"suspendedoverlay": {
|
||||
"rejoinKeyTitle": "Dołącz ponownie",
|
||||
@@ -654,15 +674,16 @@
|
||||
"chat": "Przełączanie okna rozmowy",
|
||||
"document": "Przełączanie wspólnego dokumentu",
|
||||
"download": "Pobierz nasze aplikacje",
|
||||
"embedMeeting": "Osadź spotkanie",
|
||||
"e2ee": "Szyfrowanie End-to-End",
|
||||
"feedback": "Zostaw swoją opinię",
|
||||
"fullScreen": "Przełączanie trybu pełnoekranowego",
|
||||
"grantModerator": "Przydziel uprawnienia moderatora",
|
||||
"hangup": "Opuść rozmowę",
|
||||
"grantModerator": "Przyznaj prawa moderowania",
|
||||
"hangup": "Zostaw rozmowę",
|
||||
"help": "Pomoc",
|
||||
"invite": "Zapraszaj ludzi",
|
||||
"invite": "Zaproś uczestników",
|
||||
"kick": "Usuń uczestnika",
|
||||
"lobbyButton": "Włącz/wyłącz lobby",
|
||||
"lobbyButton": "Włącz/wyłącz tryb lobby",
|
||||
"localRecording": "Przełączanie lokalnych urządzeń sterujących zapisem danych",
|
||||
"lockRoom": "Przełączenie hasła spotkania",
|
||||
"moreActions": "Przełączanie menu więcej działań",
|
||||
@@ -673,44 +694,46 @@
|
||||
"pip": "Tryb przełączania obrazu-w-obrazie",
|
||||
"privateMessage": "Wyślij wiadomość prywatną",
|
||||
"profile": "Edytuj swój profil",
|
||||
"raiseHand": "Podnieś / Opuść rękę",
|
||||
"raiseHand": "Przełączyć rękę w górę",
|
||||
"recording": "Przełączanie nagrywania",
|
||||
"remoteMute": "Wycisz uczestnika",
|
||||
"security": "Opcje bezpieczeństwa",
|
||||
"Settings": "Ustawienia",
|
||||
"security": "Opcje zabezpieczeń",
|
||||
"Settings": "Ustawienia przełączania",
|
||||
"sharedvideo": "Przełącz udostępnianie obrazu na YouTube",
|
||||
"shareRoom": "Zaproś kogoś",
|
||||
"shareYourScreen": "Współdziel ekran",
|
||||
"shortcuts": "Wyświetl skróty",
|
||||
"show": "",
|
||||
"speakerStats": "Statystyki mówców",
|
||||
"tileView": "Widok kafelkowy",
|
||||
"shareYourScreen": "Przełączanie podziału ekranu",
|
||||
"shortcuts": "Przełączanie skrótów klawiszowych",
|
||||
"show": "Pokaż na scenie",
|
||||
"speakerStats": "Przełączanie statystyk dotyczących mówców",
|
||||
"tileView": "Przełącz widok kafelkowy",
|
||||
"toggleCamera": "Przełączanie kamery",
|
||||
"videomute": "Włącz / Wyłącz kamerę",
|
||||
"videoblur": "Włącz / Wyłącz rozmazanie obrazu"
|
||||
"toggleFilmstrip": "Przełącz filmstrip",
|
||||
"videomute": "Przełączanie wyciszonego filmu wideo",
|
||||
"videoblur": "Przełącz rozmazanie obrazu"
|
||||
},
|
||||
"addPeople": "Dodaj ludzi do swojego telefonu",
|
||||
"addPeople": "Dodaj ludzi do swojej rozmowy",
|
||||
"audioOnlyOff": "Wyłącz tryb słabego łącza",
|
||||
"audioOnlyOn": "Włącz tryb słabego łącza",
|
||||
"audioRoute": "Wybierz urządzenie dźwiękowe",
|
||||
"authenticate": "Uwierzytelnianie",
|
||||
"callQuality": "Zarządzanie jakością obrazu",
|
||||
"chat": "Otwórz / Zamknij rozmowę",
|
||||
"closeChat": "Zamknij rozmowę",
|
||||
"documentClose": "Zamknij wspólny dokument",
|
||||
"documentOpen": "Otwarty współdzielony dokument",
|
||||
"chat": "Otwórz / Zamknij okno czatu",
|
||||
"closeChat": "Zamknij czat",
|
||||
"documentClose": "Zamknij udostępniony dokument",
|
||||
"documentOpen": "Otwarty udostępniony dokument",
|
||||
"download": "Pobierz nasze aplikacje",
|
||||
"e2ee": "Szyfrowanie End-to-End",
|
||||
"enterFullScreen": "Wyświetlanie pełnego ekranu",
|
||||
"enterTileView": "Wejdź w kafelkowy widok",
|
||||
"exitFullScreen": "Wyświetlanie pełnego ekranu",
|
||||
"exitTileView": "Wyjdź z kafelkowego widoku",
|
||||
"embedMeeting": "Osadź spotkanie",
|
||||
"enterFullScreen": "Wyświetl na pełnym ekranie",
|
||||
"enterTileView": "Wyświetl widok kafelkowy",
|
||||
"exitFullScreen": "Zamknij pełny ekran",
|
||||
"exitTileView": "Zamknij widok kafelkowy",
|
||||
"feedback": "Zostaw swoją opinię",
|
||||
"hangup": "Opuść",
|
||||
"hangup": "Opuść spotkanie",
|
||||
"help": "Pomoc",
|
||||
"invite": "Zapraszaj ludzi",
|
||||
"lobbyButtonDisable": "Wyłącz lobby",
|
||||
"lobbyButtonEnable": "Włącz lobby",
|
||||
"invite": "Zaproś uczestników",
|
||||
"lobbyButtonDisable": "Wyłącz tryb lobby",
|
||||
"lobbyButtonEnable": "Włącz tryb lobby",
|
||||
"login": "Zaloguj",
|
||||
"logout": "Wyloguj",
|
||||
"lowerYourHand": "Opuść rękę",
|
||||
@@ -721,17 +744,17 @@
|
||||
"noAudioSignalTitle": "Brak sygnału audio!",
|
||||
"noAudioSignalDesc": "Jeżeli celowo nie wyciszyłeś mikrofonu w ustawieniach systemowych spróbuj innego urządzenia.",
|
||||
"noAudioSignalDescSuggestion": "Jeżeli celowo nie wyciszyłeś mikrofonu w ustawieniach systemowych spróbuj sugerowanego urządzenia.",
|
||||
"noAudioSignalDialInDesc": "Wdzwoń się używając:",
|
||||
"noAudioSignalDialInLinkDesc": "Numery",
|
||||
"noisyAudioInputTitle": "Twój mikrofon wydaje się być hałaśliwy!",
|
||||
"noisyAudioInputDesc": "Twój mikrofon wydaje się hałaśliwy, wycisz mikrofon albo zmień urządzenie.",
|
||||
"openChat": "Otwórz rozmowę",
|
||||
"noAudioSignalDialInDesc": "Możesz się również wdzwonić korzystając z numerów:",
|
||||
"noAudioSignalDialInLinkDesc": "Numery wdzwaniania",
|
||||
"noisyAudioInputTitle": "Twój mikrofon powoduje zakłócenia!",
|
||||
"noisyAudioInputDesc": "Wygląda na to, że Twój mikrofon powoduje zakłócenia.",
|
||||
"openChat": "Otwórz czat",
|
||||
"pip": "Wprowadź tryb obrazu w obrazie",
|
||||
"privateMessage": "Wyślij wiadomość prywatną",
|
||||
"profile": "Edytuj swój profil",
|
||||
"raiseHand": "Podnieś / Opuść rękę",
|
||||
"raiseYourHand": "Podnieś rękę",
|
||||
"security": "Opcje bezpieczeństwa",
|
||||
"security": "Opcje zabezpieczeń",
|
||||
"Settings": "Ustawienia",
|
||||
"sharedvideo": "Udostępnij wideo z Youtube",
|
||||
"shareRoom": "Zaproś kogoś",
|
||||
@@ -751,7 +774,7 @@
|
||||
},
|
||||
"transcribing": {
|
||||
"ccButtonTooltip": "Uruchom / Zatrzymaj napisy",
|
||||
"error": "Przepisywanie się nie powiodło. Proszę spróbować ponownie.",
|
||||
"error": "Przepisywanie nie powiodło się. Proszę spróbować ponownie.",
|
||||
"expandedLabel": "Transkrypcja jest obecnie włączona",
|
||||
"failedToStart": "Błąd uruchomienia transkrypcji",
|
||||
"labelToolTip": "Spotkanie jest transkrybowane",
|
||||
@@ -774,7 +797,7 @@
|
||||
"safariGrantPermissions": "Wybierz <b><i>OK</i></b>, gdy przegladarka zapyta o pozwolenie."
|
||||
},
|
||||
"videoSIPGW": {
|
||||
"busy": "",
|
||||
"busy": "Pracujemy nad uwolnieniem zasobów. Prosimy spróbować za kilka minut.",
|
||||
"busyTitle": "Usługa pokoju jest obecnie zajęta",
|
||||
"errorAlreadyInvited": "{{displayName}} jest już zaproszony",
|
||||
"errorInvite": "Konferencja nie została jeszcze ustanowiona. Prosimy spróbować ponownie później.",
|
||||
@@ -803,13 +826,15 @@
|
||||
},
|
||||
"videothumbnail": {
|
||||
"domute": "Wyciszenie",
|
||||
"domuteOthers": "Wycisz pozostałych",
|
||||
"flip": "Odwrócenie",
|
||||
"grantModerator": "Przyznaj prawa moderatora",
|
||||
"kick": "Wyrzuć",
|
||||
"moderator": "Moderujący",
|
||||
"moderator": "Moderator",
|
||||
"mute": "Uczestnik ma wyciszone audio",
|
||||
"muted": "Wyciszony",
|
||||
"remoteControl": "Kontrola zdalna",
|
||||
"show": "",
|
||||
"show": "Pokaż na scenie",
|
||||
"videomute": "Uczestnik zatrzymał kamerę"
|
||||
},
|
||||
"welcomepage": {
|
||||
@@ -824,31 +849,32 @@
|
||||
},
|
||||
"calendar": "Kalendarz",
|
||||
"connectCalendarButton": "Podłącz swój kalendarz",
|
||||
"connectCalendarText": "",
|
||||
"connectCalendarText": "Podłącz swój kalendarz aby przeglądać wszystkie Twoje spotkania w {{app}}. Dodaj spotkania {{provider}} do swojego kalendarza i uruchamiaj je jednym kliknięciem.",
|
||||
"enterRoomTitle": "Rozpocznij nowe spotkanie",
|
||||
"getHelp": "Pomoc",
|
||||
"roomNameAllowedChars": "Nazwa spotkania nie powinna zawierać żadnego z tych znaków: ?, &, :, ', \", %, #.",
|
||||
"go": "IDŹ",
|
||||
"goSmall": "IDŹ",
|
||||
"join": "Stwórz / Dołącz",
|
||||
"go": "Dalej",
|
||||
"goSmall": "Dalej",
|
||||
"info": "Informacje",
|
||||
"join": "Utwórz / Dołącz",
|
||||
"moderatedMessage": "lub <a href=\"{{url}}\" rel=\"noopener noreferrer\" target=\"_blank\">zarezerwuj adres spotkania</a> jeśli jesteś jedynym moderatorem.",
|
||||
"privacy": "Polityka prywatności",
|
||||
"recentList": "Niedawno",
|
||||
"recentListDelete": "Usuń",
|
||||
"recentListEmpty": "Twoja ostatnia lista jest obecnie pusta. Rozmawiaj ze swoim zespołem, a wszystkie ostatnie spotkania znajdziesz tutaj.",
|
||||
"reducedUIText": "Witamy w {{app}}!",
|
||||
"roomNameAllowedChars": "Nazwa spotkania nie powinna zawierać znaków: ?, &, :, ', \", %, #.",
|
||||
"roomname": "Podaj nazwę sali konferencyjnej",
|
||||
"roomnameHint": "Wprowadź nazwę lub adres URL pokoju, do którego chcesz dołączyć. Możesz wymyślić nazwę, po prostu pozwól, aby osoby, z którymi się spotykasz, znały ją tak, aby wpisały tę samą nazwę.",
|
||||
"sendFeedback": "Wyślij opinię",
|
||||
"terms": "Warunki korzystania",
|
||||
"title": "Bezpieczna, w pełni funkcjonalna i całkowicie bezpłatna wideokonferencja"
|
||||
},
|
||||
},
|
||||
"lonelyMeetingExperience": {
|
||||
"button": "Zaproś",
|
||||
"youAreAlone": "Jesteś jedyną osobą na spotkaniu"
|
||||
"button": "Zaproś innych uczestników",
|
||||
"youAreAlone": "Tylko ty uczestniczysz w tym spotkaniu"
|
||||
},
|
||||
"helpView": {
|
||||
"header": "Pomoc"
|
||||
"header": "Centrum pomocy"
|
||||
},
|
||||
"lobby": {
|
||||
"knockingParticipantList": "Oczekujący uczestnicy",
|
||||
|
||||
@@ -269,7 +269,7 @@
|
||||
"userPassword": "senha do usuário",
|
||||
"WaitForHostMsg": "A conferência <b>{{room}}</b> ainda não começou. Se você é o anfitrião, faça a autenticação. Do contrário, aguarde a chegada do anfitrião.",
|
||||
"WaitForHostMsgWOk": "A conferência <b>{{room}}</b> ainda não começou. Se você é o anfitrião, pressione Ok para autenticar. Do contrário, aguarde a chegada do anfitrião.",
|
||||
"WaitingForHost": "Esperando o hospedeiro...",
|
||||
"WaitingForHost": "Esperando o anfitrião...",
|
||||
"Yes": "Sim",
|
||||
"yourEntireScreen": "Toda sua tela",
|
||||
"screenSharingAudio": "Compartilhar áudio",
|
||||
|
||||
@@ -1,28 +1,43 @@
|
||||
{
|
||||
"addPeople": {
|
||||
"add": "Пригласить",
|
||||
"addContacts": "Пригласите других людей",
|
||||
"copyInvite": "Скопировать приглашение на встречу",
|
||||
"copyLink": "Скопировать ссылку на встречу",
|
||||
"copyStream": "Скопировать ссылку на прямую транасляцию",
|
||||
"countryNotSupported": "Эта страна пока не поддерживается.",
|
||||
"countryReminder": "Вызов не в США? Пожалуйста, убедитесь, что указали код страны!",
|
||||
"defaultEmail": "Ваш адрес электронной почты",
|
||||
"disabled": "Поиск не дал результата.",
|
||||
"failedToAdd": "Не удалось добавить участников",
|
||||
"footerText": "Вызов номера отключен.",
|
||||
"googleEmail": "Электронная почта Google",
|
||||
"inviteMoreHeader": "Сейчас вы одни в этой встрече",
|
||||
"inviteMoreMailSubject": "Присоединиться к встрече {{appName}} ",
|
||||
"inviteMorePrompt": "Пригласить других людей",
|
||||
"linkCopied": "Ссылка скопирована в буфер обмена",
|
||||
"loading": "Поиск людей и номеров телефонов",
|
||||
"loadingNumber": "Проверка номера телефона",
|
||||
"loadingPeople": "Поиск людей для приглашения",
|
||||
"noResults": "Поиск не дал результата",
|
||||
"noValidNumbers": "Пожалуйста, введите номер телефона",
|
||||
"outlookEmail": "Электронная почта Outlook",
|
||||
"searchNumbers": "Добавить номера телефонов",
|
||||
"searchPeople": "Поиск людей",
|
||||
"searchPeopleAndNumbers": "Поиск людей или добавление их телефонов",
|
||||
"shareInvite": "Поделиться приглашением на встречу",
|
||||
"shareLink": "Поделиться ссылкой на встречу чтобы пригласить других",
|
||||
"shareStream": "Поделиться ссылкой на прямую трансляцию",
|
||||
"telephone": "Номер: {{number}}",
|
||||
"title": "Пригласить людей на эту встречу"
|
||||
"title": "Пригласить людей на эту встречу",
|
||||
"yahooEmail": "Электронная почта Yahoo"
|
||||
},
|
||||
"audioDevices": {
|
||||
"bluetooth": "Bluetooth",
|
||||
"headphones": "Наушники",
|
||||
"none": "Не обнаружены звуковые устройства",
|
||||
"phone": "Телефон",
|
||||
"speaker": "Колонка",
|
||||
"none": "Не обнаружены звуковые устройства"
|
||||
"speaker": "Колонка"
|
||||
},
|
||||
"audioOnly": {
|
||||
"audioOnly": "Только звук"
|
||||
@@ -48,21 +63,21 @@
|
||||
"chat": {
|
||||
"error": "Ошибка: Ваше сообщение не было отправлено. Причина: {{error}}",
|
||||
"fieldPlaceHolder": "Введите здесь ваше сообщение",
|
||||
"messagebox": "Введите сообщение",
|
||||
"messageTo": "Личное сообщение пользователю {{recipient}}",
|
||||
"noMessagesMessage": "В конференции пока нет никаких сообщений. Начните разговор!",
|
||||
"messagebox": "Введите сообщение",
|
||||
"nickname": {
|
||||
"popover": "Выберите имя",
|
||||
"title": "Введите имя для использования чата"
|
||||
},
|
||||
"noMessagesMessage": "В конференции пока нет никаких сообщений. Начните разговор!",
|
||||
"privateNotice": "Личное сообщение пользователю {{recipient}}",
|
||||
"title": "Чат",
|
||||
"you": "вы"
|
||||
},
|
||||
"chromeExtensionBanner": {
|
||||
"installExtensionText": "Установите расширение для интеграции с Google Календарь и Office 365",
|
||||
"buttonText": "Установить расширение Chrome",
|
||||
"dontShowAgain": "Не показывай мне это снова"
|
||||
"dontShowAgain": "Не показывай мне это снова",
|
||||
"installExtensionText": "Установите расширение для интеграции с Google Календарь и Office 365"
|
||||
},
|
||||
"connectingOverlay": {
|
||||
"joiningRoom": "Пытаемся присоединиться к вашей конференции..."
|
||||
@@ -77,10 +92,11 @@
|
||||
"DISCONNECTED": "Отключено",
|
||||
"DISCONNECTING": "Отключение",
|
||||
"ERROR": "Ошибка",
|
||||
"RECONNECTING": "Проблема с сетью. Переподключение...",
|
||||
"FETCH_SESSION_ID": "Получение идентификатора сеанса…",
|
||||
"GET_SESSION_ID_ERROR": "Ошибка получения идентификатора сеанса: {{code}}",
|
||||
"GOT_SESSION_ID": "Получение идентификатора сеанса… Готово",
|
||||
"LOW_BANDWIDTH": "Видео для {{displayName}} приостановлено из-за низкой пропускной способности",
|
||||
"GOT_SESSION_ID": "Получение идентификатора сеанса … Готово",
|
||||
"GET_SESSION_ID_ERROR": "Ошибка получения идентификатора сеанса: {{code}}"
|
||||
"RECONNECTING": "Проблема с сетью. Переподключение..."
|
||||
},
|
||||
"connectionindicator": {
|
||||
"address": "Адрес:",
|
||||
@@ -115,8 +131,7 @@
|
||||
"status": "Связь:",
|
||||
"transport_0": "Метод отправки:",
|
||||
"transport_1": "Метода отправки:",
|
||||
"transport_2": "Методов отправки:",
|
||||
"e2e_rtt": ""
|
||||
"transport_2": "Методов отправки:"
|
||||
},
|
||||
"dateUtils": {
|
||||
"earlier": "Ранее",
|
||||
@@ -128,6 +143,9 @@
|
||||
"description": "Ничего не случилось? Мы попытались запустить вашу встречу в настольном приложении {{app}}. Повторите попытку или запустите ее в веб-приложении {{app}}.",
|
||||
"descriptionWithoutWeb": "Ничего не произошло? Мы попытались запустить вашу конференцию в настольном приложении {{app}}",
|
||||
"downloadApp": "Скачать приложение",
|
||||
"ifDoNotHaveApp": "Если у вас еще нет приложения:",
|
||||
"ifHaveApp": "Если вы уже установили приложение:",
|
||||
"joinInApp": "Подключиться к этой встрече используя приложение",
|
||||
"launchWebButton": "Запустить в браузере",
|
||||
"openApp": "Перейти к приложению",
|
||||
"title": "Запуск вашей встречи в {{app}}...",
|
||||
@@ -147,15 +165,29 @@
|
||||
"selectADevice": "Выбор устройства",
|
||||
"testAudio": "Протестировать звук"
|
||||
},
|
||||
"dialOut": {
|
||||
"statusMessage": "сейчас {{status}}"
|
||||
},
|
||||
"dialog": {
|
||||
"Back": "Назад",
|
||||
"Cancel": "Отмена",
|
||||
"IamHost": "Я организатор",
|
||||
"Ok": "Ok",
|
||||
"Remove": "Удалить",
|
||||
"Share": "Поделиться",
|
||||
"Submit": "ОК",
|
||||
"WaitForHostMsg": "Конференция <b>{{room}}</b> еще не началась. Если вы организатор, пожалуйста, авторизируйтесь. В противном случае дождитесь организатора.",
|
||||
"WaitForHostMsgWOk": "Конференция <b>{{room}}</b> еще не началась. Если вы организатор, пожалуйста, нажмите Ok для аутентификации. В противном случае, дождитесь организатора.",
|
||||
"WaitingForHost": "Ждем организатора...",
|
||||
"Yes": "Да",
|
||||
"accessibilityLabel": {
|
||||
"liveStreaming": "Трансляция"
|
||||
},
|
||||
"add": "Добавить",
|
||||
"allow": "Разрешить",
|
||||
"alreadySharedVideoMsg": "Другой участник уже поделился ссылкой на видео. Данная конференция позволяет одновременно делиться только одним видео.",
|
||||
"alreadySharedVideoTitle": "Допускается показ только одного видео",
|
||||
"applicationWindow": "Окно приложения",
|
||||
"Back": "Назад",
|
||||
"cameraConstraintFailedError": "Камера не отвечает определенным требованиям.",
|
||||
"cameraNotFoundError": "Камера не обнаружена.",
|
||||
"cameraNotSendingData": "Ошибка доступа к камере. Пожалуйста, проверьте, не использует ли камеру какая-нибудь другая программа. Вы можете также выбрать другое устройство из меню настроек или попробовать перезапустить приложение.",
|
||||
@@ -163,7 +195,6 @@
|
||||
"cameraPermissionDeniedError": "Нет доступа к камере. Вы можете участвовать во встрече, но другие не будут вас видеть. Используйте значок камеры в адресной строке браузера, чтобы устранить проблему.",
|
||||
"cameraUnknownError": "Неизвестная ошибка использования камеры.",
|
||||
"cameraUnsupportedResolutionError": "Ваша камера не поддерживает необходимое разрешение видео.",
|
||||
"Cancel": "Отмена",
|
||||
"close": "Закрыть",
|
||||
"conferenceDisconnectMsg": "Следует проверить интернет-соединение. Попытка восстановления связи через {{seconds}} с.",
|
||||
"conferenceDisconnectTitle": "Вы отключены.",
|
||||
@@ -176,21 +207,29 @@
|
||||
"connectErrorWithMsg": "Ошибка. Невозможно установить связь для вашей встречи: {{msg}}",
|
||||
"connecting": "Подключение",
|
||||
"contactSupport": "Связь с поддержкой",
|
||||
"copied": "Скопировано",
|
||||
"copy": "Копировать",
|
||||
"dismiss": "Отклонить",
|
||||
"displayNameRequired": "Привет! Как тебя зовут?",
|
||||
"done": "Готово",
|
||||
"e2eeDescription": "Сквозное шифрование в настоящее время является ЭКСПЕРИМЕНТАЛЬНЫМ. Имейте в виду, что включение сквозного шифрования эффективно отключит сервисы, предоставляемые на стороне сервера, такие как: запись, потоковое вещание и участие по телефону. Также имейте в виду, что собрание будет работать только для людей, присоединяющихся из браузеров с поддержкой вставляемых потоков.",
|
||||
"e2eeLabel": "E2EE ключ",
|
||||
"e2eeNoKey": "Отсутствует",
|
||||
"e2eeSet": "Установить",
|
||||
"e2eeToggleSet": "Установить ключ",
|
||||
"e2eeWarning": "ПРЕДУПРЕЖДЕНИЕ. Похоже, что не все участники этой встречи поддерживают сквозное шифрование. Если вы включите его, они не смогут вас ни видеть, ни слышать.",
|
||||
"enterDisplayName": "Пожалуйста, введите свое имя",
|
||||
"error": "Ошибка",
|
||||
"externalInstallationMsg": "Вам необходимо установить наше дополнение для совместного использования рабочего стола.",
|
||||
"externalInstallationTitle": "Требуется расширение",
|
||||
"goToStore": "Перейти к интернет-магазину",
|
||||
"gracefulShutdown": "Технические работы. Пожалуйста, попробуйте позже.",
|
||||
"IamHost": "Я организатор",
|
||||
"incorrectRoomLockPassword": "Неверный пароль",
|
||||
"grantModeratorDialog": "Вы уверены, что хотите сделать этого участника модератором?",
|
||||
"grantModeratorTitle": "Сделать модератором",
|
||||
"incorrectPassword": "Ошибка имени пользователя или пароля",
|
||||
"inlineInstallationMsg": "Вам необходимо установить наше дополнение для совместного использования рабочего стола.",
|
||||
"incorrectRoomLockPassword": "Неверный пароль",
|
||||
"inlineInstallExtension": "Установить",
|
||||
"inlineInstallationMsg": "Вам необходимо установить наше дополнение для совместного использования рабочего стола.",
|
||||
"internalError": "Что-то пошло не так. Ошибка: {{error}}",
|
||||
"internalErrorTitle": "Внутренняя ошибка",
|
||||
"kickMessage": "Вы можете связаться с {{participantDisplayName}} для получения более подробной информации.",
|
||||
@@ -199,6 +238,7 @@
|
||||
"kickParticipantTitle": "Выгнать этого участника?",
|
||||
"kickTitle": "Ай! {{participantDisplayName}} выгнал вас из конференции.",
|
||||
"liveStreaming": "Трансляция",
|
||||
"liveStreamingDisabledBecauseOfActiveRecordingTooltip": "Невозможно пока активна запись",
|
||||
"liveStreamingDisabledForGuestTooltip": "Гости не могут начать трансляцию",
|
||||
"liveStreamingDisabledTooltip": "Возможность трансляции отключена",
|
||||
"lockMessage": "Не удалось запереть конференцию",
|
||||
@@ -214,18 +254,25 @@
|
||||
"micNotSendingDataTitle": "Ваш микрофон отключен системными настройками",
|
||||
"micPermissionDeniedError": "Нет доступа к микрофону. Вы можете участвовать во встрече, но другие не будут вас слышать. Используйте значок камеры в адресной строке браузера, чтобы устранить проблему.",
|
||||
"micUnknownError": "Неизвестная ошибка использования микрофона.",
|
||||
"muteParticipantBody": "Вы не можете включить им звук, но они могут сделать это сами в любое время.",
|
||||
"muteParticipantButton": "Выключить звук",
|
||||
"muteEveryoneDialog": "Вы уверены, что хотите отключить микрофоны у всех? Вы не сможете включить их, но они могут включить себя в любой момент.",
|
||||
"muteEveryoneElseDialog": "После отключения микрофонов у участников вы не сможете включить их, но они могут включить себя в любой момент.",
|
||||
"muteEveryoneElseTitle": "Заглушить всех, за исключением {{whom}}?",
|
||||
"muteEveryoneSelf": "себя",
|
||||
"muteEveryoneStartMuted": "Теперь у всех микрофоны выключены",
|
||||
"muteEveryoneTitle": "Заглушить всех?",
|
||||
"muteParticipantBody": "Вы не можете включить им микрофон, но они могут сделать это сами в любое время.",
|
||||
"muteParticipantButton": "Заглушить",
|
||||
"muteParticipantDialog": "Вы уверены, что хотите отключить микрофон у данного пользователя? Вы не сможете отменить это действие, однако он сможет сам снова включить микрофон в любое время.",
|
||||
"muteParticipantTitle": "Приглушить этого участника?",
|
||||
"Ok": "Ok",
|
||||
"passwordLabel": "$t(lockRoomPasswordUppercase)",
|
||||
"muteParticipantTitle": "Заглушить этого участника?",
|
||||
"passwordLabel": "Встреча была защищена участником. Пожалуйста, введите $t(lockRoomPasswordUppercase) чтобы присоединиться.",
|
||||
"passwordNotSupported": "Установка $t(lockRoomPassword) для конференции не поддерживается.",
|
||||
"passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) не поддерживается",
|
||||
"passwordRequired": "Требуется $t(lockRoomPasswordUppercase)",
|
||||
"popupError": "Ваш браузер блокирует всплывающие окна этого сайта. Пожалуйста, разрешите всплывающие окна в настройках безопасности браузера и попробуйте снова.",
|
||||
"popupErrorTitle": "Заблокировано всплывающее окно",
|
||||
"readMore": "больше",
|
||||
"recording": "Запись",
|
||||
"recordingDisabledBecauseOfActiveLiveStreamingTooltip": "Невозможно пока активно потоковое вещание",
|
||||
"recordingDisabledForGuestTooltip": "Гости не могут записывать",
|
||||
"recordingDisabledTooltip": "Невозможно начать запись",
|
||||
"rejoinNow": "Подключиться снова",
|
||||
@@ -236,13 +283,15 @@
|
||||
"remoteControlShareScreenWarning": "Если нажмете \"Разрешить\", то поделитесь своим экраном!",
|
||||
"remoteControlStopMessage": "Сессия удаленного управления завершена!",
|
||||
"remoteControlTitle": "Удаленное управление рабочим столом",
|
||||
"Remove": "Удалить",
|
||||
"removePassword": "Убрать $t(lockRoomPassword)",
|
||||
"removeSharedVideoMsg": "Уверены, что хотите убрать видео, которым поделились?",
|
||||
"removeSharedVideoTitle": "Убрать видео",
|
||||
"reservationError": "Ошибка системы резервирования",
|
||||
"reservationErrorMsg": "Код ошибки: {{code}}, сообщение: {{msg}}",
|
||||
"retry": "Повторить",
|
||||
"screenSharingAudio": "Поделиться аудио",
|
||||
"screenSharingFailed": "Ой! Кажется что-то пошло не так, мы не можем начать показ экрана!",
|
||||
"screenSharingFailedTitle": "Сбой показа экрана!",
|
||||
"screenSharingFailedToInstall": "Ошибка установки расширения для показа экрана.",
|
||||
"screenSharingFailedToInstallTitle": "Расширение для показа экрана не установлено",
|
||||
"screenSharingFirefoxPermissionDeniedError": "Что-то пошло не так, когда мы пытались поделиться вашим экраном. Пожалуйста, убедитесь, что вы дали нам разрешение на это. ",
|
||||
@@ -254,7 +303,6 @@
|
||||
"sendPrivateMessageTitle": "Отправить личное сообщение?",
|
||||
"serviceUnavailable": "Служба недоступна",
|
||||
"sessTerminated": "Связь прервана",
|
||||
"Share": "Поделиться",
|
||||
"shareVideoLinkError": "Пожалуйста, укажите корректную ссылку Youtube.",
|
||||
"shareVideoTitle": "Поделиться видео",
|
||||
"shareYourScreen": "Показать экран",
|
||||
@@ -268,7 +316,6 @@
|
||||
"stopRecordingWarning": "Уверены, что хотите остановить запись?",
|
||||
"stopStreamingWarning": "Уверены, что хотите остановить трансляцию?",
|
||||
"streamKey": "Ключ трансляции",
|
||||
"Submit": "ОК",
|
||||
"thankYou": "Спасибо, что используете {{appName}}!",
|
||||
"token": "токен",
|
||||
"tokenAuthFailed": "Извините, вам не разрешено присоединиться к этому сеансу связи.",
|
||||
@@ -276,21 +323,17 @@
|
||||
"transcribing": "Расшифровка",
|
||||
"unlockRoom": "Убрать $t(lockRoomPassword)",
|
||||
"userPassword": "пароль пользователя",
|
||||
"WaitForHostMsg": "Конференция <b>{{room}}</b> еще не началась. Если вы организатор, пожалуйста, авторизируйтесь. В противном случае дождитесь организатора.",
|
||||
"WaitForHostMsgWOk": "Конференция <b>{{room}}</b> еще не началась. Если вы организатор, пожалуйста, нажмите Ok для аутентификации. В противном случае, дождитесь организатора.",
|
||||
"WaitingForHost": "Ждем организатора...",
|
||||
"Yes": "Да",
|
||||
"yourEntireScreen": "Весь экран",
|
||||
"muteEveryoneElseTitle": "Заглушить всех, за исключением {{whom}}?",
|
||||
"screenSharingAudio": "Поделиться аудио",
|
||||
"muteEveryoneSelf": "себя"
|
||||
},
|
||||
"dialOut": {
|
||||
"statusMessage": "сейчас {{status}}"
|
||||
"yourEntireScreen": "Весь экран"
|
||||
},
|
||||
"documentSharing": {
|
||||
"title": "Общий Документ"
|
||||
},
|
||||
"e2ee": {
|
||||
"labelToolTip": "Аудио и видео связь по этому вызову защищена сквозным шифрованием"
|
||||
},
|
||||
"embedMeeting": {
|
||||
"title": "Встроить эту встречу"
|
||||
},
|
||||
"feedback": {
|
||||
"average": "Средне",
|
||||
"bad": "Плохо",
|
||||
@@ -300,6 +343,9 @@
|
||||
"veryBad": "Очень плохо",
|
||||
"veryGood": "Очень хорошо"
|
||||
},
|
||||
"helpView": {
|
||||
"header": "Справка"
|
||||
},
|
||||
"incomingCall": {
|
||||
"answer": "Ответ",
|
||||
"audioCallTitle": "Входящий звонок",
|
||||
@@ -313,8 +359,8 @@
|
||||
"cancelPassword": "Отменить $t(lockRoomPassword)",
|
||||
"conferenceURL": "Ссылка:",
|
||||
"country": "Страна",
|
||||
"dialANumber": "Чтобы присоединиться к конференции, наберите один из этих номеров и введите pin-код",
|
||||
"dialInConferenceID": "PIN:",
|
||||
"dialANumber": "Чтобы присоединиться к конференции, наберите один из этих номеров и введите пин-код",
|
||||
"dialInConferenceID": "ПИН:",
|
||||
"dialInNotSupported": "К сожалению, набор номера в настоящее время не поддерживается.",
|
||||
"dialInNumber": "Номер:",
|
||||
"dialInSummaryError": "Ошибка получения информации о наборе номера. Пожалуйста, повторите попытку позже",
|
||||
@@ -326,6 +372,7 @@
|
||||
"inviteURLFirstPartGeneral": "Вас приглашают присоединиться к конференции.",
|
||||
"inviteURLFirstPartPersonal": "{{name}} приглашает Вас присоединиться к конференции. \n",
|
||||
"inviteURLSecondPart": "\nПрисоединиться к конференции:\n{{url}}\n",
|
||||
"label": "Информация о конференции",
|
||||
"liveStreamURL": "Трансляция:",
|
||||
"moreNumbers": "Больше номеров",
|
||||
"noNumbers": "Нет номеров для набора.",
|
||||
@@ -334,8 +381,13 @@
|
||||
"numbers": "Номера для набора",
|
||||
"password": "$t(lockRoomPasswordUppercase):",
|
||||
"title": "Поделиться",
|
||||
"tooltip": "Поделитесь ссылкой и номером для подключения к этой конференции",
|
||||
"label": "Информация о конференции"
|
||||
"tooltip": "Поделитесь ссылкой и номером для подключения к этой конференции"
|
||||
},
|
||||
"inlineDialogFailure": {
|
||||
"msg": "Небольшая заминка.",
|
||||
"retry": "Попробовать снова",
|
||||
"support": "Поддержка",
|
||||
"supportMsg": "Если это продолжится, свяжитесь с"
|
||||
},
|
||||
"inviteDialog": {
|
||||
"alertText": "Не удалось пригласить некоторых участников.",
|
||||
@@ -345,12 +397,6 @@
|
||||
"searchPlaceholder": "Участник или номер телефона",
|
||||
"send": "Отправить"
|
||||
},
|
||||
"inlineDialogFailure": {
|
||||
"msg": "Небольшая заминка.",
|
||||
"retry": "Попробовать снова",
|
||||
"support": "Поддержка",
|
||||
"supportMsg": "Если это продолжится, свяжитесь с"
|
||||
},
|
||||
"keyboardShortcuts": {
|
||||
"focusLocal": "Фокус на ваше видео",
|
||||
"focusRemote": "Фокус на видео другого участника",
|
||||
@@ -383,23 +429,55 @@
|
||||
"expandedPending": "Начинается прямая трансляция...",
|
||||
"failedToStart": "Ошибка трансляции видео",
|
||||
"getStreamKeyManually": "Прямые трансляций не найдены. Попробуйте получить ключ прямой трансляции от YouTube.",
|
||||
"googlePrivacyPolicy": "Политика конфиденциальности Google",
|
||||
"invalidStreamKey": "Похоже ключ прямой трансляции неверен.",
|
||||
"limitNotificationDescriptionNative": "Ваша трансляция будет ограничена {{limit}} мин. Для неограниченного просмотра попробуйте {{app}}.",
|
||||
"limitNotificationDescriptionWeb": "Из-за высокой нагрузки ваша потоковая передача будет ограничена {{limit}} мин. Для неограниченной потоковой передачи попробуйте <a href={{url}} rel='noopener noreferrer' target='_blank'> {{app}} </a>.",
|
||||
"off": "Трансляция остановлена",
|
||||
"offBy": "{{name}} остановил прямую трансляцию",
|
||||
"on": "Трансляция",
|
||||
"onBy": "{{name}} начал прямую трансляцию",
|
||||
"pending": "Начинаем трансляцию...",
|
||||
"serviceName": "Служба трансляции",
|
||||
"signedInAs": "В настоящее время вы вошли в систему как:",
|
||||
"signIn": "Войти через Google",
|
||||
"signInCTA": "Войдите или введите свой ключ трансляции YouTube.",
|
||||
"signOut": "Выход",
|
||||
"signedInAs": "В настоящее время вы вошли в систему как:",
|
||||
"start": "Начать трансляцию",
|
||||
"streamIdHelp": "Что это?",
|
||||
"unavailableTitle": "Трансляция недоступна",
|
||||
"googlePrivacyPolicy": "Политика конфиденциальности Google",
|
||||
"youtubeTerms": "Условия использования YouTube"
|
||||
},
|
||||
"lobby": {
|
||||
"disableDialogContent": "В настоящее время включен режим лобби. Эта функция гарантирует, что нежелательные участники не смогут присоединиться к вашей встрече. Вы хотите его отключить?",
|
||||
"disableDialogSubmit": "Отключить",
|
||||
"emailField": "Введите ваш адрес электронной почты",
|
||||
"enableDialogPasswordField": "Установите пароль (необязательно)",
|
||||
"enableDialogSubmit": "Включить",
|
||||
"enableDialogText": "Режим лобби позволяет защитить вашу встречу, позволяя людям входить только после официального одобрения модератором.",
|
||||
"enterPasswordButton": "Введите пароль встречи",
|
||||
"enterPasswordTitle": "Введите пароль чтобы присоединиться к встрече",
|
||||
"invalidPassword": "Неверный пароль",
|
||||
"joinRejectedMessage": "Ваш запрос на присоединение был отклонен модератором.",
|
||||
"joinTitle": "Присоединиться к встрече",
|
||||
"joinWithPasswordMessage": "Пытаюсь присоединиться с паролем, подождите...",
|
||||
"joiningMessage": "Вы присоединитесь к встрече, как только кто-то примет ваш запрос",
|
||||
"joiningTitle": "Просьба присоединиться к встрече...",
|
||||
"joiningWithPasswordTitle": "Присоединение с паролем...",
|
||||
"knockButton": "Попросить присоединиться",
|
||||
"knockTitle": "Кто-то хочет присоединиться к встрече",
|
||||
"knockingParticipantList": "Список ожидающих участников",
|
||||
"nameField": "Введите ваше имя",
|
||||
"notificationLobbyAccessDenied": "{{originParticipantName}} запретил присоединиться {{targetParticipantName}}",
|
||||
"notificationLobbyAccessGranted": "{{originParticipantName}}разрешил присоединиться {{targetParticipantName}} ",
|
||||
"notificationLobbyDisabled": "Лобби отключено пользователем {{originParticipantName}}",
|
||||
"notificationLobbyEnabled": "Лобби включено пользователем {{originParticipantName}}",
|
||||
"notificationTitle": "Лобби",
|
||||
"passwordField": "Введите пароль встречи",
|
||||
"passwordJoinButton": "Присоединиться",
|
||||
"reject": "Отказать",
|
||||
"toggleLabel": "Включить лобби"
|
||||
},
|
||||
"localRecording": {
|
||||
"clientState": {
|
||||
"off": "Отключен",
|
||||
@@ -431,8 +509,15 @@
|
||||
},
|
||||
"lockRoomPassword": "пароль",
|
||||
"lockRoomPasswordUppercase": "Пароль",
|
||||
"lonelyMeetingExperience": {
|
||||
"button": "Пригласить",
|
||||
"getHelp": "Получить помощь",
|
||||
"title": "Защищенная, полнофункциональная и совершенно бесплатная система видеоконференций",
|
||||
"youAreAlone": "Вы один в видеоконференции"
|
||||
},
|
||||
"me": "я",
|
||||
"notify": {
|
||||
"OldElectronAPPTitle": "Уязвимость в системе безопасности!",
|
||||
"connectedOneMember": "{{name}} присоединился к конференции",
|
||||
"connectedThreePlusMembers": "{{name}} и {{count}} других пользователей присоединились к конференции",
|
||||
"connectedTwoMembers": "{{first}} и {{second}} присоединились к конференции",
|
||||
@@ -447,25 +532,64 @@
|
||||
"me": "Я",
|
||||
"moderator": "Получены права модератора!",
|
||||
"muted": "Вы начали разговор без звука.",
|
||||
"mutedTitle": "Вы без звука!",
|
||||
"mutedRemotelyTitle": "{{participantDisplayName}} отключил Вам микрофон!",
|
||||
"mutedRemotelyDescription": "Вы всегда можете включить микрофон, когда будете готовы говорить. Отключите его, когда закончите, чтобы не транслировать шумы в конференцию.",
|
||||
"mutedRemotelyTitle": "{{participantDisplayName}} отключил Вам микрофон!",
|
||||
"mutedTitle": "Вы без звука!",
|
||||
"newDeviceAction": "Использовать",
|
||||
"newDeviceAudioTitle": "Обнаружено новое аудиоустройство",
|
||||
"newDeviceCameraTitle": "Обнаружена новая камера",
|
||||
"oldElectronClientDescription1": "Похоже, вы используете старую версию клиента Jitsi Meet, которая имеет известные уязвимости в системе безопасности. Убедитесь, что вы обновили до нашей ",
|
||||
"oldElectronClientDescription2": "последней версии",
|
||||
"oldElectronClientDescription3": " сейчас!",
|
||||
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) удален другим участником.",
|
||||
"passwordSetRemotely": "Другой участник установил $t(lockRoomPasswordUppercase)",
|
||||
"raisedHand": "{{name}} хотел бы выступить.",
|
||||
"somebody": "Кто-то",
|
||||
"startSilentTitle": "У вас отсутствует звук!",
|
||||
"startSilentDescription": "Перезайдите в конференцию, чтобы включить звук",
|
||||
"startSilentTitle": "У вас отсутствует звук!",
|
||||
"suboptimalBrowserWarning": "К сожалению, ваш браузер не полностью поддерживает данную систему вэбконференций. Мы работаем над проблемой, однако, пока рекомендуем вам воспользоваться <a href='{{recommendedBrowserPageLink}}' target='_blank'> следующими браузерами</a>.",
|
||||
"suboptimalExperienceTitle": "Предупреждение браузера",
|
||||
"unmute": "Включить микрофон",
|
||||
"newDeviceCameraTitle": "Обнаружена новая камера",
|
||||
"newDeviceAudioTitle": "Обнаружено новое аудиоустройство",
|
||||
"newDeviceAction": "Использовать"
|
||||
"unmute": "Включить микрофон"
|
||||
},
|
||||
"passwordSetRemotely": "установлен другим участником",
|
||||
"passwordDigitsOnly": "До {{number}} цифр",
|
||||
"passwordSetRemotely": "установлен другим участником",
|
||||
"poweredby": "работает на",
|
||||
"prejoin": {
|
||||
"audioAndVideoError": "Ошибка звука и видео:",
|
||||
"audioOnlyError": "Ошибка звука:",
|
||||
"audioTrackError": "Не удалось создать аудио дорожку.",
|
||||
"callMe": "Позвоните мне",
|
||||
"callMeAtNumber": "Позвоните мне по этому номеру:",
|
||||
"calling": "Вызываем",
|
||||
"configuringDevices": "Настраиваются устройства...",
|
||||
"connectedWithAudioQ": "Вы подключили звук?",
|
||||
"copyAndShare": "Скопировать и поделиться ссылкой на встречу",
|
||||
"dialInMeeting": "Дозвониться до встречи",
|
||||
"dialInPin": "Дозвониться до встречи и ввести ПИН код:",
|
||||
"dialing": "Дозвон",
|
||||
"doNotShow": "Не показывать снова",
|
||||
"errorDialOut": "Не удалось дозвониться",
|
||||
"errorDialOutDisconnected": "Не удалось дозвониться. Отключено",
|
||||
"errorDialOutFailed": "Не удалось дозвониться. Сбой вызова",
|
||||
"errorDialOutStatus": "Ошибка получения статуса вызова",
|
||||
"errorStatusCode": "Ошибка вызова, код статуса: {{status}}",
|
||||
"errorValidation": "Проверка номера не удалась",
|
||||
"iWantToDialIn": "Я хочу дозвониться",
|
||||
"initiated": "Вызов инициирован",
|
||||
"joinAudioByPhone": "Подключиться с телефонной связью",
|
||||
"joinMeeting": "Присоединиться ко встрече",
|
||||
"joinWithoutAudio": "Присоединиться без звука",
|
||||
"linkCopied": "Ссылка скопирована в буфер обмена",
|
||||
"lookGood": "Кажется ваш микрофон работает правильно",
|
||||
"or": "или",
|
||||
"premeeting": "Перед подключением",
|
||||
"screenSharingError": "Ошибка показа экрана:",
|
||||
"showScreen": "Включить экран перед подключением",
|
||||
"startWithPhone": "Начать с телефонной связью",
|
||||
"videoOnlyError": "Ошибка видео:",
|
||||
"videoTrackError": "Не удалось создать видео дорожку.",
|
||||
"viewAllNumbers": "посмотреть всех участников"
|
||||
},
|
||||
"presenceStatus": {
|
||||
"busy": "Занят",
|
||||
"calling": "Вызываю...",
|
||||
@@ -499,14 +623,16 @@
|
||||
"expandedPending": "Начинаем запись конференции...",
|
||||
"failedToStart": "Ошибка начала записи",
|
||||
"fileSharingdescription": "Поделиться записью с участниками конференции",
|
||||
"live": "Прямая трансляция",
|
||||
"limitNotificationDescriptionNative": "Из-за высокой нагрузки ваша запись будет ограничена {{limit}} мин. Для неограниченного количества записей попробуйте <3> {{app}} </3>.",
|
||||
"limitNotificationDescriptionWeb": "Из-за высокой нагрузки ваша запись будет ограничена {{limit}} мин. Для неограниченного количества записей попробуйте <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"live": "В ЭФИРЕ",
|
||||
"loggedIn": "Вошел как {{userName}}",
|
||||
"off": "Запись остановлена",
|
||||
"offBy": "{{name}} остановил запись",
|
||||
"on": "Запись",
|
||||
"onBy": "{{name}} включил запись",
|
||||
"pending": "Подготовка записи конференции. . .",
|
||||
"rec": "Идет запись",
|
||||
"rec": "ИДЕТ ЗАПИСЬ",
|
||||
"serviceDescription": "Ваша запись будет сохранена соответствующей службой",
|
||||
"serviceName": "Служба записи",
|
||||
"signIn": "Вход",
|
||||
@@ -517,6 +643,12 @@
|
||||
"sectionList": {
|
||||
"pullToRefresh": "Потяните для обновления"
|
||||
},
|
||||
"security": {
|
||||
"about": "Вы можете добавить к собранию $t(lockRoomPassword). Участникам необходимо будет предоставить $t(lockRoomPassword), прежде чем им будет разрешено присоединиться к собранию.",
|
||||
"aboutReadOnly": "Участники-модераторы могут добавить к собранию $t(lockRoomPassword). Участникам необходимо будет предоставить $t(lockRoomPassword), прежде чем им будет разрешено присоединиться к собранию.",
|
||||
"insecureRoomNameWarning": "Имя комнаты небезопасно. Нежелательные участники могут присоединиться к вашей конференции. Подумайте о том, чтобы защитить вашу встречу используя настройки безопасности.",
|
||||
"securityOptions": "Настройки безопасности"
|
||||
},
|
||||
"settings": {
|
||||
"calendar": {
|
||||
"about": "Интеграция с календарем {{appName}} используется для безопасного доступа к вашему календарю и синхронизации запланированных мероприятий.",
|
||||
@@ -529,6 +661,7 @@
|
||||
"followMe": "Все следуют за мной",
|
||||
"language": "Язык",
|
||||
"loggedIn": "Вошел как {{name}}",
|
||||
"microphones": "Микрофоны",
|
||||
"moderator": "Модератор",
|
||||
"more": "Больше опций",
|
||||
"name": "Имя",
|
||||
@@ -536,11 +669,10 @@
|
||||
"selectAudioOutput": "Звуковой выход",
|
||||
"selectCamera": "Камера",
|
||||
"selectMic": "Микрофон",
|
||||
"speakers": "Динамики",
|
||||
"startAudioMuted": "Все начинают с выключенным звуком",
|
||||
"startVideoMuted": "Все начинают в скрытом режиме",
|
||||
"title": "Настройки",
|
||||
"speakers": "Динамики",
|
||||
"microphones": "Микрофоны"
|
||||
"title": "Настройки"
|
||||
},
|
||||
"settingsView": {
|
||||
"advanced": "Дополнительные",
|
||||
@@ -550,6 +682,8 @@
|
||||
"buildInfoSection": "Информация о сборке",
|
||||
"conferenceSection": "Номера для набора",
|
||||
"disableCallIntegration": "Отключить встроенную интеграцию вызовов",
|
||||
"disableCrashReporting": "Отключить отправку отчетов о сбоях",
|
||||
"disableCrashReportingWarning": "Вы действительно хотите отключить отчеты о сбоях? Настройка будет применена после перезапуска приложения.",
|
||||
"disableP2P": "Отключить режим Peer-To-Peer",
|
||||
"displayName": "Отображаемое имя",
|
||||
"email": "Email",
|
||||
@@ -565,7 +699,7 @@
|
||||
"dialInfoText": "\n\n=====\n\nПросто хотите набрать номер на Вашем телефоне?\n\n{{defaultDialInNumber}}Щелкните на эту ссылку, чтобы просмотреть телефонные номера для этой конференции\n{{dialInfoPageUrl}}",
|
||||
"mainText": "Нажмите на ссылку чтобы присоединиться к конференции:\n{{roomUrl}}"
|
||||
},
|
||||
"speaker": "Колонка",
|
||||
"speaker": "Спикер",
|
||||
"speakerStats": {
|
||||
"hours": "{{count}}ч",
|
||||
"minutes": "{{count}}м",
|
||||
@@ -584,7 +718,9 @@
|
||||
"title": "Видеосвязь прервана. Причина: этот компьютер перешел в режим сна."
|
||||
},
|
||||
"toolbar": {
|
||||
"Settings": "Настройки",
|
||||
"accessibilityLabel": {
|
||||
"Settings": "Вкл/Выкл меню настроек",
|
||||
"audioOnly": "Вкл/Выкл только звук",
|
||||
"audioRoute": "Выбрать аудиоустройство",
|
||||
"callQuality": "Качество связи",
|
||||
@@ -592,36 +728,41 @@
|
||||
"chat": "Показать/скрыть окно чата",
|
||||
"document": "Закрыть общий документ",
|
||||
"download": "Скачать приложение",
|
||||
"e2ee": "Сквозное шифрование",
|
||||
"embedMeeting": "Встроить встречу",
|
||||
"feedback": "Оставить отзыв",
|
||||
"fullScreen": "Полноэкранный/оконный режим",
|
||||
"grantModerator": "Сделать модератором",
|
||||
"hangup": "Завершить звонок",
|
||||
"help": "Справка",
|
||||
"invite": "Пригласить",
|
||||
"kick": "Выкинуть участника",
|
||||
"lobbyButton": "Вкл/Выкл режим лобби",
|
||||
"localRecording": "Вкл/Выкл кнопки записи",
|
||||
"lockRoom": "Установить пароль",
|
||||
"moreActions": "Показать/скрыть меню доп. настроек",
|
||||
"moreOptions": "Меню доп. настроек",
|
||||
"moreActionsMenu": "Меню доп. настроек",
|
||||
"moreOptions": "Меню доп. настроек",
|
||||
"mute": "Вкл/Выкл звук",
|
||||
"muteEveryone": "Выкл. микрофон у всех",
|
||||
"pip": "Вкл/Выкл режим Картинка-в-картинке",
|
||||
"privateMessage": "Отправить личное сообщение",
|
||||
"profile": "Редактировать профиль",
|
||||
"raiseHand": "Поднять руку",
|
||||
"recording": "Вкл/Выкл запись",
|
||||
"remoteMute": "Отключить участнику микрофон",
|
||||
"Settings": "Вкл/Выкл меню настроек",
|
||||
"sharedvideo": "Вкл/Выкл Youtube - трансляцию",
|
||||
"security": "Настройки безопасности",
|
||||
"shareRoom": "Отправить приглашение",
|
||||
"shareYourScreen": "Вкл/Выкл демонстрацию экрана",
|
||||
"sharedvideo": "Вкл/Выкл Youtube - трансляцию",
|
||||
"shortcuts": "Вкл/Выкл значки",
|
||||
"show": "Показать крупным планом",
|
||||
"speakerStats": "Вкл/Выкл статистику",
|
||||
"tileView": "Вкл/Выкл плитку",
|
||||
"toggleCamera": "Переключить камеру",
|
||||
"videomute": "Вкл/Выкл видео",
|
||||
"muteEveryone": "Выкл. микрофон у всех",
|
||||
"videoblur": "Вкл/Выкл размытие фона"
|
||||
"toggleFilmstrip": "Включить диафильм",
|
||||
"videoblur": "Вкл/Выкл размытие фона",
|
||||
"videomute": "Вкл/Выкл видео"
|
||||
},
|
||||
"addPeople": "Добавить людей к вашему сеансу связи",
|
||||
"audioOnlyOff": "Отключить режим экономии пропуской способности",
|
||||
@@ -634,6 +775,8 @@
|
||||
"documentClose": "Закрыть общий документ",
|
||||
"documentOpen": "Открыть общий документ",
|
||||
"download": "Скачать приложение",
|
||||
"e2ee": "Сквозное шифрование",
|
||||
"embedMeeting": "Встроить встречу",
|
||||
"enterFullScreen": "Полный экран",
|
||||
"enterTileView": "Общий план",
|
||||
"exitFullScreen": "Полный экран",
|
||||
@@ -642,39 +785,44 @@
|
||||
"hangup": "Выход",
|
||||
"help": "Справка",
|
||||
"invite": "Пригласить",
|
||||
"lobbyButtonDisable": "Отключить режим лобби",
|
||||
"lobbyButtonEnable": "Включить режим лобби",
|
||||
"login": "Войти",
|
||||
"logout": "Завершить сеанс",
|
||||
"lowerYourHand": "Опустить руку",
|
||||
"moreActions": "Больше",
|
||||
"moreActions": "Больше действий",
|
||||
"moreOptions": "Больше настроек",
|
||||
"mute": "Микрофон (вкл./выкл.)",
|
||||
"muteEveryone": "Выкл. микрофон у всех",
|
||||
"noAudioSignalTitle": "От вашего микрофона не идет звуковой сигнал!",
|
||||
"noAudioSignalDesc": "Если вы специально не отключали микрофон в системных настройках, подумайте о том, чтобы поменять его.",
|
||||
"noAudioSignalDescSuggestion": "Если вы специально не отключали микрофон в системных настройках, вы можете попробовать использовать следующее устройство:",
|
||||
"noisyAudioInputTitle": "Похоже, ваш микрофон создает шум!",
|
||||
"noAudioSignalDialInDesc": "Вы можете также дозвониться используя:",
|
||||
"noAudioSignalDialInLinkDesc": "Номера для дозвона",
|
||||
"noAudioSignalTitle": "От вашего микрофона не идет звуковой сигнал!",
|
||||
"noisyAudioInputDesc": "Возможно, ваш микрофон создает шум. Вы можете выключить его или смените устройство.",
|
||||
"noisyAudioInputTitle": "Похоже, ваш микрофон создает шум!",
|
||||
"openChat": "Открыть чат",
|
||||
"pip": "Вкл режим Картинка-в-картинке",
|
||||
"privateMessage": "Отправить личное сообщение",
|
||||
"profile": "Редактировать профиль",
|
||||
"raiseHand": "Хочу говорить",
|
||||
"raiseYourHand": "Поднять руку",
|
||||
"Settings": "Настройки",
|
||||
"sharedvideo": "Видео YouTube",
|
||||
"security": "Настройки безопасности",
|
||||
"shareRoom": "Отправить приглашение",
|
||||
"sharedvideo": "Видео YouTube",
|
||||
"shortcuts": "Комбинации клавиш",
|
||||
"speakerStats": "Статистика",
|
||||
"startScreenSharing": "Начать трансляцию с экрана",
|
||||
"startSubtitles": "Включить субтитры",
|
||||
"startvideoblur": "Размыть фон на видео",
|
||||
"stopScreenSharing": "Остановить трансляцию с экрана",
|
||||
"stopSubtitles": "Отключить субтитры",
|
||||
"stopSharedVideo": "Остановить видео на YouTube",
|
||||
"stopSubtitles": "Отключить субтитры",
|
||||
"stopvideoblur": "Отключить размытие фона",
|
||||
"talkWhileMutedPopup": "Пытаетесь говорить? У вас отключен звук.",
|
||||
"tileViewToggle": "Вкл/выкл плитку",
|
||||
"toggleCamera": "Вкл/выкл камеру",
|
||||
"videomute": "Камера",
|
||||
"startvideoblur": "Размыть фон на видео",
|
||||
"stopvideoblur": "Отключить размытие фона"
|
||||
"videomute": "Камера"
|
||||
},
|
||||
"transcribing": {
|
||||
"ccButtonTooltip": "Вкл. / Выкл. субтитры",
|
||||
@@ -685,8 +833,7 @@
|
||||
"off": "Расшифровка остановлена",
|
||||
"pending": "Подготовка расшифровки конференции...",
|
||||
"start": "Вкл/Выкл показ субтитров",
|
||||
"stop": "Вкл/Выкл показ субтитров",
|
||||
"tr": ""
|
||||
"stop": "Вкл/Выкл показ субтитров"
|
||||
},
|
||||
"userMedia": {
|
||||
"androidGrantPermissions": "Выберите <b><i>Разрешить</i></b>, когда браузер спросит о разрешениях.",
|
||||
@@ -732,6 +879,7 @@
|
||||
"domute": "Выключить звук",
|
||||
"domuteOthers": "Выключить остальных",
|
||||
"flip": "Отразить",
|
||||
"grantModerator": "Сделать модератором",
|
||||
"kick": "Выкинуть",
|
||||
"moderator": "Модератор",
|
||||
"mute": "Без звука",
|
||||
@@ -754,26 +902,22 @@
|
||||
"connectCalendarButton": "Привязать календарь",
|
||||
"connectCalendarText": "Подключите календарь, чтобы увидеть все ваши конференции в {{app}}. Кроме того, добавив {{provider}} конференций в календарь, вы сможете запускать их одним щелчком мышки.",
|
||||
"enterRoomTitle": "Начать новую видеоконференцию",
|
||||
"roomNameAllowedChars": "Название конференции не должно содержать следующие символы: ?, &, :, ', \", %, #.",
|
||||
"getHelp": "Справка",
|
||||
"go": "ОК",
|
||||
"goSmall": "ОК",
|
||||
"join": "СОЗДАТЬ / ПРИСОЕДИНИТЬСЯ",
|
||||
"info": "Инфо",
|
||||
"join": "СОЗДАТЬ / ПРИСОЕДИНИТЬСЯ",
|
||||
"moderatedMessage": "Или заранее <a href=\"{{url}}\" rel=\"noopener noreferrer\" target=\"_blank\">зарезервируйте URL-адрес встречи</a>, где вы будете единственным модератором.",
|
||||
"privacy": "Приватность",
|
||||
"recentList": "Недавние",
|
||||
"recentListDelete": "Удалить",
|
||||
"recentListEmpty": "Сейчас ваш список недавно проведенных конференций пуст. По мере вашего пользования сервисом он будет пополняться.",
|
||||
"reducedUIText": "Добро пожаловать в {{app}}!",
|
||||
"roomNameAllowedChars": "Название конференции не должно содержать следующие символы: ?, &, :, ', \", %, #.",
|
||||
"roomname": "Укажите название комнаты",
|
||||
"roomnameHint": "Укажите название комнаты или ее адрес. Можете сами создать название и передать его будущим участникам встречи, чтобы они использовали именно его.",
|
||||
"sendFeedback": "Обратная связь",
|
||||
"terms": "Условия",
|
||||
"title": "Защищенная, полнофункциональная и совершенно бесплатная система видеоконференций"
|
||||
},
|
||||
"lonelyMeetingExperience": {
|
||||
"button": "Пригласить",
|
||||
"youAreAlone": "Вы один в видеоконференции",
|
||||
"title": "Защищенная, полнофункциональная и совершенно бесплатная система видеоконференций",
|
||||
"getHelp": "Получить помощь"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +216,9 @@
|
||||
"kickParticipantDialog": "Are you sure you want to kick this participant?",
|
||||
"kickParticipantTitle": "Kick this participant?",
|
||||
"kickTitle": "Ouch! {{participantDisplayName}} kicked you out of the meeting",
|
||||
"leaveJibriQueue": "Exit queue",
|
||||
"liveStreaming": "Live Streaming",
|
||||
"leaveJibriQueueWarning": "Are you sure you would like to exit the queue?",
|
||||
"liveStreamingDisabledBecauseOfActiveRecordingTooltip": "Not possible while recording is active",
|
||||
"liveStreamingDisabledForGuestTooltip": "Guests can't start live streaming.",
|
||||
"liveStreamingDisabledTooltip": "Start live stream disabled.",
|
||||
@@ -908,5 +910,22 @@
|
||||
"passwordJoinButton": "Join",
|
||||
"reject": "Reject",
|
||||
"toggleLabel": "Enable lobby"
|
||||
},
|
||||
"jibriQueue": {
|
||||
"recording": {
|
||||
"title": "You have joined a recording queue!",
|
||||
"time": "Estimated time for starting the recording: {{time}}",
|
||||
"footer": "For unlimited recordings you should subscribe to 8x8 Meetings",
|
||||
"left": "You have left the recording queue!"
|
||||
},
|
||||
"livestreaming": {
|
||||
"title": "You have joined a live streaming queue!",
|
||||
"time": "Estimated time for starting the live streaming: {{time}}",
|
||||
"footer": "For unlimited live streaming you should subscribe to 8x8 Meetings",
|
||||
"left": "You have left the live streaming queue!"
|
||||
},
|
||||
"position": "{{count}} more person is waiting in front of you.",
|
||||
"position_plural": "{{count}} more people are waiting in front of you.",
|
||||
"exit": "Exit queue"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
import { isEnabled as isDropboxEnabled } from '../../react/features/dropbox';
|
||||
import { setE2EEKey } from '../../react/features/e2ee';
|
||||
import { invite } from '../../react/features/invite';
|
||||
import { toggleLobbyMode } from '../../react/features/lobby/actions.web';
|
||||
import { RECORDING_TYPES } from '../../react/features/recording/constants';
|
||||
import { getActiveSession } from '../../react/features/recording/functions';
|
||||
import { muteAllParticipants } from '../../react/features/remote-video-menu/actions';
|
||||
@@ -89,6 +90,9 @@ function initCommands() {
|
||||
|
||||
APP.store.dispatch(muteAllParticipants(localIds));
|
||||
},
|
||||
'toggle-lobby': isLobbyEnabled => {
|
||||
APP.store.dispatch(toggleLobbyMode(isLobbyEnabled));
|
||||
},
|
||||
'password': password => {
|
||||
const { conference, passwordRequired }
|
||||
= APP.store.getState()['features/base/conference'];
|
||||
@@ -234,6 +238,7 @@ function initCommands() {
|
||||
return;
|
||||
}
|
||||
|
||||
const jibriQueueJID = state['features/base/config'].jibriQueueJID;
|
||||
let recordingConfig;
|
||||
|
||||
if (mode === JitsiRecordingConstants.mode.FILE) {
|
||||
@@ -247,7 +252,8 @@ function initCommands() {
|
||||
'token': dropboxToken
|
||||
}
|
||||
}
|
||||
})
|
||||
}),
|
||||
jibriQueueJID
|
||||
};
|
||||
} else {
|
||||
recordingConfig = {
|
||||
@@ -256,12 +262,14 @@ function initCommands() {
|
||||
'file_recording_metadata': {
|
||||
'share': shouldShare
|
||||
}
|
||||
})
|
||||
}),
|
||||
jibriQueueJID
|
||||
};
|
||||
}
|
||||
} else if (mode === JitsiRecordingConstants.mode.STREAM) {
|
||||
recordingConfig = {
|
||||
broadcastId: youtubeBroadcastID,
|
||||
jibriQueueJID,
|
||||
mode: JitsiRecordingConstants.mode.STREAM,
|
||||
streamId: youtubeStreamKey
|
||||
};
|
||||
@@ -271,7 +279,9 @@ function initCommands() {
|
||||
return;
|
||||
}
|
||||
|
||||
conference.startRecording(recordingConfig);
|
||||
conference.startRecording(recordingConfig).catch(() => {
|
||||
// prevent unhandled promise rejection.
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -298,8 +308,10 @@ function initCommands() {
|
||||
|
||||
const activeSession = getActiveSession(state, mode);
|
||||
|
||||
if (activeSession && activeSession.id) {
|
||||
conference.stopRecording(activeSession.id);
|
||||
if (activeSession && (activeSession.id || activeSession.queueID)) {
|
||||
conference.stopRecording(activeSession.id, activeSession.queueID).catch(() => {
|
||||
// prevent unhandled promise rejection.
|
||||
});
|
||||
} else {
|
||||
logger.error('No recording or streaming session found');
|
||||
}
|
||||
|
||||
2
modules/API/external/external_api.js
vendored
2
modules/API/external/external_api.js
vendored
@@ -31,6 +31,7 @@ const commands = {
|
||||
displayName: 'display-name',
|
||||
e2eeKey: 'e2ee-key',
|
||||
email: 'email',
|
||||
toggleLobby: 'toggle-lobby',
|
||||
hangup: 'video-hangup',
|
||||
muteEveryone: 'mute-everyone',
|
||||
password: 'password',
|
||||
@@ -277,6 +278,7 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
this._transport = new Transport({
|
||||
backend: new PostMessageTransportBackend({
|
||||
postisOptions: {
|
||||
allowedOrigin: new URL(this._url).origin,
|
||||
scope: `jitsi_meet_external_api_${id}`,
|
||||
window: this._frame.contentWindow
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ const UI = {};
|
||||
import EventEmitter from 'events';
|
||||
import Logger from 'jitsi-meet-logger';
|
||||
|
||||
import { isMobileBrowser } from '../../react/features/base/environment/utils';
|
||||
import { getLocalParticipant } from '../../react/features/base/participants';
|
||||
import { toggleChat } from '../../react/features/chat';
|
||||
import { setDocumentUrl } from '../../react/features/etherpad';
|
||||
@@ -15,7 +16,7 @@ import {
|
||||
dockToolbox,
|
||||
setToolboxEnabled,
|
||||
showToolbox
|
||||
} from '../../react/features/toolbox';
|
||||
} from '../../react/features/toolbox/actions.web';
|
||||
import UIEvents from '../../service/UI/UIEvents';
|
||||
|
||||
import EtherpadManager from './etherpad/Etherpad';
|
||||
@@ -154,6 +155,12 @@ UI.start = function() {
|
||||
|
||||
sharedVideoManager = new SharedVideoManager(eventEmitter);
|
||||
|
||||
if (isMobileBrowser()) {
|
||||
$('body').addClass('mobile-browser');
|
||||
} else {
|
||||
$('body').addClass('desktop-browser');
|
||||
}
|
||||
|
||||
if (interfaceConfig.filmStripOnly) {
|
||||
$('body').addClass('filmstrip-only');
|
||||
APP.store.dispatch(setNotificationsEnabled(false));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* global $, APP, interfaceConfig */
|
||||
|
||||
import { getSharedDocumentUrl, setDocumentEditingState } from '../../../react/features/etherpad';
|
||||
import { getToolboxHeight } from '../../../react/features/toolbox';
|
||||
import { getToolboxHeight } from '../../../react/features/toolbox/functions.web';
|
||||
import Filmstrip from '../videolayout/Filmstrip';
|
||||
import LargeContainer from '../videolayout/LargeContainer';
|
||||
import VideoLayout from '../videolayout/VideoLayout';
|
||||
|
||||
@@ -12,11 +12,9 @@ import {
|
||||
participantLeft,
|
||||
pinParticipant
|
||||
} from '../../../react/features/base/participants';
|
||||
import {
|
||||
dockToolbox,
|
||||
getToolboxHeight,
|
||||
showToolbox
|
||||
} from '../../../react/features/toolbox';
|
||||
import { dockToolbox, showToolbox } from '../../../react/features/toolbox/actions.web';
|
||||
import { getToolboxHeight } from '../../../react/features/toolbox/functions.web';
|
||||
import { YOUTUBE_PARTICIPANT_NAME } from '../../../react/features/youtube-player/constants';
|
||||
import UIEvents from '../../../service/UI/UIEvents';
|
||||
import UIUtil from '../util/UIUtil';
|
||||
import Filmstrip from '../videolayout/Filmstrip';
|
||||
@@ -305,7 +303,7 @@ export default class SharedVideoManager {
|
||||
conference: APP.conference._room,
|
||||
id: self.url,
|
||||
isFakeParticipant: true,
|
||||
name: 'YouTube'
|
||||
name: YOUTUBE_PARTICIPANT_NAME
|
||||
}));
|
||||
|
||||
APP.store.dispatch(pinParticipant(self.url));
|
||||
|
||||
@@ -451,7 +451,7 @@ export default class SmallVideo {
|
||||
*/
|
||||
selectDisplayMode(input) {
|
||||
// Display name is always and only displayed when user is on the stage
|
||||
if (input.isCurrentlyOnLargeVideo && !input.tileViewEnabled) {
|
||||
if (input.isCurrentlyOnLargeVideo && !input.tileViewActive) {
|
||||
return input.isVideoPlayable && !input.isAudioOnly ? DISPLAY_BLACKNESS_WITH_NAME : DISPLAY_AVATAR_WITH_NAME;
|
||||
} else if (input.isVideoPlayable && input.hasVideo && !input.isAudioOnly) {
|
||||
// check hovering and change state to video with name
|
||||
@@ -472,7 +472,7 @@ export default class SmallVideo {
|
||||
isCurrentlyOnLargeVideo: this.isCurrentlyOnLargeVideo(),
|
||||
isHovered: this._isHovered(),
|
||||
isAudioOnly: APP.conference.isAudioOnly(),
|
||||
tileViewEnabled: shouldDisplayTileView(APP.store.getState()),
|
||||
tileViewActive: shouldDisplayTileView(APP.store.getState()),
|
||||
isVideoPlayable: this.isVideoPlayable(),
|
||||
hasVideo: Boolean(this.selectVideoElement().length),
|
||||
connectionStatus: APP.conference.getParticipantConnectionStatus(this.id),
|
||||
|
||||
7659
package-lock.json
generated
7659
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,7 @@
|
||||
"@atlaskit/dropdown-menu": "6.1.25",
|
||||
"@atlaskit/field-text": "7.0.19",
|
||||
"@atlaskit/field-text-area": "4.0.15",
|
||||
"@atlaskit/flag": "9.1.8",
|
||||
"@atlaskit/flag": "13.0.0",
|
||||
"@atlaskit/icon": "15.0.3",
|
||||
"@atlaskit/inline-dialog": "5.3.0",
|
||||
"@atlaskit/inline-message": "7.0.10",
|
||||
@@ -31,8 +31,9 @@
|
||||
"@atlaskit/tabs": "8.0.11",
|
||||
"@atlaskit/theme": "7.0.2",
|
||||
"@atlaskit/toggle": "5.0.14",
|
||||
"@atlaskit/portal": "4.0.0",
|
||||
"@atlaskit/tooltip": "12.1.13",
|
||||
"@jitsi/js-utils": "1.0.0",
|
||||
"@jitsi/js-utils": "1.0.1",
|
||||
"@microsoft/microsoft-graph-client": "1.1.0",
|
||||
"@react-native-community/async-storage": "1.3.4",
|
||||
"@react-native-community/google-signin": "3.0.1",
|
||||
@@ -56,7 +57,7 @@
|
||||
"jquery-i18next": "1.2.1",
|
||||
"js-md5": "0.6.1",
|
||||
"jwt-decode": "2.2.0",
|
||||
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#2c4e3816e97d174b0a9e82ce1ace5a77eda9a891",
|
||||
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#f74cd0abe9c696a9c3ca7dbb9ca170e6e84d6756",
|
||||
"libflacjs": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d",
|
||||
"lodash": "4.17.19",
|
||||
"moment": "2.19.4",
|
||||
@@ -125,6 +126,7 @@
|
||||
"expose-loader": "0.7.5",
|
||||
"flow-bin": "0.104.0",
|
||||
"imports-loader": "0.7.1",
|
||||
"jest": "26.1.0",
|
||||
"jetifier": "1.6.4",
|
||||
"metro-react-native-babel-preset": "0.56.0",
|
||||
"node-sass": "4.14.1",
|
||||
@@ -144,6 +146,7 @@
|
||||
"scripts": {
|
||||
"lint": "eslint . && flow",
|
||||
"postinstall": "jetify",
|
||||
"test": "jest",
|
||||
"validate": "npm ls"
|
||||
},
|
||||
"browser": {
|
||||
|
||||
@@ -284,11 +284,12 @@ export function maybeRedirectToWelcomePage(options: Object = {}) {
|
||||
|
||||
// if close page is enabled redirect to it, without further action
|
||||
if (enableClosePage) {
|
||||
const { isGuest } = getState()['features/base/jwt'];
|
||||
const { isGuest, jwt } = getState()['features/base/jwt'];
|
||||
|
||||
// save whether current user is guest or not, before navigating
|
||||
// to close page
|
||||
// save whether current user is guest or not, and pass auth token,
|
||||
// before navigating to close page
|
||||
window.sessionStorage.setItem('guest', isGuest);
|
||||
window.sessionStorage.setItem('jwt', jwt);
|
||||
|
||||
let path = 'close.html';
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import '../base/dialog/reducer';
|
||||
import '../base/flags/reducer';
|
||||
import '../base/jwt/reducer';
|
||||
import '../base/known-domains/reducer';
|
||||
import '../base/lastn/reducer';
|
||||
import '../base/lib-jitsi-meet/reducer';
|
||||
import '../base/logging/reducer';
|
||||
import '../base/media/reducer';
|
||||
|
||||
@@ -58,6 +58,11 @@ export type Props = {
|
||||
*/
|
||||
status?: ?string,
|
||||
|
||||
/**
|
||||
* TestId of the element, if any.
|
||||
*/
|
||||
testId?: string,
|
||||
|
||||
/**
|
||||
* URL of the avatar, if any.
|
||||
*/
|
||||
@@ -122,6 +127,7 @@ class Avatar<P: Props> extends PureComponent<P, State> {
|
||||
id,
|
||||
size,
|
||||
status,
|
||||
testId,
|
||||
url
|
||||
} = this.props;
|
||||
const { avatarFailed } = this.state;
|
||||
@@ -134,6 +140,7 @@ class Avatar<P: Props> extends PureComponent<P, State> {
|
||||
onAvatarLoadError: undefined,
|
||||
size,
|
||||
status,
|
||||
testId,
|
||||
url: undefined
|
||||
};
|
||||
|
||||
|
||||
@@ -25,7 +25,12 @@ type Props = AbstractProps & {
|
||||
/**
|
||||
* One of the expected status strings (e.g. 'available') to render a badge on the avatar, if necessary.
|
||||
*/
|
||||
status?: ?string
|
||||
status?: ?string,
|
||||
|
||||
/**
|
||||
* TestId of the element, if any.
|
||||
*/
|
||||
testId?: string
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -45,6 +50,7 @@ export default class StatelessAvatar extends AbstractStatelessAvatar<Props> {
|
||||
return (
|
||||
<div
|
||||
className = { `${this._getAvatarClassName()} ${this._getBadgeClassName()}` }
|
||||
data-testid = { this.props.testId }
|
||||
id = { this.props.id }
|
||||
style = { this._getAvatarStyle(this.props.color) }>
|
||||
<Icon
|
||||
@@ -59,6 +65,7 @@ export default class StatelessAvatar extends AbstractStatelessAvatar<Props> {
|
||||
<div className = { this._getBadgeClassName() }>
|
||||
<img
|
||||
className = { this._getAvatarClassName() }
|
||||
data-testid = { this.props.testId }
|
||||
id = { this.props.id }
|
||||
onError = { this.props.onAvatarLoadError }
|
||||
src = { url }
|
||||
@@ -71,6 +78,7 @@ export default class StatelessAvatar extends AbstractStatelessAvatar<Props> {
|
||||
return (
|
||||
<div
|
||||
className = { `${this._getAvatarClassName()} ${this._getBadgeClassName()}` }
|
||||
data-testid = { this.props.testId }
|
||||
id = { this.props.id }
|
||||
style = { this._getAvatarStyle(this.props.color) }>
|
||||
<svg
|
||||
@@ -97,6 +105,7 @@ export default class StatelessAvatar extends AbstractStatelessAvatar<Props> {
|
||||
<div className = { this._getBadgeClassName() }>
|
||||
<img
|
||||
className = { this._getAvatarClassName('defaultAvatar') }
|
||||
data-testid = { this.props.testId }
|
||||
id = { this.props.id }
|
||||
src = { this.props.defaultAvatar || 'images/avatar.png' }
|
||||
style = { this._getAvatarStyle() } />
|
||||
|
||||
@@ -122,6 +122,7 @@ export default [
|
||||
'ignoreStartMuted',
|
||||
'liveStreamingEnabled',
|
||||
'localRecording',
|
||||
'maxFullResolutionParticipants',
|
||||
'minParticipants',
|
||||
'nick',
|
||||
'openBridgeChannel',
|
||||
|
||||
56
react/features/base/lastn/functions.js
Normal file
56
react/features/base/lastn/functions.js
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Checks if the given Object is a correct last N limit mapping, coverts both keys and values to numbers and sorts
|
||||
* the keys in ascending order.
|
||||
*
|
||||
* @param {Object} lastNLimits - The Object to be verified.
|
||||
* @returns {undefined|Map<number, number>}
|
||||
*/
|
||||
export function validateLastNLimits(lastNLimits) {
|
||||
// Checks if only numbers are used
|
||||
if (typeof lastNLimits !== 'object'
|
||||
|| !Object.keys(lastNLimits).length
|
||||
|| Object.keys(lastNLimits)
|
||||
.find(limit => limit === null || isNaN(Number(limit))
|
||||
|| lastNLimits[limit] === null || isNaN(Number(lastNLimits[limit])))) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Converts to numbers and sorts the keys
|
||||
const sortedMapping = new Map();
|
||||
const orderedLimits = Object.keys(lastNLimits)
|
||||
.map(n => Number(n))
|
||||
.sort((n1, n2) => n1 - n2);
|
||||
|
||||
for (const limit of orderedLimits) {
|
||||
sortedMapping.set(limit, Number(lastNLimits[limit]));
|
||||
}
|
||||
|
||||
return sortedMapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns "last N" value which corresponds to a level defined in the {@code lastNLimits} mapping. See
|
||||
* {@code config.js} for more detailed explanation on how the mapping is defined.
|
||||
*
|
||||
* @param {number} participantsCount - The current number of participants in the conference.
|
||||
* @param {Map<number, number>} [lastNLimits] - The mapping of number of participants to "last N" values. NOTE that
|
||||
* this function expects a Map that has been preprocessed by {@link validateLastNLimits}, because the keys must be
|
||||
* sorted in ascending order and both keys and values should be numbers.
|
||||
* @returns {number|undefined} - A "last N" number if there was a corresponding "last N" value matched with the number
|
||||
* of participants or {@code undefined} otherwise.
|
||||
*/
|
||||
export function limitLastN(participantsCount, lastNLimits) {
|
||||
if (!lastNLimits || !lastNLimits.keys) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let selectedLimit;
|
||||
|
||||
for (const participantsN of lastNLimits.keys()) {
|
||||
if (participantsCount >= participantsN) {
|
||||
selectedLimit = participantsN;
|
||||
}
|
||||
}
|
||||
|
||||
return selectedLimit ? lastNLimits.get(selectedLimit) : undefined;
|
||||
}
|
||||
103
react/features/base/lastn/functions.test.js
Normal file
103
react/features/base/lastn/functions.test.js
Normal file
@@ -0,0 +1,103 @@
|
||||
import { limitLastN, validateLastNLimits } from './functions';
|
||||
|
||||
describe('limitLastN', () => {
|
||||
it('handles undefined mapping', () => {
|
||||
expect(limitLastN(0, undefined)).toBe(undefined);
|
||||
});
|
||||
describe('when a correct limit mapping is given', () => {
|
||||
const limits = new Map();
|
||||
|
||||
limits.set(5, -1);
|
||||
limits.set(10, 8);
|
||||
limits.set(20, 5);
|
||||
|
||||
it('returns undefined when less participants that the first limit', () => {
|
||||
expect(limitLastN(2, limits)).toBe(undefined);
|
||||
});
|
||||
it('picks the first limit correctly', () => {
|
||||
expect(limitLastN(5, limits)).toBe(-1);
|
||||
expect(limitLastN(9, limits)).toBe(-1);
|
||||
});
|
||||
it('picks the middle limit correctly', () => {
|
||||
expect(limitLastN(10, limits)).toBe(8);
|
||||
expect(limitLastN(13, limits)).toBe(8);
|
||||
expect(limitLastN(19, limits)).toBe(8);
|
||||
});
|
||||
it('picks the top limit correctly', () => {
|
||||
expect(limitLastN(20, limits)).toBe(5);
|
||||
expect(limitLastN(23, limits)).toBe(5);
|
||||
expect(limitLastN(100, limits)).toBe(5);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('validateLastNLimits', () => {
|
||||
describe('validates the input by returning undefined', () => {
|
||||
it('if lastNLimits param is not an Object', () => {
|
||||
expect(validateLastNLimits(5)).toBe(undefined);
|
||||
});
|
||||
it('if any key is not a number', () => {
|
||||
const limits = {
|
||||
'abc': 8,
|
||||
5: -1,
|
||||
20: 5
|
||||
};
|
||||
|
||||
expect(validateLastNLimits(limits)).toBe(undefined);
|
||||
});
|
||||
it('if any value is not a number', () => {
|
||||
const limits = {
|
||||
8: 'something',
|
||||
5: -1,
|
||||
20: 5
|
||||
};
|
||||
|
||||
expect(validateLastNLimits(limits)).toBe(undefined);
|
||||
});
|
||||
it('if any value is null', () => {
|
||||
const limits = {
|
||||
1: 1,
|
||||
5: null,
|
||||
20: 5
|
||||
};
|
||||
|
||||
expect(validateLastNLimits(limits)).toBe(undefined);
|
||||
});
|
||||
it('if any value is undefined', () => {
|
||||
const limits = {
|
||||
1: 1,
|
||||
5: undefined,
|
||||
20: 5
|
||||
};
|
||||
|
||||
expect(validateLastNLimits(limits)).toBe(undefined);
|
||||
});
|
||||
it('if the map is empty', () => {
|
||||
expect(validateLastNLimits({})).toBe(undefined);
|
||||
});
|
||||
});
|
||||
it('sorts by the keys', () => {
|
||||
const mappingKeys = validateLastNLimits({
|
||||
10: 5,
|
||||
3: 3,
|
||||
5: 4
|
||||
}).keys();
|
||||
|
||||
expect(mappingKeys.next().value).toBe(3);
|
||||
expect(mappingKeys.next().value).toBe(5);
|
||||
expect(mappingKeys.next().value).toBe(10);
|
||||
expect(mappingKeys.next().done).toBe(true);
|
||||
});
|
||||
it('converts keys and values to numbers', () => {
|
||||
const mapping = validateLastNLimits({
|
||||
3: 3,
|
||||
5: 4,
|
||||
10: 5
|
||||
});
|
||||
|
||||
for (const key of mapping.keys()) {
|
||||
expect(typeof key).toBe('number');
|
||||
expect(typeof mapping.get(key)).toBe('number');
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -4,11 +4,21 @@ import { SET_FILMSTRIP_ENABLED } from '../../filmstrip/actionTypes';
|
||||
import { SELECT_LARGE_VIDEO_PARTICIPANT } from '../../large-video/actionTypes';
|
||||
import { APP_STATE_CHANGED } from '../../mobile/background/actionTypes';
|
||||
import { SCREEN_SHARE_PARTICIPANTS_UPDATED, SET_TILE_VIEW } from '../../video-layout/actionTypes';
|
||||
import { shouldDisplayTileView } from '../../video-layout/functions';
|
||||
import { SET_AUDIO_ONLY } from '../audio-only/actionTypes';
|
||||
import { CONFERENCE_JOINED } from '../conference/actionTypes';
|
||||
import { getParticipantById } from '../participants/functions';
|
||||
import {
|
||||
PARTICIPANT_JOINED,
|
||||
PARTICIPANT_KICKED,
|
||||
PARTICIPANT_LEFT
|
||||
} from '../participants/actionTypes';
|
||||
import {
|
||||
getParticipantById,
|
||||
getParticipantCount
|
||||
} from '../participants/functions';
|
||||
import { MiddlewareRegistry } from '../redux';
|
||||
|
||||
import { limitLastN } from './functions';
|
||||
import logger from './logger';
|
||||
|
||||
declare var APP: Object;
|
||||
@@ -20,6 +30,9 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
switch (action.type) {
|
||||
case APP_STATE_CHANGED:
|
||||
case CONFERENCE_JOINED:
|
||||
case PARTICIPANT_JOINED:
|
||||
case PARTICIPANT_KICKED:
|
||||
case PARTICIPANT_LEFT:
|
||||
case SCREEN_SHARE_PARTICIPANTS_UPDATED:
|
||||
case SELECT_LARGE_VIDEO_PARTICIPANT:
|
||||
case SET_AUDIO_ONLY:
|
||||
@@ -46,6 +59,8 @@ function _updateLastN({ getState }) {
|
||||
const { appState } = state['features/background'] || {};
|
||||
const { enabled: filmStripEnabled } = state['features/filmstrip'];
|
||||
const config = state['features/base/config'];
|
||||
const { lastNLimits } = state['features/base/lastn'];
|
||||
const participantCount = getParticipantCount(state);
|
||||
|
||||
if (!conference) {
|
||||
logger.debug('There is no active conference, not updating last N');
|
||||
@@ -56,10 +71,18 @@ function _updateLastN({ getState }) {
|
||||
const defaultLastN = typeof config.channelLastN === 'undefined' ? -1 : config.channelLastN;
|
||||
let lastN = defaultLastN;
|
||||
|
||||
// Apply last N limit based on the # of participants
|
||||
const limitedLastN = limitLastN(participantCount, lastNLimits);
|
||||
|
||||
if (limitedLastN !== undefined) {
|
||||
lastN = limitedLastN;
|
||||
}
|
||||
|
||||
if (typeof appState !== 'undefined' && appState !== 'active') {
|
||||
lastN = 0;
|
||||
} else if (audioOnly) {
|
||||
const { screenShares, tileViewEnabled } = state['features/video-layout'];
|
||||
const { screenShares } = state['features/video-layout'];
|
||||
const tileViewEnabled = shouldDisplayTileView(state);
|
||||
const largeVideoParticipantId = state['features/large-video'].participantId;
|
||||
const largeVideoParticipant
|
||||
= largeVideoParticipantId ? getParticipantById(state, largeVideoParticipantId) : undefined;
|
||||
|
||||
27
react/features/base/lastn/reducer.js
Normal file
27
react/features/base/lastn/reducer.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import {
|
||||
SET_CONFIG
|
||||
} from '../config';
|
||||
import { ReducerRegistry, set } from '../redux';
|
||||
|
||||
import { validateLastNLimits } from './functions';
|
||||
|
||||
ReducerRegistry.register('features/base/lastn', (state = { }, action) => {
|
||||
switch (action.type) {
|
||||
case SET_CONFIG:
|
||||
return _setConfig(state, action);
|
||||
}
|
||||
|
||||
return state;
|
||||
});
|
||||
|
||||
/**
|
||||
* Reduces a specific Redux action SET_CONFIG.
|
||||
*
|
||||
* @param {Object} state - The Redux state of feature base/lastn.
|
||||
* @param {Action} action - The Redux action SET_CONFIG to reduce.
|
||||
* @private
|
||||
* @returns {Object} The new state after the reduction of the specified action.
|
||||
*/
|
||||
function _setConfig(state, { config }) {
|
||||
return set(state, 'lastNLimits', validateLastNLimits(config.lastNLimits));
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
|
||||
import { YoutubeLargeVideo } from '../../../youtube-player';
|
||||
import { YoutubeLargeVideo } from '../../../youtube-player/components';
|
||||
import { Avatar } from '../../avatar';
|
||||
import { translate } from '../../i18n';
|
||||
import { JitsiParticipantConnectionStatus } from '../../lib-jitsi-meet';
|
||||
|
||||
@@ -26,6 +26,11 @@ type Props = {
|
||||
*/
|
||||
hasOptions?: boolean,
|
||||
|
||||
/**
|
||||
* TestId of the button. Can be used to locate element when testing UI.
|
||||
*/
|
||||
testId?: string,
|
||||
|
||||
/**
|
||||
* The type of th button: primary, secondary, text.
|
||||
*/
|
||||
@@ -52,6 +57,7 @@ function ActionButton({
|
||||
className = '',
|
||||
disabled,
|
||||
hasOptions,
|
||||
testId,
|
||||
type = 'primary',
|
||||
onClick,
|
||||
onOptionsClick
|
||||
@@ -59,6 +65,7 @@ function ActionButton({
|
||||
return (
|
||||
<div
|
||||
className = { `action-btn ${className} ${type} ${disabled ? 'disabled' : ''}` }
|
||||
data-testid = { testId ? testId : undefined }
|
||||
onClick = { disabled ? undefined : onClick }>
|
||||
{children}
|
||||
{hasOptions && <div
|
||||
|
||||
@@ -11,6 +11,11 @@ type Props = {
|
||||
*/
|
||||
className?: string,
|
||||
|
||||
/**
|
||||
* TestId of the button. Can be used to locate element when testing UI.
|
||||
*/
|
||||
testId?: string,
|
||||
|
||||
/**
|
||||
* Callback for the onChange event of the field.
|
||||
*/
|
||||
@@ -105,6 +110,7 @@ export default class InputField extends PureComponent<Props, State> {
|
||||
return (
|
||||
<input
|
||||
className = { `field ${this.state.focused ? 'focused' : ''} ${this.props.className || ''}` }
|
||||
data-testid = { this.props.testId ? this.props.testId : undefined }
|
||||
onBlur = { this._onBlur }
|
||||
onChange = { this._onChange }
|
||||
onFocus = { this._onFocus }
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
import { AudioSettingsButton, VideoSettingsButton } from '../../../../toolbox';
|
||||
import { AudioSettingsButton, VideoSettingsButton } from '../../../../toolbox/components/web';
|
||||
|
||||
import CopyMeetingUrl from './CopyMeetingUrl';
|
||||
import Preview from './Preview';
|
||||
|
||||
@@ -47,6 +47,11 @@ type Props = {
|
||||
*/
|
||||
_welcomePageIsVisible: boolean,
|
||||
|
||||
/**
|
||||
* The default value for the Jitsi logo URL.
|
||||
*/
|
||||
defaultJitsiLogoURL: ?string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
@@ -218,13 +223,14 @@ class Watermarks extends Component<Props, State> {
|
||||
let reactElement = null;
|
||||
const {
|
||||
_customLogoUrl,
|
||||
_customLogoLink
|
||||
_customLogoLink,
|
||||
defaultJitsiLogoURL
|
||||
} = this.props;
|
||||
|
||||
if (this._canDisplayJitsiWatermark()) {
|
||||
const link = _customLogoLink || this.state.jitsiWatermarkLink;
|
||||
const style = {
|
||||
backgroundImage: `url(${_customLogoUrl || interfaceConfig.DEFAULT_LOGO_URL})`,
|
||||
backgroundImage: `url(${_customLogoUrl || defaultJitsiLogoURL || interfaceConfig.DEFAULT_LOGO_URL})`,
|
||||
maxWidth: 140,
|
||||
maxHeight: 70
|
||||
};
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
// @flow
|
||||
|
||||
export * from './components';
|
||||
@@ -6,8 +6,8 @@ import { createVideoBlurEvent, sendAnalytics } from '../../analytics';
|
||||
import { translate } from '../../base/i18n';
|
||||
import { IconBlurBackground } from '../../base/icons';
|
||||
import { connect } from '../../base/redux';
|
||||
import { AbstractButton, BetaTag } from '../../base/toolbox';
|
||||
import type { AbstractButtonProps } from '../../base/toolbox';
|
||||
import { AbstractButton, BetaTag } from '../../base/toolbox/components';
|
||||
import type { AbstractButtonProps } from '../../base/toolbox/components';
|
||||
import { toggleBlurEffect } from '../actions';
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,7 @@ import { translate } from '../../base/i18n';
|
||||
import { IconMessage, IconReply } from '../../base/icons';
|
||||
import { getParticipantById } from '../../base/participants';
|
||||
import { connect } from '../../base/redux';
|
||||
import { AbstractButton, type AbstractButtonProps } from '../../base/toolbox';
|
||||
import { AbstractButton, type AbstractButtonProps } from '../../base/toolbox/components';
|
||||
import { setPrivateMessageRecipient } from '../actions';
|
||||
|
||||
export type Props = AbstractButtonProps & {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { connect } from '../../../base/redux';
|
||||
import {
|
||||
AbstractButton,
|
||||
type AbstractButtonProps
|
||||
} from '../../../base/toolbox';
|
||||
} from '../../../base/toolbox/components';
|
||||
import { openDisplayNamePrompt } from '../../../display-name';
|
||||
import { CHAT_VIEW_MODAL_ID } from '../../constants';
|
||||
import { getUnreadCount } from '../../functions';
|
||||
|
||||
@@ -18,7 +18,8 @@ import {
|
||||
} from '../base/participants';
|
||||
import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
|
||||
import { playSound, registerSound, unregisterSound } from '../base/sounds';
|
||||
import { isButtonEnabled, showToolbox } from '../toolbox';
|
||||
import { showToolbox } from '../toolbox/actions';
|
||||
import { isButtonEnabled } from '../toolbox/functions';
|
||||
|
||||
import { SEND_MESSAGE, SET_PRIVATE_MESSAGE_RECIPIENT } from './actionTypes';
|
||||
import { addMessage, clearMessages, toggleChat } from './actions';
|
||||
|
||||
@@ -25,7 +25,9 @@ import { LargeVideo } from '../../../large-video';
|
||||
import { KnockingParticipantList } from '../../../lobby';
|
||||
import { BackButtonRegistry } from '../../../mobile/back-button';
|
||||
import { Captions } from '../../../subtitles';
|
||||
import { isToolboxVisible, setToolboxVisible, Toolbox } from '../../../toolbox';
|
||||
import { setToolboxVisible } from '../../../toolbox/actions';
|
||||
import { Toolbox } from '../../../toolbox/components/native';
|
||||
import { isToolboxVisible } from '../../../toolbox/functions';
|
||||
import {
|
||||
AbstractConference,
|
||||
abstractMapStateToProps
|
||||
|
||||
@@ -8,7 +8,7 @@ import { getConferenceName } from '../../../base/conference';
|
||||
import { getFeatureFlag, CONFERENCE_TIMER_ENABLED, MEETING_NAME_ENABLED } from '../../../base/flags';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { PictureInPictureButton } from '../../../mobile/picture-in-picture';
|
||||
import { isToolboxVisible } from '../../../toolbox';
|
||||
import { isToolboxVisible } from '../../../toolbox/functions.native';
|
||||
import ConferenceTimer from '../ConferenceTimer';
|
||||
|
||||
import styles, { NAVBAR_GRADIENT_COLORS } from './styles';
|
||||
|
||||
@@ -14,12 +14,8 @@ import { CalleeInfoContainer } from '../../../invite';
|
||||
import { LargeVideo } from '../../../large-video';
|
||||
import { KnockingParticipantList, LobbyScreen } from '../../../lobby';
|
||||
import { Prejoin, isPrejoinPageVisible } from '../../../prejoin';
|
||||
import {
|
||||
Toolbox,
|
||||
fullScreenChanged,
|
||||
setToolboxAlwaysVisible,
|
||||
showToolbox
|
||||
} from '../../../toolbox';
|
||||
import { fullScreenChanged, setToolboxAlwaysVisible, showToolbox } from '../../../toolbox/actions.web';
|
||||
import { Toolbox } from '../../../toolbox/components/web';
|
||||
import { LAYOUTS, getCurrentLayout } from '../../../video-layout';
|
||||
import { maybeShowSuboptimalExperienceNotification } from '../../functions';
|
||||
import {
|
||||
|
||||
@@ -7,10 +7,8 @@ import { Icon, IconInviteMore } from '../../../base/icons';
|
||||
import { getParticipantCount } from '../../../base/participants';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { beginAddPeople } from '../../../invite';
|
||||
import {
|
||||
isButtonEnabled,
|
||||
isToolboxVisible
|
||||
} from '../../../toolbox';
|
||||
import { isButtonEnabled, isToolboxVisible } from '../../../toolbox/functions.web';
|
||||
import { shouldDisplayTileView } from '../../../video-layout/functions';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
@@ -83,7 +81,7 @@ function mapStateToProps(state) {
|
||||
const hide = interfaceConfig.HIDE_INVITE_MORE_HEADER;
|
||||
|
||||
return {
|
||||
_tileViewEnabled: state['features/video-layout'].tileViewEnabled,
|
||||
_tileViewEnabled: shouldDisplayTileView(state),
|
||||
_visible: isToolboxVisible(state) && isButtonEnabled('invite') && isAlone && !hide
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import React, { Component } from 'react';
|
||||
import { getConferenceName } from '../../../base/conference/functions';
|
||||
import { getParticipantCount } from '../../../base/participants/functions';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { isToolboxVisible } from '../../../toolbox';
|
||||
import { isToolboxVisible } from '../../../toolbox/functions.web';
|
||||
import ConferenceTimer from '../ConferenceTimer';
|
||||
|
||||
import ParticipantsCount from './ParticipantsCount';
|
||||
|
||||
@@ -13,7 +13,7 @@ import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
|
||||
import { SET_REDUCED_UI } from '../base/responsive-ui';
|
||||
import { FeedbackDialog } from '../feedback';
|
||||
import { setFilmstripEnabled } from '../filmstrip';
|
||||
import { setToolboxEnabled } from '../toolbox';
|
||||
import { setToolboxEnabled } from '../toolbox/actions';
|
||||
|
||||
import { notifyKickedOut } from './actions';
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ class DeepLinkingDesktopPage<P : Props> extends Component<P> {
|
||||
*/
|
||||
render() {
|
||||
const { t } = this.props;
|
||||
const { NATIVE_APP_NAME, SHOW_DEEP_LINKING_IMAGE } = interfaceConfig;
|
||||
const { HIDE_DEEP_LINKING_LOGO, NATIVE_APP_NAME, SHOW_DEEP_LINKING_IMAGE } = interfaceConfig;
|
||||
const rightColumnStyle
|
||||
= SHOW_DEEP_LINKING_IMAGE ? null : { width: '100%' };
|
||||
|
||||
@@ -82,9 +82,13 @@ class DeepLinkingDesktopPage<P : Props> extends Component<P> {
|
||||
<AtlasKitThemeProvider mode = 'light'>
|
||||
<div className = 'deep-linking-desktop'>
|
||||
<div className = 'header'>
|
||||
<img
|
||||
className = 'logo'
|
||||
src = 'images/logo-deep-linking.png' />
|
||||
{
|
||||
HIDE_DEEP_LINKING_LOGO
|
||||
? null
|
||||
: <img
|
||||
className = 'logo'
|
||||
src = 'images/logo-deep-linking.png' />
|
||||
}
|
||||
</div>
|
||||
<div className = 'content'>
|
||||
{
|
||||
|
||||
@@ -91,7 +91,7 @@ class DeepLinkingMobilePage extends Component<Props> {
|
||||
*/
|
||||
render() {
|
||||
const { _downloadUrl, _room, t } = this.props;
|
||||
const { NATIVE_APP_NAME, SHOW_DEEP_LINKING_IMAGE } = interfaceConfig;
|
||||
const { HIDE_DEEP_LINKING_LOGO, NATIVE_APP_NAME, SHOW_DEEP_LINKING_IMAGE } = interfaceConfig;
|
||||
const downloadButtonClassName
|
||||
= `${_SNS}__button ${_SNS}__button_primary`;
|
||||
|
||||
@@ -115,9 +115,13 @@ class DeepLinkingMobilePage extends Component<Props> {
|
||||
return (
|
||||
<div className = { _SNS }>
|
||||
<div className = 'header'>
|
||||
<img
|
||||
className = 'logo'
|
||||
src = 'images/logo-deep-linking.png' />
|
||||
{
|
||||
HIDE_DEEP_LINKING_LOGO
|
||||
? null
|
||||
: <img
|
||||
className = 'logo'
|
||||
src = 'images/logo-deep-linking.png' />
|
||||
}
|
||||
</div>
|
||||
<div className = { `${_SNS}__body` }>
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ import { createToolbarEvent, sendAnalytics } from '../../analytics';
|
||||
import { translate } from '../../base/i18n';
|
||||
import { IconShareDoc } from '../../base/icons';
|
||||
import { connect } from '../../base/redux';
|
||||
import { AbstractButton, type AbstractButtonProps } from '../../base/toolbox';
|
||||
import { AbstractButton, type AbstractButtonProps } from '../../base/toolbox/components';
|
||||
import { toggleDocument } from '../actions';
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import { getTrackByMediaTypeAndParticipant } from '../../../base/tracks';
|
||||
import { ConnectionIndicator } from '../../../connection-indicator';
|
||||
import { DisplayNameLabel } from '../../../display-name';
|
||||
import { RemoteVideoMenu } from '../../../remote-video-menu';
|
||||
import { toggleToolboxVisible } from '../../../toolbox';
|
||||
import { toggleToolboxVisible } from '../../../toolbox/actions.native';
|
||||
|
||||
import AudioMutedIndicator from './AudioMutedIndicator';
|
||||
import DominantSpeakerIndicator from './DominantSpeakerIndicator';
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { Icon, IconMenuDown, IconMenuUp } from '../../../base/icons';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { dockToolbox } from '../../../toolbox';
|
||||
import { dockToolbox } from '../../../toolbox/actions.web';
|
||||
import { getCurrentLayout, LAYOUTS } from '../../../video-layout';
|
||||
import { setFilmstripHovered, setFilmstripVisible } from '../../actions';
|
||||
import { shouldRemoteVideosBeVisible } from '../../functions';
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
AudioMuteButton,
|
||||
HangupButton,
|
||||
VideoMuteButton
|
||||
} from '../../../toolbox';
|
||||
} from '../../../toolbox/components';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
|
||||
@@ -152,17 +152,14 @@ function _onFollowMeCommand(attributes = {}, id, store) {
|
||||
}
|
||||
}
|
||||
|
||||
const pinnedParticipant
|
||||
= getPinnedParticipant(state, attributes.nextOnStage);
|
||||
const pinnedParticipant = getPinnedParticipant(state);
|
||||
const idOfParticipantToPin = attributes.nextOnStage;
|
||||
|
||||
if (typeof idOfParticipantToPin !== 'undefined'
|
||||
&& (!pinnedParticipant
|
||||
|| idOfParticipantToPin !== pinnedParticipant.id)
|
||||
&& (!pinnedParticipant || idOfParticipantToPin !== pinnedParticipant.id)
|
||||
&& oldState.nextOnStage !== attributes.nextOnStage) {
|
||||
_pinVideoThumbnailById(store, idOfParticipantToPin);
|
||||
} else if (typeof idOfParticipantToPin === 'undefined'
|
||||
&& pinnedParticipant) {
|
||||
} else if (typeof idOfParticipantToPin === 'undefined' && pinnedParticipant) {
|
||||
store.dispatch(pinParticipant(null));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
isLocalParticipantModerator
|
||||
} from '../base/participants';
|
||||
import { StateListenerRegistry } from '../base/redux';
|
||||
import { shouldDisplayTileView } from '../video-layout/functions';
|
||||
|
||||
import { FOLLOW_ME_COMMAND } from './constants';
|
||||
|
||||
@@ -72,7 +73,7 @@ function _getFollowMeState(state) {
|
||||
filmstripVisible: state['features/filmstrip'].visible,
|
||||
nextOnStage: pinnedParticipant && pinnedParticipant.id,
|
||||
sharedDocumentVisible: state['features/etherpad'].editing,
|
||||
tileViewEnabled: state['features/video-layout'].tileViewEnabled
|
||||
tileViewEnabled: shouldDisplayTileView(state)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,7 @@ import { getFeatureFlag, INVITE_ENABLED } from '../../../../base/flags';
|
||||
import { translate } from '../../../../base/i18n';
|
||||
import { IconAddPeople } from '../../../../base/icons';
|
||||
import { connect } from '../../../../base/redux';
|
||||
import { AbstractButton } from '../../../../base/toolbox';
|
||||
import type { AbstractButtonProps } from '../../../../base/toolbox';
|
||||
import { AbstractButton, type AbstractButtonProps } from '../../../../base/toolbox/components';
|
||||
import { doInvitePeople } from '../../../actions.native';
|
||||
|
||||
type Props = AbstractButtonProps & {
|
||||
|
||||
@@ -5,7 +5,7 @@ import React from 'react';
|
||||
import { Avatar } from '../../../base/avatar';
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { isToolboxVisible } from '../../../toolbox';
|
||||
import { isToolboxVisible } from '../../../toolbox/functions.web';
|
||||
import AbstractKnockingParticipantList, {
|
||||
mapStateToProps as abstractMapStateToProps,
|
||||
type Props as AbstractProps
|
||||
@@ -48,25 +48,28 @@ class KnockingParticipantList extends AbstractKnockingParticipantList<Props> {
|
||||
<Avatar
|
||||
displayName = { p.name }
|
||||
size = { 48 }
|
||||
testId = 'knockingParticipant.avatar'
|
||||
url = { p.loadableAvatarUrl } />
|
||||
<div className = 'details'>
|
||||
<span>
|
||||
<span data-testid = 'knockingParticipant.name'>
|
||||
{ p.name }
|
||||
</span>
|
||||
{ p.email && (
|
||||
<span>
|
||||
<span data-testid = 'knockingParticipant.email'>
|
||||
{ p.email }
|
||||
</span>
|
||||
) }
|
||||
</div>
|
||||
<button
|
||||
className = 'primary'
|
||||
data-testid = 'lobby.allow'
|
||||
onClick = { this._onRespondToParticipant(p.id, true) }
|
||||
type = 'button'>
|
||||
{ t('lobby.allow') }
|
||||
</button>
|
||||
<button
|
||||
className = 'borderLess'
|
||||
data-testid = 'lobby.reject'
|
||||
onClick = { this._onRespondToParticipant(p.id, false) }
|
||||
type = 'button'>
|
||||
{ t('lobby.reject') }
|
||||
|
||||
@@ -97,6 +97,7 @@ class LobbyScreen extends AbstractLobbyScreen {
|
||||
<InputField
|
||||
onChange = { this._onChangeDisplayName }
|
||||
placeHolder = { t('lobby.nameField') }
|
||||
testId = 'lobby.nameField'
|
||||
value = { displayName } />
|
||||
</div>
|
||||
</div>
|
||||
@@ -117,6 +118,7 @@ class LobbyScreen extends AbstractLobbyScreen {
|
||||
className = { _passwordJoinFailed ? 'error' : '' }
|
||||
onChange = { this._onChangePassword }
|
||||
placeHolder = { _passwordJoinFailed ? t('lobby.invalidPassword') : t('lobby.passwordField') }
|
||||
testId = 'lobby.password'
|
||||
type = 'password'
|
||||
value = { this.state.password } />
|
||||
</div>
|
||||
@@ -136,11 +138,13 @@ class LobbyScreen extends AbstractLobbyScreen {
|
||||
<ActionButton
|
||||
disabled = { !this.state.password }
|
||||
onClick = { this._onJoinWithPassword }
|
||||
testId = 'lobby.passwordJoinButton'
|
||||
type = 'primary'>
|
||||
{ t('lobby.passwordJoinButton') }
|
||||
</ActionButton>
|
||||
<ActionButton
|
||||
onClick = { this._onSwitchToKnockMode }
|
||||
testId = 'lobby.backToKnockModeButton'
|
||||
type = 'secondary'>
|
||||
{ t('lobby.backToKnockModeButton') }
|
||||
</ActionButton>
|
||||
@@ -161,11 +165,13 @@ class LobbyScreen extends AbstractLobbyScreen {
|
||||
{ _knocking || <ActionButton
|
||||
disabled = { !this.state.displayName }
|
||||
onClick = { this._onAskToJoin }
|
||||
testId = 'lobby.knockButton'
|
||||
type = 'primary'>
|
||||
{ t('lobby.knockButton') }
|
||||
</ActionButton> }
|
||||
<ActionButton
|
||||
onClick = { this._onSwitchToPasswordMode }
|
||||
testId = 'lobby.enterPasswordButton'
|
||||
type = 'secondary'>
|
||||
{ t('lobby.enterPasswordButton') }
|
||||
</ActionButton>
|
||||
|
||||
@@ -59,18 +59,19 @@ class LobbySection extends PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements {@code PureComponent#componentDidUpdate}.
|
||||
* Implements React's {@link Component#getDerivedStateFromProps()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (this.props._lobbyEnabled !== prevProps._lobbyEnabled
|
||||
&& this.state.lobbyEnabled !== prevState.lobbyEnabled) {
|
||||
// eslint-disable-next-line react/no-did-update-set-state
|
||||
this.setState({
|
||||
lobbyEnabled: this.props._lobbyEnabled
|
||||
});
|
||||
static getDerivedStateFromProps(props: Props, state: Object) {
|
||||
if (props._lobbyEnabled !== state.lobbyEnabled) {
|
||||
|
||||
return {
|
||||
lobbyEnabled: props._lobbyEnabled
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,23 +1,6 @@
|
||||
// @flow
|
||||
|
||||
import { getCurrentConference } from '../base/conference';
|
||||
import { toState } from '../base/redux';
|
||||
|
||||
const JID_PATTERN = '[^@]+@[^/]+/(.+)';
|
||||
|
||||
/**
|
||||
* Returns a knocking participant by ID or JID.
|
||||
*
|
||||
* @param {Function | Object} stateful - The Redux state or a function that resolves to the Redux state.
|
||||
* @param {string} id - The ID or JID of the participant.
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function getKnockingParticipantById(stateful: Function | Object, id: string): Object {
|
||||
const { knockingParticipants } = toState(stateful)['features/lobby'];
|
||||
const idToFind = getIdFromJid(id) || id;
|
||||
|
||||
return knockingParticipants.find(p => p.id === idToFind);
|
||||
}
|
||||
|
||||
/**
|
||||
* Approves (lets in) or rejects a knocking participant.
|
||||
@@ -38,15 +21,3 @@ export function setKnockingParticipantApproval(getState: Function, id: string, a
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an ID from a JID, if a JID is provided, undefined otherwise.
|
||||
*
|
||||
* @param {string} jid - The JID to get the ID from.
|
||||
* @returns {?string}
|
||||
*/
|
||||
function getIdFromJid(jid: string): ?string {
|
||||
const match = new RegExp(JID_PATTERN, 'g').exec(jid) || [];
|
||||
|
||||
return match[1];
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import {
|
||||
startKnocking,
|
||||
setPasswordJoinFailed
|
||||
} from './actions';
|
||||
import { getKnockingParticipantById } from './functions';
|
||||
|
||||
MiddlewareRegistry.register(store => next => action => {
|
||||
switch (action.type) {
|
||||
@@ -176,7 +175,8 @@ function _maybeSendLobbyNotification(origin, message, { dispatch, getState }) {
|
||||
|
||||
const notificationProps: any = {
|
||||
descriptionArguments: {
|
||||
originParticipantName: getParticipantDisplayName(getState, origin._id)
|
||||
originParticipantName: getParticipantDisplayName(getState, origin._id),
|
||||
targetParticipantName: message.name
|
||||
},
|
||||
titleKey: 'lobby.notificationTitle'
|
||||
};
|
||||
@@ -187,13 +187,9 @@ function _maybeSendLobbyNotification(origin, message, { dispatch, getState }) {
|
||||
break;
|
||||
case 'LOBBY-ACCESS-GRANTED':
|
||||
notificationProps.descriptionKey = 'lobby.notificationLobbyAccessGranted';
|
||||
notificationProps.descriptionArguments.targetParticipantName
|
||||
= getKnockingParticipantById(getState, message.value)?.name;
|
||||
break;
|
||||
case 'LOBBY-ACCESS-DENIED':
|
||||
notificationProps.descriptionKey = 'lobby.notificationLobbyAccessDenied';
|
||||
notificationProps.descriptionArguments.targetParticipantName
|
||||
= getKnockingParticipantById(getState, message.value)?.name;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import React, { Component } from 'react';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
import { IconRec } from '../../base/icons';
|
||||
import { ToolbarButton } from '../../toolbox';
|
||||
import { ToolbarButton } from '../../toolbox/components/web';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of
|
||||
@@ -4,8 +4,7 @@ import { openDialog } from '../../../base/dialog';
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { IconAudioRoute } from '../../../base/icons';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { AbstractButton } from '../../../base/toolbox';
|
||||
import type { AbstractButtonProps } from '../../../base/toolbox';
|
||||
import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components';
|
||||
|
||||
import AudioRoutePickerDialog from './AudioRoutePickerDialog';
|
||||
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { IconHangup } from '../../../base/icons';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { AbstractButton } from '../../../base/toolbox';
|
||||
import type { AbstractButtonProps } from '../../../base/toolbox';
|
||||
import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components';
|
||||
import { incomingCallAnswered } from '../actions';
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { IconHangup } from '../../../base/icons';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { AbstractButton } from '../../../base/toolbox';
|
||||
import type { AbstractButtonProps } from '../../../base/toolbox';
|
||||
import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components';
|
||||
import { incomingCallDeclined } from '../actions';
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,8 +6,7 @@ import { PIP_ENABLED, getFeatureFlag } from '../../../base/flags';
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { IconMenuDown } from '../../../base/icons';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { AbstractButton } from '../../../base/toolbox';
|
||||
import type { AbstractButtonProps } from '../../../base/toolbox';
|
||||
import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components';
|
||||
import { enterPictureInPicture } from '../actions';
|
||||
|
||||
type Props = AbstractButtonProps & {
|
||||
|
||||
@@ -148,6 +148,18 @@ export default class AbstractNotification<P: Props> extends Component<P> {
|
||||
return descriptionArray;
|
||||
}
|
||||
|
||||
_getDescriptionKey: () => string
|
||||
|
||||
/**
|
||||
* Returns the description key that was used if any.
|
||||
*
|
||||
* @protected
|
||||
* @returns {string}
|
||||
*/
|
||||
_getDescriptionKey() {
|
||||
return this.props.descriptionKey;
|
||||
}
|
||||
|
||||
_onDismissed: () => void;
|
||||
|
||||
/**
|
||||
|
||||
@@ -62,12 +62,15 @@ class Notification extends AbstractNotification<Props> {
|
||||
id = { uid }
|
||||
isDismissAllowed = { isDismissAllowed }
|
||||
onDismissed = { onDismissed }
|
||||
testId = { titleKey }
|
||||
title = { title || t(titleKey, titleArguments) } />
|
||||
);
|
||||
}
|
||||
|
||||
_getDescription: () => Array<string>
|
||||
|
||||
_getDescriptionKey: () => string
|
||||
|
||||
_onDismissed: () => void;
|
||||
|
||||
/**
|
||||
@@ -78,11 +81,12 @@ class Notification extends AbstractNotification<Props> {
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
_renderDescription() {
|
||||
const description = this._getDescription();
|
||||
|
||||
// the id is used for testing the UI
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
this._getDescription()
|
||||
}
|
||||
<div data-testid = { this._getDescriptionKey() } >
|
||||
{ description }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// @flow
|
||||
|
||||
import { FlagGroup } from '@atlaskit/flag';
|
||||
import Portal from '@atlaskit/portal';
|
||||
import React from 'react';
|
||||
import { Transition, TransitionGroup } from 'react-transition-group';
|
||||
|
||||
import { connect } from '../../../base/redux';
|
||||
import AbstractNotificationsContainer, {
|
||||
@@ -27,6 +28,16 @@ type Props = AbstractProps & {
|
||||
* @extends {Component}
|
||||
*/
|
||||
class NotificationsContainer extends AbstractNotificationsContainer<Props> {
|
||||
/**
|
||||
* Creates new NotificationContainer instance.
|
||||
*
|
||||
* @param {Props} props - The props of the react component.
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this._renderNotification = this._renderNotification.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
@@ -40,39 +51,92 @@ class NotificationsContainer extends AbstractNotificationsContainer<Props> {
|
||||
}
|
||||
|
||||
return (
|
||||
<FlagGroup onDismissed = { this._onDismissed }>
|
||||
{ this._renderFlags() }
|
||||
</FlagGroup>
|
||||
<Portal zIndex = { 600 }>
|
||||
<div className = 'notificationsContainer'>
|
||||
{ this._renderTopNotificationsContainer() }
|
||||
{ this._renderBottomNotificationsContainer() }
|
||||
</div>
|
||||
</Portal>
|
||||
);
|
||||
}
|
||||
|
||||
_onDismissed: number => void;
|
||||
|
||||
/**
|
||||
* Renders notifications to display as ReactElements. An empty array will
|
||||
* be returned if notifications are disabled.
|
||||
* Renders the bottom notification container.
|
||||
*
|
||||
* @private
|
||||
* @returns {ReactElement[]}
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
_renderFlags() {
|
||||
_renderBottomNotificationsContainer() {
|
||||
const { _notifications } = this.props;
|
||||
|
||||
return _notifications.map(notification => {
|
||||
const { props, uid } = notification;
|
||||
return (
|
||||
<TransitionGroup className = 'bottomContainer'>
|
||||
{
|
||||
_notifications.filter(n => n.props.position !== 'top').map((notification, index) => {
|
||||
const { props, uid } = notification;
|
||||
|
||||
// The id attribute is necessary as {@code FlagGroup} looks for
|
||||
// either id or key to set a key on notifications, but accessing
|
||||
// props.key will cause React to print an error.
|
||||
return (
|
||||
<Notification
|
||||
{ ...props }
|
||||
id = { uid }
|
||||
key = { uid }
|
||||
uid = { uid } />
|
||||
return this._renderNotification({
|
||||
...props,
|
||||
isDismissAllowed: index > 0 ? false : props.isDismissAllowed
|
||||
}, uid);
|
||||
})
|
||||
}
|
||||
</TransitionGroup>
|
||||
);
|
||||
}
|
||||
|
||||
);
|
||||
});
|
||||
_renderNotification: (string, number) => Function;
|
||||
|
||||
/**
|
||||
* Renders a notification.
|
||||
*
|
||||
* @param {Object} props - The props for the Notification component.
|
||||
* @param {string} uid - A unique ID for the notification.
|
||||
* @returns {Function} - Returns a transition function for the Transition component.
|
||||
*/
|
||||
_renderNotification(props, uid) {
|
||||
return (
|
||||
<Transition
|
||||
key = { uid }
|
||||
timeout = { 400 }>
|
||||
{
|
||||
transitionState => (
|
||||
<div className = { `notification ${transitionState}` }>
|
||||
<Notification
|
||||
{ ...props }
|
||||
id = { uid }
|
||||
key = { uid }
|
||||
onDismissed = { this._onDismissed }
|
||||
uid = { uid } />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</Transition>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the top notifications container.
|
||||
*
|
||||
* @private
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
_renderTopNotificationsContainer() {
|
||||
const { _notifications } = this.props;
|
||||
|
||||
return (
|
||||
<TransitionGroup className = 'topContainer'>
|
||||
{
|
||||
_notifications.filter(n => n.props.position === 'top').map(notification => {
|
||||
const { props, uid } = notification;
|
||||
|
||||
return this._renderNotification(props, uid);
|
||||
})
|
||||
}
|
||||
</TransitionGroup>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import { ActionButton, InputField, PreMeetingScreen, ToggleButton } from '../../
|
||||
import { connect } from '../../base/redux';
|
||||
import { getDisplayName, updateSettings } from '../../base/settings';
|
||||
import { getLocalJitsiVideoTrack } from '../../base/tracks';
|
||||
import { isButtonEnabled } from '../../toolbox/functions.web';
|
||||
import {
|
||||
joinConference as joinConferenceAction,
|
||||
joinConferenceWithoutAudio as joinConferenceWithoutAudioAction,
|
||||
@@ -28,6 +29,8 @@ import {
|
||||
import JoinByPhoneDialog from './dialogs/JoinByPhoneDialog';
|
||||
import DeviceStatus from './preview/DeviceStatus';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
@@ -100,6 +103,11 @@ type Props = {
|
||||
*/
|
||||
showJoinActions: boolean,
|
||||
|
||||
/**
|
||||
* Flag signaling the visibility of the conference URL section.
|
||||
*/
|
||||
showConferenceInfo: boolean,
|
||||
|
||||
/**
|
||||
* If 'JoinByPhoneDialog' is visible or not.
|
||||
*/
|
||||
@@ -139,6 +147,7 @@ class Prejoin extends Component<Props, State> {
|
||||
* @static
|
||||
*/
|
||||
static defaultProps = {
|
||||
showConferenceInfo: true,
|
||||
showJoinActions: true,
|
||||
showSkipPrejoin: true
|
||||
};
|
||||
@@ -257,6 +266,7 @@ class Prejoin extends Component<Props, State> {
|
||||
showAvatar,
|
||||
showCameraPreview,
|
||||
showDialog,
|
||||
showConferenceInfo,
|
||||
showJoinActions,
|
||||
t,
|
||||
videoTrack
|
||||
@@ -270,7 +280,7 @@ class Prejoin extends Component<Props, State> {
|
||||
footer = { this._renderFooter() }
|
||||
name = { name }
|
||||
showAvatar = { showAvatar }
|
||||
showConferenceInfo = { showJoinActions }
|
||||
showConferenceInfo = { showConferenceInfo }
|
||||
skipPrejoinButton = { this._renderSkipPrejoinButton() }
|
||||
title = { t('prejoin.joinMeeting') }
|
||||
videoMuted = { !showCameraPreview }
|
||||
@@ -313,6 +323,7 @@ class Prejoin extends Component<Props, State> {
|
||||
hasOptions = { true }
|
||||
onClick = { joinConference }
|
||||
onOptionsClick = { _onOptionsClick }
|
||||
testId = 'prejoin.joinMeeting'
|
||||
type = 'primary'>
|
||||
{ t('prejoin.joinMeeting') }
|
||||
</ActionButton>
|
||||
@@ -367,11 +378,22 @@ class Prejoin extends Component<Props, State> {
|
||||
* Maps (parts of) the redux state to the React {@code Component} props.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @param {Object} ownProps - The props passed to the component.
|
||||
* @returns {Object}
|
||||
*/
|
||||
function mapStateToProps(state): Object {
|
||||
function mapStateToProps(state, ownProps): Object {
|
||||
const name = getDisplayName(state);
|
||||
const joinButtonDisabled = isDisplayNameRequired(state) && !name;
|
||||
const { showJoinActions } = ownProps;
|
||||
const isInviteButtonEnabled = isButtonEnabled('invite');
|
||||
|
||||
// Hide conference info when interfaceConfig is available and the invite button is disabled.
|
||||
// In all other cases we want to preserve the behaviour and control the the conference info
|
||||
// visibility trough showJoinActions.
|
||||
const showConferenceInfo
|
||||
= typeof isInviteButtonEnabled === 'undefined' || isInviteButtonEnabled === true
|
||||
? showJoinActions
|
||||
: false;
|
||||
|
||||
return {
|
||||
buttonIsToggled: isPrejoinSkipped(state),
|
||||
@@ -382,6 +404,7 @@ function mapStateToProps(state): Object {
|
||||
showDialog: isJoinByPhoneDialogVisible(state),
|
||||
hasJoinByPhoneButton: isJoinByPhoneButtonVisible(state),
|
||||
showCameraPreview: !isVideoMutedByUser(state),
|
||||
showConferenceInfo,
|
||||
videoTrack: getLocalJitsiVideoTrack(state)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -46,3 +46,17 @@ export const SET_PENDING_RECORDING_NOTIFICATION_UID
|
||||
* }
|
||||
*/
|
||||
export const SET_STREAM_KEY = 'SET_STREAM_KEY';
|
||||
|
||||
/**
|
||||
* The type of Redux action which sets the waiting in queue recording notification UID to
|
||||
* use it for when hiding the notification is necessary, or unsets it when
|
||||
* undefined (or no param) is passed.
|
||||
*
|
||||
* {
|
||||
* type: SET_WAITING_IN_RECORDING_NOTIFICATION_UID,
|
||||
* streamType: string,
|
||||
* uid: ?number
|
||||
* }
|
||||
* @public
|
||||
*/
|
||||
export const SET_WAITING_IN_RECORDING_NOTIFICATION_UID = 'SET_WAITING_IN_RECORDING_NOTIFICATION_UID';
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { openDialog } from '../base/dialog';
|
||||
import JitsiMeetJS, { JitsiRecordingConstants } from '../base/lib-jitsi-meet';
|
||||
import {
|
||||
NOTIFICATION_TIMEOUT,
|
||||
NOTIFICATION_TYPE,
|
||||
hideNotification,
|
||||
showErrorNotification,
|
||||
showNotification
|
||||
@@ -12,8 +16,10 @@ import {
|
||||
CLEAR_RECORDING_SESSIONS,
|
||||
RECORDING_SESSION_UPDATED,
|
||||
SET_PENDING_RECORDING_NOTIFICATION_UID,
|
||||
SET_STREAM_KEY
|
||||
SET_STREAM_KEY,
|
||||
SET_WAITING_IN_RECORDING_NOTIFICATION_UID
|
||||
} from './actionTypes';
|
||||
import { QueueInfo, StopLiveStreamDialog, StopRecordingDialog } from './components';
|
||||
|
||||
/**
|
||||
* Clears the data of every recording sessions.
|
||||
@@ -50,6 +56,25 @@ export function hidePendingRecordingNotification(streamType: string) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals that the waiting in queue recording notification should be removed from the screen.
|
||||
*
|
||||
* @param {string} streamType - The type of the stream ({@code 'file'} or
|
||||
* {@code 'stream'}).
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function hideWaitingInQueueRecordingNotification(streamType: string) {
|
||||
return (dispatch: Function, getState: Function) => {
|
||||
const { waitingInQueueNotificationUids } = getState()['features/recording'];
|
||||
const waitingInQueueNotificationUid = waitingInQueueNotificationUids[streamType];
|
||||
|
||||
if (waitingInQueueNotificationUid) {
|
||||
dispatch(hideNotification(waitingInQueueNotificationUid));
|
||||
dispatch(_setWaitingInQueueRecordingNotificationUid(undefined, streamType));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stream key last used by the user for later reuse.
|
||||
*
|
||||
@@ -97,6 +122,22 @@ export function showPendingRecordingNotification(streamType: string) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals that the jibri queue has been left and notification should be shown on the
|
||||
* screen.
|
||||
*
|
||||
* @param {string} streamType - The type of the stream ({@code file} or
|
||||
* {@code stream}).
|
||||
* @returns {showNotification}
|
||||
*/
|
||||
export function showQueueLeftRecordingNotification(streamType: string) {
|
||||
const isLiveStreaming = streamType === JitsiMeetJS.constants.recording.mode.STREAM;
|
||||
|
||||
return showNotification({
|
||||
titleKey: `jibriQueue.${isLiveStreaming ? 'livestreaming' : 'recording'}.left`
|
||||
}, NOTIFICATION_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals that the recording error notification should be shown.
|
||||
*
|
||||
@@ -175,6 +216,15 @@ export function updateRecordingSessionData(session: Object) {
|
||||
= status === JitsiRecordingConstants.status.ON
|
||||
? Date.now() / 1000
|
||||
: undefined;
|
||||
const queueID = session.getQueueID();
|
||||
let queueEstimatedTimeOfStart, queuePosition;
|
||||
|
||||
if (status === JitsiRecordingConstants.status.WAITING_IN_QUEUE) {
|
||||
const { position, estimatedTimeLeft } = session.getQueueMetrics();
|
||||
|
||||
queuePosition = position;
|
||||
queueEstimatedTimeOfStart = (new Date()).getTime() + (estimatedTimeLeft * 1000);
|
||||
}
|
||||
|
||||
return {
|
||||
type: RECORDING_SESSION_UPDATED,
|
||||
@@ -186,7 +236,10 @@ export function updateRecordingSessionData(session: Object) {
|
||||
mode: session.getMode(),
|
||||
status,
|
||||
terminator: session.getTerminator(),
|
||||
timestamp
|
||||
timestamp,
|
||||
queueID,
|
||||
queuePosition,
|
||||
queueEstimatedTimeOfStart
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -212,3 +265,57 @@ function _setPendingRecordingNotificationUid(uid: ?number, streamType: string) {
|
||||
uid
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets UID of the the pending streaming notification to use it when hiding
|
||||
* the notification is necessary, or unsets it when undefined (or no param) is
|
||||
* passed.
|
||||
*
|
||||
* @param {?number} uid - The UID of the notification.
|
||||
* @param {string} streamType - The type of the stream ({@code file} or {@code stream}).
|
||||
* @returns {{
|
||||
* type: SET_PENDING_RECORDING_NOTIFICATION_UID,
|
||||
* streamType: string,
|
||||
* uid: number
|
||||
* }}
|
||||
*/
|
||||
function _setWaitingInQueueRecordingNotificationUid(uid: ?number, streamType: string) {
|
||||
return {
|
||||
type: SET_WAITING_IN_RECORDING_NOTIFICATION_UID,
|
||||
streamType,
|
||||
uid
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals that the recording queue notification should be shown on the screen.
|
||||
*
|
||||
* @param {string} streamType - The type of the stream ({@code file} or
|
||||
* {@code stream}).
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function showWaitingInQueueRecordingNotification(streamType: string) {
|
||||
return (dispatch: Function) => {
|
||||
const isLiveStreaming = streamType === JitsiMeetJS.constants.recording.mode.STREAM;
|
||||
const showNotificationAction = showNotification({
|
||||
appearance: NOTIFICATION_TYPE.INFO,
|
||||
customActionNameKey: 'jibriQueue.exit',
|
||||
customActionHandler: () => {
|
||||
if (isLiveStreaming) {
|
||||
dispatch(openDialog(StopLiveStreamDialog));
|
||||
} else {
|
||||
dispatch(openDialog(StopRecordingDialog));
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
position: 'top',
|
||||
titleKey: `jibriQueue.${isLiveStreaming ? 'livestreaming' : 'recording'}.title`,
|
||||
description: <QueueInfo />
|
||||
});
|
||||
|
||||
dispatch(showNotificationAction);
|
||||
dispatch(_setWaitingInQueueRecordingNotificationUid(
|
||||
showNotificationAction.uid, streamType));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,10 +4,7 @@ import { openDialog } from '../../../base/dialog';
|
||||
import { IconLiveStreaming } from '../../../base/icons';
|
||||
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
|
||||
import { getLocalParticipant } from '../../../base/participants';
|
||||
import {
|
||||
AbstractButton,
|
||||
type AbstractButtonProps
|
||||
} from '../../../base/toolbox';
|
||||
import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components';
|
||||
import { getActiveSession } from '../../functions';
|
||||
|
||||
import {
|
||||
|
||||
@@ -217,6 +217,8 @@ export default class AbstractStartLiveStreamDialog<P: Props>
|
||||
broadcastId: selectedBroadcastID,
|
||||
mode: JitsiRecordingConstants.mode.STREAM,
|
||||
streamId: key
|
||||
}).catch(() => {
|
||||
// prevent unhandled promise rejection.
|
||||
});
|
||||
|
||||
return true;
|
||||
|
||||
@@ -65,7 +65,9 @@ export default class AbstractStopLiveStreamDialog extends Component<Props> {
|
||||
const { _session } = this.props;
|
||||
|
||||
if (_session) {
|
||||
this.props._conference.stopRecording(_session.id);
|
||||
this.props._conference.stopRecording(_session.id, _session.queueID).catch(() => {
|
||||
// prevent unhandled promise rejection.
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -4,6 +4,7 @@ import React from 'react';
|
||||
|
||||
import { Dialog } from '../../../../base/dialog';
|
||||
import { translate } from '../../../../base/i18n';
|
||||
import { JitsiRecordingConstants } from '../../../../base/lib-jitsi-meet';
|
||||
import { connect } from '../../../../base/redux';
|
||||
import AbstractStopLiveStreamDialog, {
|
||||
_mapStateToProps
|
||||
@@ -24,13 +25,17 @@ class StopLiveStreamDialog extends AbstractStopLiveStreamDialog {
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
const { _session = {}, t } = this.props;
|
||||
|
||||
const isInQueue = _session.status === JitsiRecordingConstants.status.WAITING_IN_QUEUE;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
okKey = 'dialog.stopLiveStreaming'
|
||||
okKey = { isInQueue ? 'dialog.leaveJibriQueue' : 'dialog.stopLiveStreaming' }
|
||||
onSubmit = { this._onSubmit }
|
||||
titleKey = 'dialog.liveStreaming'
|
||||
width = 'small'>
|
||||
{ this.props.t('dialog.stopStreamingWarning') }
|
||||
{ t(isInQueue ? 'dialog.leaveJibriQueueWarning' : 'dialog.stopStreamingWarning') }
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,10 +11,7 @@ import {
|
||||
getLocalParticipant,
|
||||
isLocalParticipantModerator
|
||||
} from '../../../base/participants';
|
||||
import {
|
||||
AbstractButton,
|
||||
type AbstractButtonProps
|
||||
} from '../../../base/toolbox';
|
||||
import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components';
|
||||
import { getActiveSession } from '../../functions';
|
||||
|
||||
import { StartRecordingDialog, StopRecordingDialog } from './_';
|
||||
|
||||
@@ -280,6 +280,8 @@ class AbstractStartRecordingDialog extends Component<Props, State> {
|
||||
_conference.startRecording({
|
||||
mode: JitsiRecordingConstants.mode.FILE,
|
||||
appData
|
||||
}).catch(() => {
|
||||
// prevent unhandled promise rejection.
|
||||
});
|
||||
|
||||
if (_autoCaptionOnRecord) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user