mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-09-15 01:28:56 +00:00
Compare commits
3 Commits
android-sd
...
release-77
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae03f798ee | ||
|
|
4ffc2e74da | ||
|
|
138f885b70 |
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@@ -73,10 +73,6 @@ jobs:
|
||||
node-version: 16
|
||||
cache: 'npm'
|
||||
- run: npm install
|
||||
- name: setup-cocoapods
|
||||
uses: maxim-lobanov/setup-cocoapods@v1
|
||||
with:
|
||||
podfile-path: ios/Podfile.lock
|
||||
- name: Install Pods
|
||||
run: |
|
||||
pod --version
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -99,7 +99,10 @@ tsconfig.json
|
||||
#
|
||||
react-native-sdk/*.tgz
|
||||
react-native-sdk/android/src
|
||||
!react-native-sdk/android/src/main/java/org/jitsi/meet/sdk/JitsiMeetOngoingConferenceService.java
|
||||
!react-native-sdk/android/src/main/java/org/jitsi/meet/sdk/JitsiMeetReactNativePackage.java
|
||||
!react-native-sdk/android/src/main/java/org/jitsi/meet/sdk/JMOngoingConferenceModule.java
|
||||
!react-native-sdk/android/src/main/java/org/jitsi/meet/sdk/RNOngoingNotification.java
|
||||
react-native-sdk/images
|
||||
react-native-sdk/ios
|
||||
react-native-sdk/lang
|
||||
|
||||
@@ -26,5 +26,5 @@ android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
android.bundle.enableUncompressedNativeLibs=false
|
||||
|
||||
appVersion=24.0.1
|
||||
sdkVersion=9.0.1
|
||||
appVersion=99.0.0
|
||||
sdkVersion=99.0.0
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
||||
|
||||
<uses-feature
|
||||
@@ -50,6 +51,10 @@
|
||||
android:name="org.jitsi.meet.sdk.JitsiMeetOngoingConferenceService"
|
||||
android:foregroundServiceType="mediaPlayback" />
|
||||
|
||||
<service
|
||||
android:name="org.jitsi.meet.sdk.JitsiMeetMediaProjectionService"
|
||||
android:foregroundServiceType="mediaProjection" />
|
||||
|
||||
<provider
|
||||
android:name="com.reactnativecommunity.webview.RNCWebViewFileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
|
||||
@@ -87,7 +87,6 @@ class AudioDeviceHandlerGeneric implements
|
||||
devices.add(AudioModeModule.DEVICE_EARPIECE);
|
||||
break;
|
||||
case AudioDeviceInfo.TYPE_BUILTIN_SPEAKER:
|
||||
case AudioDeviceInfo.TYPE_HDMI:
|
||||
devices.add(AudioModeModule.DEVICE_SPEAKER);
|
||||
break;
|
||||
case AudioDeviceInfo.TYPE_WIRED_HEADPHONES:
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
|
||||
|
||||
@ReactModule(name = JitsiMeetMediaProjectionModule.NAME)
|
||||
class JitsiMeetMediaProjectionModule
|
||||
extends ReactContextBaseJavaModule {
|
||||
|
||||
public static final String NAME = "JitsiMeetMediaProjectionModule";
|
||||
|
||||
public JitsiMeetMediaProjectionModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void launch() {
|
||||
Context context = getReactApplicationContext();
|
||||
|
||||
JitsiMeetMediaProjectionService.launch(context);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void abort() {
|
||||
Context context = getReactApplicationContext();
|
||||
|
||||
JitsiMeetMediaProjectionService.abort(context);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright @ 2019-present 8x8, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
|
||||
/**
|
||||
* This class implements an Android {@link Service}, a foreground one specifically, and it's
|
||||
* responsible for presenting an ongoing notification when a conference is in progress.
|
||||
* The service will help keep the app running while in the background.
|
||||
*
|
||||
* See: https://developer.android.com/guide/components/services
|
||||
*/
|
||||
public class JitsiMeetMediaProjectionService extends Service {
|
||||
private static final String TAG = JitsiMeetMediaProjectionService.class.getSimpleName();
|
||||
|
||||
public static void launch(Context context) {
|
||||
OngoingNotification.createOngoingConferenceNotificationChannel();
|
||||
|
||||
Intent intent = new Intent(context, JitsiMeetMediaProjectionService.class);
|
||||
|
||||
ComponentName componentName;
|
||||
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
componentName = context.startForegroundService(intent);
|
||||
} else {
|
||||
componentName = context.startService(intent);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
// Avoid crashing due to ForegroundServiceStartNotAllowedException (API level 31).
|
||||
// See: https://developer.android.com/guide/components/foreground-services#background-start-restrictions
|
||||
JitsiMeetLogger.w(TAG + " Ongoing conference service not started", e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (componentName == null) {
|
||||
JitsiMeetLogger.w(TAG + " Ongoing conference service not started");
|
||||
}
|
||||
}
|
||||
|
||||
public static void abort(Context context) {
|
||||
Intent intent = new Intent(context, JitsiMeetMediaProjectionService.class);
|
||||
context.stopService(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
Notification notification = OngoingNotification.buildOngoingConferenceNotification(null);
|
||||
|
||||
if (notification == null) {
|
||||
stopSelf();
|
||||
JitsiMeetLogger.w(TAG + " Couldn't start service, notification is null");
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
startForeground(OngoingNotification.NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION);
|
||||
} else {
|
||||
startForeground(OngoingNotification.NOTIFICATION_ID, notification);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.Service;
|
||||
@@ -34,7 +33,6 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* This class implements an Android {@link Service}, a foreground one specifically, and it's
|
||||
@@ -54,12 +52,8 @@ public class JitsiMeetOngoingConferenceService extends Service
|
||||
|
||||
private boolean isAudioMuted;
|
||||
|
||||
static final int NOTIFICATION_ID = new Random().nextInt(99999) + 10000;
|
||||
|
||||
|
||||
public static void launch(Context context, HashMap<String, Object> extraData) {
|
||||
|
||||
OngoingNotification.createNotificationChannel((Activity) context);
|
||||
OngoingNotification.createOngoingConferenceNotificationChannel();
|
||||
|
||||
Intent intent = new Intent(context, JitsiMeetOngoingConferenceService.class);
|
||||
|
||||
@@ -96,15 +90,15 @@ public class JitsiMeetOngoingConferenceService extends Service
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted, this);
|
||||
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted);
|
||||
if (notification == null) {
|
||||
stopSelf();
|
||||
JitsiMeetLogger.w(TAG + " Couldn't start service, notification is null");
|
||||
} else {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK);
|
||||
startForeground(OngoingNotification.NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK);
|
||||
} else {
|
||||
startForeground(NOTIFICATION_ID, notification);
|
||||
startForeground(OngoingNotification.NOTIFICATION_ID, notification);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,13 +130,13 @@ public class JitsiMeetOngoingConferenceService extends Service
|
||||
if (isAudioMuted != null) {
|
||||
this.isAudioMuted = Boolean.parseBoolean(intent.getStringExtra("muted"));
|
||||
|
||||
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted, this);
|
||||
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted);
|
||||
if (notification == null) {
|
||||
stopSelf();
|
||||
JitsiMeetLogger.w(TAG + " Couldn't start service, notification is null");
|
||||
} else {
|
||||
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.notify(NOTIFICATION_ID, notification);
|
||||
notificationManager.notify(OngoingNotification.NOTIFICATION_ID, notification);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,13 +216,13 @@ public class JitsiMeetOngoingConferenceService extends Service
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
isAudioMuted = Boolean.parseBoolean(intent.getStringExtra("muted"));
|
||||
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted, context);
|
||||
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted);
|
||||
if (notification == null) {
|
||||
stopSelf();
|
||||
JitsiMeetLogger.w(TAG + " Couldn't update service, notification is null");
|
||||
} else {
|
||||
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.notify(NOTIFICATION_ID, notification);
|
||||
notificationManager.notify(OngoingNotification.NOTIFICATION_ID, notification);
|
||||
|
||||
JitsiMeetLogger.i(TAG + " audio muted changed");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class NotificationChannels {
|
||||
static final String ONGOING_CONFERENCE_CHANNEL_ID = "JitsiOngoingConferenceChannel";
|
||||
|
||||
public static List<String> allIds = new ArrayList<String>() {{ add(ONGOING_CONFERENCE_CHANNEL_ID); }};
|
||||
}
|
||||
@@ -16,21 +16,22 @@
|
||||
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
import static org.jitsi.meet.sdk.NotificationChannels.ONGOING_CONFERENCE_CHANNEL_ID;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import android.os.Build;
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Helper class for creating the ongoing notification which is used with
|
||||
@@ -40,15 +41,15 @@ import android.os.Build;
|
||||
class OngoingNotification {
|
||||
private static final String TAG = OngoingNotification.class.getSimpleName();
|
||||
|
||||
static final int NOTIFICATION_ID = new Random().nextInt(99999) + 10000;
|
||||
private static long startingTime = 0;
|
||||
|
||||
static final String ONGOING_CONFERENCE_CHANNEL_ID = "JitsiOngoingConferenceChannel";
|
||||
|
||||
static void createNotificationChannel(Activity context) {
|
||||
static void createOngoingConferenceNotificationChannel() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
return;
|
||||
}
|
||||
|
||||
Context context = ReactInstanceManagerHolder.getCurrentActivity();
|
||||
if (context == null) {
|
||||
JitsiMeetLogger.w(TAG + " Cannot create notification channel: no current context");
|
||||
return;
|
||||
@@ -59,13 +60,12 @@ class OngoingNotification {
|
||||
|
||||
NotificationChannel channel
|
||||
= notificationManager.getNotificationChannel(ONGOING_CONFERENCE_CHANNEL_ID);
|
||||
|
||||
if (channel != null) {
|
||||
// The channel was already created, no need to do it again.
|
||||
return;
|
||||
}
|
||||
|
||||
channel = new NotificationChannel(ONGOING_CONFERENCE_CHANNEL_ID, context.getString(R.string.ongoing_notification_channel_name), NotificationManager.IMPORTANCE_DEFAULT);
|
||||
channel = new NotificationChannel(ONGOING_CONFERENCE_CHANNEL_ID, context.getString(R.string.ongoing_notification_action_unmute), NotificationManager.IMPORTANCE_DEFAULT);
|
||||
channel.enableLights(false);
|
||||
channel.enableVibration(false);
|
||||
channel.setShowBadge(false);
|
||||
@@ -73,8 +73,8 @@ class OngoingNotification {
|
||||
notificationManager.createNotificationChannel(channel);
|
||||
}
|
||||
|
||||
static Notification buildOngoingConferenceNotification(Boolean isMuted, Context context) {
|
||||
|
||||
static Notification buildOngoingConferenceNotification(Boolean isMuted) {
|
||||
Context context = ReactInstanceManagerHolder.getCurrentActivity();
|
||||
if (context == null) {
|
||||
JitsiMeetLogger.w(TAG + " Cannot create notification: no current context");
|
||||
return null;
|
||||
@@ -92,7 +92,7 @@ class OngoingNotification {
|
||||
builder
|
||||
.setCategory(NotificationCompat.CATEGORY_CALL)
|
||||
.setContentTitle(context.getString(R.string.ongoing_notification_title))
|
||||
.setContentText(context.getString(R.string.ongoing_notification_text))
|
||||
.setContentText(isMuted != null ? context.getString(R.string.ongoing_notification_text) : context.getString(R.string.ongoing_notification_action_screenshare))
|
||||
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||
.setContentIntent(pendingIntent)
|
||||
.setOngoing(true)
|
||||
@@ -103,6 +103,10 @@ class OngoingNotification {
|
||||
.setOnlyAlertOnce(true)
|
||||
.setSmallIcon(context.getResources().getIdentifier("ic_notification", "drawable", context.getPackageName()));
|
||||
|
||||
if (isMuted == null) {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
NotificationCompat.Action hangupAction = createAction(context, JitsiMeetOngoingConferenceService.Action.HANGUP, R.string.ongoing_notification_action_hang_up);
|
||||
|
||||
JitsiMeetOngoingConferenceService.Action toggleAudioAction = isMuted
|
||||
|
||||
@@ -37,7 +37,6 @@ import com.oney.WebRTCModule.webrtcutils.H264AndSoftwareVideoEncoderFactory;
|
||||
|
||||
import org.devio.rn.splashscreen.SplashScreenModule;
|
||||
import org.webrtc.EglBase;
|
||||
import org.webrtc.Logging;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
@@ -68,6 +67,7 @@ class ReactInstanceManagerHolder {
|
||||
new DropboxModule(reactContext),
|
||||
new ExternalAPIModule(reactContext),
|
||||
new JavaScriptSandboxModule(reactContext),
|
||||
new JitsiMeetMediaProjectionModule(reactContext),
|
||||
new LocaleDetector(reactContext),
|
||||
new LogBridgeModule(reactContext),
|
||||
new SplashScreenModule(reactContext),
|
||||
@@ -241,8 +241,6 @@ class ReactInstanceManagerHolder {
|
||||
|
||||
options.videoDecoderFactory = new H264AndSoftwareVideoDecoderFactory(eglContext);
|
||||
options.videoEncoderFactory = new H264AndSoftwareVideoEncoderFactory(eglContext);
|
||||
options.enableMediaProjectionService = true;
|
||||
// options.loggingSeverity = Logging.Severity.LS_INFO;
|
||||
|
||||
Log.d(TAG, "initializing RN with Activity");
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<resources>
|
||||
<string name="app_name">Jitsi Meet SDK</string>
|
||||
<string name="dropbox_app_key"></string>
|
||||
<string name="media_projection_notification_title">Media projection</string>
|
||||
<string name="media_projection_notification_text">You are currently sharing your screen.</string>
|
||||
<string name="ongoing_notification_title">Ongoing meeting</string>
|
||||
<string name="ongoing_notification_text">You are currently in a meeting. Tap to return to it.</string>
|
||||
<string name="ongoing_notification_action_hang_up">Hang up</string>
|
||||
<string name="ongoing_notification_action_mute">Mute</string>
|
||||
<string name="ongoing_notification_action_screenshare">You are currently screen-sharing. Tap to return to the meeting.</string>
|
||||
<string name="ongoing_notification_action_unmute">Unmute</string>
|
||||
<string name="ongoing_notification_channel_name">Ongoing Conference Notifications</string>
|
||||
</resources>
|
||||
|
||||
@@ -38,7 +38,6 @@ import {
|
||||
dataChannelClosed,
|
||||
dataChannelOpened,
|
||||
e2eRttChanged,
|
||||
endpointMessageReceived,
|
||||
kickedOut,
|
||||
lockStateChanged,
|
||||
nonParticipantMessageReceived,
|
||||
@@ -91,7 +90,7 @@ import {
|
||||
setVideoMuted,
|
||||
setVideoUnmutePermissions
|
||||
} from './react/features/base/media/actions';
|
||||
import { MEDIA_TYPE, VIDEO_TYPE } from './react/features/base/media/constants';
|
||||
import { MEDIA_TYPE } from './react/features/base/media/constants';
|
||||
import {
|
||||
getStartWithAudioMuted,
|
||||
getStartWithVideoMuted,
|
||||
@@ -163,8 +162,10 @@ import { isScreenAudioShared } from './react/features/screen-share/functions';
|
||||
import { toggleScreenshotCaptureSummary } from './react/features/screenshot-capture/actions';
|
||||
import { AudioMixerEffect } from './react/features/stream-effects/audio-mixer/AudioMixerEffect';
|
||||
import { createRnnoiseProcessor } from './react/features/stream-effects/rnnoise';
|
||||
import { endpointMessageReceived } from './react/features/subtitles/actions.any';
|
||||
import { handleToggleVideoMuted } from './react/features/toolbox/actions.any';
|
||||
import { muteLocal } from './react/features/video-menu/actions.any';
|
||||
import { iAmVisitor } from './react/features/visitors/functions';
|
||||
import UIEvents from './service/UI/UIEvents';
|
||||
|
||||
const logger = Logger.getLogger(__filename);
|
||||
@@ -404,13 +405,7 @@ function disconnect() {
|
||||
* @returns {void}
|
||||
*/
|
||||
function setGUMPendingStateOnFailedTracks(tracks) {
|
||||
const tracksTypes = tracks.map(track => {
|
||||
if (track.getVideoType() === VIDEO_TYPE.DESKTOP) {
|
||||
return MEDIA_TYPE.SCREENSHARE;
|
||||
}
|
||||
|
||||
return track.getType();
|
||||
});
|
||||
const tracksTypes = tracks.map(track => track.getType());
|
||||
const nonPendingTracks = [ MEDIA_TYPE.AUDIO, MEDIA_TYPE.VIDEO ].filter(type => !tracksTypes.includes(type));
|
||||
|
||||
APP.store.dispatch(gumPending(nonPendingTracks, IGUMPendingState.NONE));
|
||||
@@ -684,8 +679,6 @@ export default {
|
||||
startWithVideoMuted: getStartWithVideoMuted(state) || isUserInteractionRequiredForUnmute(state)
|
||||
};
|
||||
|
||||
logger.debug(`Executed conference.init with roomName: ${roomName}`);
|
||||
|
||||
this.roomName = roomName;
|
||||
|
||||
try {
|
||||
@@ -704,6 +697,10 @@ export default {
|
||||
const handleInitialTracks = (options, tracks) => {
|
||||
let localTracks = tracks;
|
||||
|
||||
// No local tracks are added when user joins as a visitor.
|
||||
if (iAmVisitor(state)) {
|
||||
return [];
|
||||
}
|
||||
if (options.startWithAudioMuted || room?.isStartAudioMuted()) {
|
||||
// Always add the track on Safari because of a known issue where audio playout doesn't happen
|
||||
// if the user joins audio and video muted, i.e., if there is no local media capture.
|
||||
@@ -1256,24 +1253,7 @@ export default {
|
||||
room = APP.connection.initJitsiConference(APP.conference.roomName, this._getConferenceOptions());
|
||||
|
||||
// Filter out the tracks that are muted (except on Safari).
|
||||
let tracks = localTracks;
|
||||
|
||||
if (!browser.isWebKitBased()) {
|
||||
const mutedTrackTypes = [];
|
||||
|
||||
tracks = localTracks.filter(track => {
|
||||
if (!track.isMuted()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (track.getVideoType() !== VIDEO_TYPE.DESKTOP) {
|
||||
mutedTrackTypes.push(track.getType());
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
APP.store.dispatch(gumPending(mutedTrackTypes, IGUMPendingState.NONE));
|
||||
}
|
||||
const tracks = browser.isWebKitBased() ? localTracks : localTracks.filter(track => !track.isMuted());
|
||||
|
||||
this._setLocalAudioVideoStreams(tracks);
|
||||
this._room = room; // FIXME do not use this
|
||||
@@ -1844,24 +1824,28 @@ export default {
|
||||
|
||||
room.on(
|
||||
JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
|
||||
(participant, data) => {
|
||||
APP.store.dispatch(endpointMessageReceived(participant, data));
|
||||
if (data?.name === ENDPOINT_TEXT_MESSAGE_NAME) {
|
||||
APP.API.notifyEndpointTextMessageReceived({
|
||||
senderInfo: {
|
||||
jid: participant.getJid(),
|
||||
id: participant.getId()
|
||||
},
|
||||
eventData: data
|
||||
});
|
||||
(...args) => {
|
||||
APP.store.dispatch(endpointMessageReceived(...args));
|
||||
if (args && args.length >= 2) {
|
||||
const [ sender, eventData ] = args;
|
||||
|
||||
if (eventData.name === ENDPOINT_TEXT_MESSAGE_NAME) {
|
||||
APP.API.notifyEndpointTextMessageReceived({
|
||||
senderInfo: {
|
||||
jid: sender._jid,
|
||||
id: sender._id
|
||||
},
|
||||
eventData
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
room.on(
|
||||
JitsiConferenceEvents.NON_PARTICIPANT_MESSAGE_RECEIVED,
|
||||
(id, data) => {
|
||||
APP.store.dispatch(nonParticipantMessageReceived(id, data));
|
||||
APP.API.notifyNonParticipantMessageReceived(id, data);
|
||||
(...args) => {
|
||||
APP.store.dispatch(nonParticipantMessageReceived(...args));
|
||||
APP.API.notifyNonParticipantMessageReceived(...args);
|
||||
});
|
||||
|
||||
room.on(
|
||||
|
||||
28
config.js
28
config.js
@@ -85,7 +85,7 @@ var config = {
|
||||
// disableE2EE: false,
|
||||
|
||||
// Enables supports for AV1 codec.
|
||||
// enableAv1Support: false,
|
||||
// enableAv1: false,
|
||||
|
||||
// Enables XMPP WebSocket (as opposed to BOSH) for the given amount of users.
|
||||
// mobileXmppWsThreshold: 10, // enable XMPP WebSockets on mobile for 10% of the users
|
||||
@@ -103,9 +103,6 @@ var config = {
|
||||
|
||||
// Experiment: Whether to skip interim transcriptions.
|
||||
// skipInterimTranscriptions: false,
|
||||
|
||||
// Dump transcripts to a <transcript> element for debugging.
|
||||
// dumpTranscript: false,
|
||||
},
|
||||
|
||||
// Disables moderator indicators.
|
||||
@@ -329,14 +326,9 @@ var config = {
|
||||
|
||||
// configuration for all things recording related. Existing settings will be migrated here in the future.
|
||||
// recordings: {
|
||||
// // IF true (default) recording audio and video is selected by default in the recording dialog.
|
||||
// // recordAudioAndVideo: true,
|
||||
// // If true, shows a notification at the start of the meeting with a call to action button
|
||||
// // to start recording (for users who can do so).
|
||||
// // suggestRecording: true,
|
||||
// // If true, shows a warning label in the prejoin screen to point out the possibility that
|
||||
// // the call you're joining might be recorded.
|
||||
// // showPrejoinWarning: true,
|
||||
// },
|
||||
|
||||
// recordingService: {
|
||||
@@ -428,6 +420,9 @@ var config = {
|
||||
// // ./src/react/features/transcribing/transcriber-langs.json.
|
||||
// preferredLanguage: 'en-US',
|
||||
|
||||
// // Disable start transcription for all participants.
|
||||
// disableStartForAll: false,
|
||||
|
||||
// // Enables automatic turning on transcribing when recording is started
|
||||
// autoTranscribeOnRecord: false,
|
||||
// },
|
||||
@@ -652,7 +647,7 @@ var config = {
|
||||
// // Whether to disable welcome page. In case it's disabled a random room
|
||||
// // will be joined when no room is specified.
|
||||
// disabled: false,
|
||||
// // If set, landing page will redirect to this URL.
|
||||
// // If set,landing page will redirect to this URL.
|
||||
// customUrl: ''
|
||||
// },
|
||||
|
||||
@@ -725,7 +720,7 @@ var config = {
|
||||
// Configs for prejoin page.
|
||||
// prejoinConfig: {
|
||||
// // When 'true', it shows an intermediate page before joining, where the user can configure their devices.
|
||||
// // This replaces `prejoinPageEnabled`. Defaults to true.
|
||||
// // This replaces `prejoinPageEnabled`.
|
||||
// enabled: true,
|
||||
// // Hides the participant name editing field in the prejoin screen.
|
||||
// // If requireDisplayName is also set as true, a name should still be provided through
|
||||
@@ -1213,12 +1208,6 @@ var config = {
|
||||
// desktop: {
|
||||
// appName: 'Jitsi Meet',
|
||||
// appScheme: 'jitsi-meet,
|
||||
// download: {
|
||||
// linux:
|
||||
// 'https://github.com/jitsi/jitsi-meet-electron/releases/latest/download/jitsi-meet-x86_64.AppImage',
|
||||
// macos: 'https://github.com/jitsi/jitsi-meet-electron/releases/latest/download/jitsi-meet.dmg',
|
||||
// windows: 'https://github.com/jitsi/jitsi-meet-electron/releases/latest/download/jitsi-meet.exe'
|
||||
// },
|
||||
// enabled: false
|
||||
// },
|
||||
// // If true, any checks to handoff to another application will be prevented
|
||||
@@ -1302,8 +1291,6 @@ var config = {
|
||||
// remoteVideoMenu: {
|
||||
// // Whether the remote video context menu to be rendered or not.
|
||||
// disabled: true,
|
||||
// // If set to true the 'Switch to visitor' button will be disabled.
|
||||
// disableDemote: true,
|
||||
// // If set to true the 'Kick out' button will be disabled.
|
||||
// disableKick: true,
|
||||
// // If set to true the 'Grant moderator' button will be disabled.
|
||||
@@ -1392,8 +1379,6 @@ var config = {
|
||||
|
||||
// Options related to the participants pane.
|
||||
// participantsPane: {
|
||||
// // Enables feature
|
||||
// enabled: true,
|
||||
// // Hides the moderator settings tab.
|
||||
// hideModeratorSettingsTab: false,
|
||||
// // Hides the more actions button.
|
||||
@@ -1445,6 +1430,7 @@ var config = {
|
||||
// 'conference-timer',
|
||||
// 'participants-count',
|
||||
// 'e2ee',
|
||||
// 'transcribing',
|
||||
// 'video-quality',
|
||||
// 'insecure-room',
|
||||
// 'highlight-moment',
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.reactions-animations-overflow-container {
|
||||
.reactions-animations-container {
|
||||
position: absolute;
|
||||
width: 20%;
|
||||
bottom: 0;
|
||||
@@ -117,13 +117,6 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.reactions-animations-container {
|
||||
left: 50%;
|
||||
bottom: 0px;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
$reactionCount: 20;
|
||||
|
||||
@function random($min, $max) {
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
position: absolute;
|
||||
top: 0;
|
||||
height: 48px;
|
||||
max-width: calc(100% - 24px);
|
||||
}
|
||||
|
||||
@keyframes hideSubject {
|
||||
|
||||
@@ -36,7 +36,6 @@ $flagsImagePath: "../images/";
|
||||
@import 'modals/invite/info';
|
||||
@import 'modals/screen-share/share-audio';
|
||||
@import 'modals/screen-share/share-screen-warning';
|
||||
@import 'modals/whiteboard';
|
||||
@import 'videolayout_default';
|
||||
@import 'subject';
|
||||
@import 'popup_menu';
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
.whiteboard {
|
||||
|
||||
.excalidraw-wrapper {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,7 @@ VirtualHost "jitmeet.example.com"
|
||||
}
|
||||
av_moderation_component = "avmoderation.jitmeet.example.com"
|
||||
speakerstats_component = "speakerstats.jitmeet.example.com"
|
||||
conference_duration_component = "conferenceduration.jitmeet.example.com"
|
||||
end_conference_component = "endconference.jitmeet.example.com"
|
||||
-- we need bosh
|
||||
modules_enabled = {
|
||||
@@ -129,6 +130,9 @@ Component "focus.jitmeet.example.com" "client_proxy"
|
||||
Component "speakerstats.jitmeet.example.com" "speakerstats_component"
|
||||
muc_component = "conference.jitmeet.example.com"
|
||||
|
||||
Component "conferenceduration.jitmeet.example.com" "conference_duration_component"
|
||||
muc_component = "conference.jitmeet.example.com"
|
||||
|
||||
Component "endconference.jitmeet.example.com" "end_conference"
|
||||
muc_component = "conference.jitmeet.example.com"
|
||||
|
||||
|
||||
1
globals.d.ts
vendored
1
globals.d.ts
vendored
@@ -21,7 +21,6 @@ declare global {
|
||||
JitsiMeetElectron?: any;
|
||||
PressureObserver?: any;
|
||||
PressureRecord?: any;
|
||||
ReactNativeWebView?: any;
|
||||
// selenium tests handler
|
||||
_sharedVideoPlayer: any;
|
||||
alwaysOnTop: { api: any };
|
||||
|
||||
3
globals.native.d.ts
vendored
3
globals.native.d.ts
vendored
@@ -19,9 +19,6 @@ interface IWindow {
|
||||
location: ILocation;
|
||||
PressureObserver?: any;
|
||||
PressureRecord?: any;
|
||||
ReactNativeWebView?: any;
|
||||
TextDecoder?: any;
|
||||
TextEncoder?: any;
|
||||
self: any;
|
||||
top: any;
|
||||
|
||||
|
||||
@@ -453,7 +453,7 @@ PODS:
|
||||
- react-native-video/Video (6.0.0-alpha.11):
|
||||
- PromisesSwift
|
||||
- React-Core
|
||||
- react-native-webrtc (118.0.3):
|
||||
- react-native-webrtc (118.0.0):
|
||||
- JitsiWebRTC (~> 118.0.0)
|
||||
- React-Core
|
||||
- react-native-webview (13.5.1):
|
||||
@@ -827,7 +827,7 @@ SPEC CHECKSUMS:
|
||||
Amplitude: 834c7332dfb9640a751e21c13efb22a07c0c12d4
|
||||
amplitude-react-native: 0ed8cab759aafaa94961b82122bf56297da607ad
|
||||
AppAuth: 3bb1d1cd9340bd09f5ed189fb00b1cc28e1e8570
|
||||
boost: 7dcd2de282d72e344012f7d6564d024930a6a440
|
||||
boost: a7c83b31436843459a1961bfd74b96033dc77234
|
||||
CocoaLumberjack: b7e05132ff94f6ae4dfa9d5bce9141893a21d9da
|
||||
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
|
||||
FBLazyVector: dc178b8748748c036ef9493a5d59d6d1f91a36ce
|
||||
@@ -842,7 +842,7 @@ SPEC CHECKSUMS:
|
||||
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
|
||||
Giphy: 6b5f6986c8df4f71e01a8ef86595f426b3439fb5
|
||||
giphy-react-native-sdk: fcda9639f8ca2cc47e0517b6ef11c19359db5f5a
|
||||
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
|
||||
glog: 3d02b25ca00c2d456734d0bcff864cbc62f6ae1a
|
||||
GoogleAppMeasurement: 4c19f031220c72464d460c9daa1fb5d1acce958e
|
||||
GoogleDataTransport: 57c22343ab29bc686febbf7cbb13bad167c2d8fe
|
||||
GoogleSignIn: b232380cf495a429b8095d3178a8d5855b42e842
|
||||
@@ -855,7 +855,7 @@ SPEC CHECKSUMS:
|
||||
ObjectiveDropboxOfficial: fe206ce8c0bc49976c249d472db7fdbc53ebbd53
|
||||
PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4
|
||||
PromisesSwift: 28dca69a9c40779916ac2d6985a0192a5cb4a265
|
||||
RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1
|
||||
RCT-Folly: 0080d0a6ebf2577475bda044aa59e2ca1f909cda
|
||||
RCTRequired: f30c3213569b1dc43659ecc549a6536e1e11139e
|
||||
RCTTypeSafety: e1ed3137728804fa98bce30b70e3da0b8e23054e
|
||||
React: 54070abee263d5773486987f1cf3a3616710ed52
|
||||
@@ -881,7 +881,7 @@ SPEC CHECKSUMS:
|
||||
react-native-slider: 1cdd6ba29675df21f30544253bf7351d3c2d68c4
|
||||
react-native-splash-screen: 4312f786b13a81b5169ef346d76d33bc0c6dc457
|
||||
react-native-video: 472b7c366eaaaa0207e546d9a50410df89790bcf
|
||||
react-native-webrtc: 6fc32f3d556aa60aa2334eeaf6cadcdab2432809
|
||||
react-native-webrtc: c8d9ad3c152105b2720ca2851d04b49659551992
|
||||
react-native-webview: 8baa0f5c6d336d6ba488e942bcadea5bf51f050a
|
||||
React-NativeModulesApple: 4225ac31a26696c02c54b471052b3e85e74a9a0c
|
||||
React-perflogger: cb433f318c6667060fc1f62e26eb58d6eb30a627
|
||||
@@ -916,4 +916,4 @@ SPEC CHECKSUMS:
|
||||
|
||||
PODFILE CHECKSUM: ec00682c7062a323dff24a3c3643ca0bbb420d01
|
||||
|
||||
COCOAPODS: 1.14.3
|
||||
COCOAPODS: 1.12.1
|
||||
|
||||
@@ -1031,7 +1031,8 @@
|
||||
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
" ",
|
||||
"-Wl",
|
||||
"-ld_classic",
|
||||
);
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
@@ -1094,7 +1095,8 @@
|
||||
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
" ",
|
||||
"-Wl",
|
||||
"-ld_classic",
|
||||
);
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>24.0.1</string>
|
||||
<string>99.0.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>NSExtension</key>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>24.0.1</string>
|
||||
<string>99.0.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>24.0.1</string>
|
||||
<string>99.0.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>24.0.1</string>
|
||||
<string>99.0.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>CLKComplicationPrincipalClass</key>
|
||||
|
||||
@@ -629,7 +629,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "WITH_ENVIRONMENT=\"../../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n";
|
||||
shellScript = "export NODE_BINARY=node\nexport NODE_ARGS=\"--max_old_space_size=4096\"\n../../node_modules/react-native/scripts/react-native-xcode.sh\n";
|
||||
};
|
||||
DE9A016B289A9A9A00E41CBB /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
@@ -781,7 +781,8 @@
|
||||
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
" ",
|
||||
"-Wl",
|
||||
"-ld_classic",
|
||||
);
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
@@ -847,7 +848,8 @@
|
||||
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
" ",
|
||||
"-Wl",
|
||||
"-ld_classic",
|
||||
);
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>9.0.1</string>
|
||||
<string>99.0.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>9.0.1</string>
|
||||
<string>99.0.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
@@ -209,7 +209,7 @@
|
||||
"appNotInstalled": "Sie benötigen die „{{app}}“-App, um der Konferenz auf dem Smartphone beizutreten.",
|
||||
"description": "Nichts passiert? Wir haben versucht, die Konferenz in {{app}} zu öffnen. Versuchen Sie es erneut oder treten Sie der Konferenz in {{app}} im Web bei.",
|
||||
"descriptionNew": "Nichts passiert? Wir haben versucht, die Konferenz in {{app}} zu öffnen. <br /><br /> Versuchen Sie es erneut oder treten Sie der Konferenz im Web bei.",
|
||||
"descriptionWithoutWeb": "Ist nichts passiert? Wir haben versucht, Ihre Konferenz in der „{{app}}“-Desktop-App zu starten.",
|
||||
"descriptionWithoutWeb": "Ist nichts passiert? Wir haben versucht, Ihre Besprechung in der „{{app}}“-Desktop-App zu starten.",
|
||||
"downloadApp": "App herunterladen",
|
||||
"downloadMobileApp": "Aus dem App Store herunterladen",
|
||||
"ifDoNotHaveApp": "Wenn Sie die App noch nicht haben:",
|
||||
@@ -219,13 +219,11 @@
|
||||
"joinInBrowser": "Im Browser",
|
||||
"launchMeetingLabel": "Wie möchten Sie an der Konferenz teilnehmen?",
|
||||
"launchWebButton": "Im Web öffnen",
|
||||
"noDesktopApp": "Sie haben die App noch nicht installiert?",
|
||||
"noMobileApp": "Sie haben die App noch nicht installiert?",
|
||||
"or": "oder",
|
||||
"termsAndConditions": "Indem Sie fortfahren, stimmen Sie unseren <a href='{{termsAndConditionsLink}}' rel='noopener noreferrer' target='_blank'>Nutzungsbedingungen</a> zu.",
|
||||
"title": "Die Konferenz wird in {{app}} geöffnet …",
|
||||
"titleNew": "Konferenz starten ...",
|
||||
"tryAgainButton": "Erneut versuchen",
|
||||
"tryAgainButton": "Erneut mit der nativen Applikation versuchen",
|
||||
"unsupportedBrowser": "Sie verwenden einen Browser, der noch nicht unterstützt wird."
|
||||
},
|
||||
"defaultLink": "Bsp.: {{url}}",
|
||||
@@ -536,7 +534,7 @@
|
||||
"conferenceURL": "Link:",
|
||||
"copyNumber": "Nummer kopieren",
|
||||
"country": "Land",
|
||||
"dialANumber": "Um an der Konferenz teilzunehmen, müssen Sie eine dieser Nummern wählen und dann die PIN eingeben.",
|
||||
"dialANumber": "Um am Meeting teilzunehmen, müssen Sie eine dieser Nummern wählen und dann die PIN eingeben.",
|
||||
"dialInConferenceID": "PIN:",
|
||||
"dialInNotSupported": "Entschuldigung, leider wird das Einwählen derzeit nicht unterstützt.",
|
||||
"dialInNumber": "Einwählen:",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -219,9 +219,7 @@
|
||||
"joinInBrowser": "Pievienojieties pārlūkā",
|
||||
"launchMeetingLabel": "Kā vēlaties pievienoties šai sapulcei?",
|
||||
"launchWebButton": "Palaist tīmekļa pārlūkā",
|
||||
"noDesktopApp": "Vai jums nav lietotnes?",
|
||||
"noMobileApp": "Vai jums nav lietotnes?",
|
||||
"or": "vai",
|
||||
"termsAndConditions": "Turpinot jūs piekrītat mūsu <a href='{{termsAndConditionsLink}}' rel='noopener noreferrer' target='_blank'>pakalpojumu sniegšanas noteikumiem.</a>",
|
||||
"title": "Notiek jūsu sapulces palaišana lietotnē {{app}}...",
|
||||
"titleNew": "Notiek jūsu sapulces palaišana ...",
|
||||
@@ -839,7 +837,6 @@
|
||||
"headings": {
|
||||
"lobby": "Vestibils ({{count}})",
|
||||
"participantsList": "Sapulces dalībnieki ({{count}})",
|
||||
"visitorRequests": " (pieprasījumi {{count}})",
|
||||
"visitors": "Apmeklētāji ({{count}})",
|
||||
"waitingLobby": "Gaida vestibilā ({{count}})"
|
||||
},
|
||||
@@ -1000,6 +997,7 @@
|
||||
"limitNotificationDescriptionNative": "Lielā pieprasījuma dēļ jūsu ieraksts tiks ierobežots līdz {{limit}} min. Lai iegūtu neierobežotu ierakstu skaitu, izmēģiniet <3>{{app}}</3>.",
|
||||
"limitNotificationDescriptionWeb": "Lielā pieprasījuma dēļ jūsu ieraksts tiks ierobežots līdz {{limit}} min. Lai iegūtu neierobežotu ierakstu skaitu, izmēģiniet <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"linkGenerated": "Mēs esam izveidojuši saiti uz jūsu ierakstu.",
|
||||
"live": "ĒTERĀ",
|
||||
"localRecordingNoNotificationWarning": "Ieraksts netiks izziņots citiem dalībniekiem. Jums būs jāpaziņo viņiem, ka sapulce tiek ierakstīta.",
|
||||
"localRecordingNoVideo": "Video netiek ierakstīts",
|
||||
"localRecordingStartWarning": "Pirms iziešanas no sapulces, lūdzu, apturiet ierakstīšanu, lai to saglabātu.",
|
||||
@@ -1016,16 +1014,14 @@
|
||||
"onBy": "{{name}} ieslēdza ierakstu",
|
||||
"onlyRecordSelf": "Ierakstīt tikai manas audio un video straumes",
|
||||
"pending": "Gatavojas ierakstīt sapulci...",
|
||||
"recordAudioAndVideo": "Ierakstīt audio un video",
|
||||
"recordTranscription": "Ierakstīt transkripciju",
|
||||
"rec": "Notiek ieraksts",
|
||||
"saveLocalRecording": "Ieraksta faila saglabāšana lokāli (beta)",
|
||||
"serviceDescription": "Jūsu ierakstu saglabās attiecīgais pakalpojums",
|
||||
"serviceDescriptionCloud": "Ierakstīšana mākonī",
|
||||
"serviceDescriptionCloud": "Mākoņa ierakstīšana",
|
||||
"serviceDescriptionCloudInfo": "Ierakstītās sapulces tiek automātiski dzēstas 24 stundas pēc to ierakstīšanas laika.",
|
||||
"serviceName": "Ieraksta pakalpojums",
|
||||
"sessionAlreadyActive": "Šī sesija jau tiek ierakstīta vai straumēta tiešraidē.",
|
||||
"showAdvancedOptions": "Papildus iespējas",
|
||||
"signIn": "Pierakstīties",
|
||||
"signIn": "Ierakstīties",
|
||||
"signOut": "Izrakstīties",
|
||||
"surfaceError": "Lūdzu, izvēlieties pašreizējo cilni.",
|
||||
"title": "Ieraksts",
|
||||
@@ -1355,9 +1351,12 @@
|
||||
},
|
||||
"transcribing": {
|
||||
"ccButtonTooltip": "Iesl./izsl. subtitrus",
|
||||
"expandedLabel": "Transkripcija ir ieslēgta",
|
||||
"error": "Transkripcijas kļūme. Lūdzu, mēģiniet vēlāk.",
|
||||
"expandedLabel": "Transkripcija ieslēgta",
|
||||
"failedToStart": "Neizdevās sākt transkripciju",
|
||||
"labelToolTip": "Notiek sapulces transkripcija",
|
||||
"labelToolTip": "Notiek sapulces transkripcija.",
|
||||
"off": "Transkripcija izslēgta",
|
||||
"pending": "Gatavojas veikt sapulces transkripciju...",
|
||||
"sourceLanguageDesc": "Pašlaik sapulces valoda ir iestatīta uz <b>{{sourceLanguage}}</b>. <br/> Varat to mainīt no ",
|
||||
"sourceLanguageHere": "šeit",
|
||||
"start": "Iesl. subtitru rādīšanu",
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"addPeople": {
|
||||
"accessibilityLabel": {
|
||||
"meetingLink": "Lidhje takimi: {{url}}"
|
||||
},
|
||||
"add": "Ftoni",
|
||||
"addContacts": "Ftoni kontaktet tuaja",
|
||||
"contacts": "kontakte",
|
||||
@@ -42,18 +39,6 @@
|
||||
"audioOnly": {
|
||||
"audioOnly": "Gjerësi e ulët bande"
|
||||
},
|
||||
"bandwidthSettings": {
|
||||
"assumedBandwidthBps": "p.sh. 10000000 për 10 Mbps",
|
||||
"assumedBandwidthBpsWarning": "Vlera më të mëdha mund të shkaktojnë probleme rrjeti.",
|
||||
"customValue": "vlerë vetjake",
|
||||
"customValueEffect": "për të ujdisur vlerën e tanishme bps",
|
||||
"leaveEmpty": "lëreni të zbrazët",
|
||||
"leaveEmptyEffect": "për të lejuar kryerje vlerësimesh",
|
||||
"possibleValues": "Vlera të mundshme",
|
||||
"setAssumedBandwidthBps": "Gjerësi bande e supozuar (bps)",
|
||||
"title": "Rregullime gjerësi bande",
|
||||
"zeroEffect": "për të çaktivizuar videon"
|
||||
},
|
||||
"breakoutRooms": {
|
||||
"actions": {
|
||||
"add": "Shtoni aneks konsultimesh",
|
||||
@@ -63,22 +48,15 @@
|
||||
"leaveBreakoutRoom": "Dilni nga aneks konsultimesh",
|
||||
"more": "Më tepër",
|
||||
"remove": "Hiqe",
|
||||
"rename": "Riemërtojeni",
|
||||
"renameBreakoutRoom": "Riemërtoni aneks konsultimesh",
|
||||
"sendToBreakoutRoom": "Dërgoje pjesëmarrësin te:"
|
||||
},
|
||||
"breakoutList": "Listë aneksesh",
|
||||
"buttonLabel": "Dhoma aneks konsultimesh",
|
||||
"defaultName": "Dhomë aneks konsultimesh #{{index}}",
|
||||
"hideParticipantList": "Fshihe listën e pjesëmarrësve",
|
||||
"mainRoom": "Dhoma kryesore",
|
||||
"notifications": {
|
||||
"joined": "Po hyhet te dhomë aneks konsultimesh \"{{name}}\"",
|
||||
"joinedMainRoom": "Po hyhet te dhoma kryesore",
|
||||
"joinedTitle": "Dhoma Aneks Konsultimesh"
|
||||
},
|
||||
"showParticipantList": "Shfaq listë pjesëmarrësish",
|
||||
"title": "Dhoma Aneks Konsultimesh"
|
||||
}
|
||||
},
|
||||
"calendarSync": {
|
||||
"addMeetingURL": "Shtoni një lidhje takimi",
|
||||
@@ -90,9 +68,9 @@
|
||||
},
|
||||
"join": "Merrni pjesë",
|
||||
"joinTooltip": "Merrni pjesë në takim",
|
||||
"nextMeeting": "Takimi pasues",
|
||||
"nextMeeting": "takimi pasues",
|
||||
"noEvents": "S’ka veprimtari të ardhshme të vëna në plan.",
|
||||
"ongoingMeeting": "Takim në zhvillim e sipër",
|
||||
"ongoingMeeting": "takim në zhvillim e sipër",
|
||||
"permissionButton": "Hapni rregullimet",
|
||||
"permissionMessage": "Që të shihni në aplikacion takimet tuaja, janë të domosdoshme lejet mbi Kalendarin.",
|
||||
"refresh": "Rifresko kalendarin",
|
||||
@@ -178,7 +156,6 @@
|
||||
"localport_plural": "Porta vendore:",
|
||||
"maxEnabledResolution": "maksimum dërgimi",
|
||||
"more": "Shfaq më tepër",
|
||||
"no": "jo",
|
||||
"packetloss": "Humbje paketesh:",
|
||||
"participant_id": "ID pjesëmarrësi:",
|
||||
"quality": {
|
||||
@@ -197,8 +174,7 @@
|
||||
"status": "Lidhje:",
|
||||
"transport": "Transport:",
|
||||
"transport_plural": "Transporte:",
|
||||
"video_ssrc": "Video SSRC:",
|
||||
"yes": "po"
|
||||
"video_ssrc": "SSRC Videoje:"
|
||||
},
|
||||
"dateUtils": {
|
||||
"earlier": "Më herët",
|
||||
@@ -219,9 +195,7 @@
|
||||
"joinInBrowser": "Hyni që nga shfletues",
|
||||
"launchMeetingLabel": "Si doni të hyhet në këtë takim?",
|
||||
"launchWebButton": "Nise në web",
|
||||
"noDesktopApp": "S’e keni aplikacionin?",
|
||||
"noMobileApp": "S’e keni aplikacionin?",
|
||||
"or": "OR",
|
||||
"termsAndConditions": "Duke vazhduar, pajtoheni me <a href='{{termsAndConditionsLink}}' rel='noopener noreferrer' target='_blank'>terms & conditions.</a> tona",
|
||||
"title": "Po niset takimi juaj në {{app}}…",
|
||||
"titleNew": "Po niset takimi juaj…",
|
||||
@@ -246,7 +220,7 @@
|
||||
"noPermission": "S’u akordua leje",
|
||||
"previewUnavailable": "S’bëhet dot paraparje",
|
||||
"selectADevice": "Përzgjidhni një pajisje",
|
||||
"testAudio": "Testojeni"
|
||||
"testAudio": "Luaj një tingull, për provë"
|
||||
},
|
||||
"dialIn": {
|
||||
"screenTitle": "Përmbledhje rënieje numrash"
|
||||
@@ -257,28 +231,21 @@
|
||||
"dialog": {
|
||||
"Back": "Mbrapsht",
|
||||
"Cancel": "Anuloje",
|
||||
"IamHost": "Hyni",
|
||||
"IamHost": "Jam organizatori",
|
||||
"Ok": "OK",
|
||||
"Remove": "Hiqe",
|
||||
"Share": "Ndaje",
|
||||
"Submit": "Parashtroje",
|
||||
"WaitForHostMsg": "Konferenca s’ka nisur, ngaqë s’ka mbërritur ende ndonjë moderator. Nëse dëshironi të bëheni një moderator, ju lutemi, bëni hyrjen. Përndryshe, ju lutemi, pritni.",
|
||||
"WaitingForHostButton": "Prit për moderator",
|
||||
"WaitingForHostTitle": "Po pritet për një moderator…",
|
||||
"WaitForHostMsg": "Konferenca s’ka nisur ende. Nëse jeni organizatori, ju lutemi, bëni mirëfilltësimin. Përndryshe, ju lutemi, pritni që të mbërrijë organizatori.",
|
||||
"WaitingForHostTitle": "Po pritet për organizatorin…",
|
||||
"Yes": "Po",
|
||||
"accessibilityLabel": {
|
||||
"Cancel": "Anuloje (dilni nga dialogu)",
|
||||
"Ok": "OK (ruajeni dhe dilni nga dialogu)",
|
||||
"close": "Mbylle dialogun",
|
||||
"liveStreaming": "Transmetim i Drejtpërdrejtë",
|
||||
"sharingTabs": "Mundësi ndarjeje me të tjerë"
|
||||
"liveStreaming": "Transmetim i Drejtpërdrejtë"
|
||||
},
|
||||
"add": "Shtoni",
|
||||
"addMeetingNote": "Shtoni një shënim rreth këtij takimi",
|
||||
"addOptionalNote": "Shtoni një shënim (në daçi):",
|
||||
"allow": "Lejoje",
|
||||
"allowToggleCameraDialog": "A e lejoni {{initiatorName}} të ndryshojë anën nga sheh kamera juaj?",
|
||||
"allowToggleCameraTitle": "Të lejohet ndryshimi i kamerës?",
|
||||
"alreadySharedVideoMsg": "Një tjetër pjesëmarrës po ndan me të tjerët një video. Kjo konferencë lejon vetëm një ndarje videoje në herë.",
|
||||
"alreadySharedVideoTitle": "Lejohet vetëm një ndarje videoje me të tjerët në herë",
|
||||
"applicationWindow": "Dritare aplikacioni",
|
||||
@@ -339,8 +306,7 @@
|
||||
"lockRoom": "Shtoni takim $t(lockRoomPasswordUppercase)",
|
||||
"lockTitle": "Kyçja dështoi",
|
||||
"login": "Hyrje",
|
||||
"loginQuestion": "Jeni i sigurt se doni të hyhet dhe të braktiset konferenca?",
|
||||
"logoutQuestion": "Jeni i sigurt se doni të dilet dhe të braktiset konferenca?",
|
||||
"logoutQuestion": "Jeni i sigurt se doni të dilet dhe të ndalet konferenca?",
|
||||
"logoutTitle": "Dalje",
|
||||
"maxUsersLimitReached": "U mbërrit në kufi numri maksimum pjesëmarrësish. Konferenca është plot. Ju lutemi, lidhuni me të zotin e takimit, ose provoni më vonë!",
|
||||
"maxUsersLimitReachedTitle": "U mbërrit në kufi numri maksimum pjesëmarrësish",
|
||||
@@ -368,7 +334,7 @@
|
||||
"muteEveryonesVideoTitle": "Të ndalet videoja e gjithkujt?",
|
||||
"muteParticipantBody": "S’do jeni në gjendje të hiqni heshtimin për ta, por ata munden kurdo ta heqin për veten.",
|
||||
"muteParticipantButton": "Heshtoje",
|
||||
"muteParticipantsVideoBody": "S’do të jeni në gjendje të riaktivizoni kamerën e tyre, por ata munden kurdo ta riaktivizojnë për veten.",
|
||||
"muteParticipantsVideoBody": "S’do të jeni në gjendje të riaktivizoni kamerën e tyre, por ata munden kurdo ta riaktvizojnë për veten.",
|
||||
"muteParticipantsVideoBodyModerationOn": "S’do të jeni në gjendje të riaktivizoni kamerën e tyre dhe as ata s’do të munden.",
|
||||
"muteParticipantsVideoButton": "Ndale videon",
|
||||
"muteParticipantsVideoDialog": "Jeni i sigurt se doni të çaktivizoni kamerën e këtij pjesëmarrësi? S’do të jeni në gjendje të riaktivizoni kamerën, por ai mund ta riaktivizojë kurdo.",
|
||||
@@ -383,6 +349,8 @@
|
||||
"permissionCameraRequiredError": "Leja mbi kamerën është e domosdoshme për të marrë pjesë në konferenca me video. Ju lutemi, akordojeni që nga Rregullimet",
|
||||
"permissionErrorTitle": "Leje e domosdoshme",
|
||||
"permissionMicRequiredError": "Leja mbi mikrofonin është e domosdoshme për të marrë pjesë në konferenca me audio. Ju lutemi, akordojeni që nga Rregullimet",
|
||||
"popupError": "Shfletuesi juaj i bllokon dritaret flluskë prej këtij sajti. Ju lutemi, aktivizoni flluskat te rregullimet e sigurisë të shfletuesit tuaj dhe riprovoni.",
|
||||
"popupErrorTitle": "Flluska u bllokua",
|
||||
"readMore": "më tepër",
|
||||
"recentlyUsedObjects": "Së fundi përdorët objekte",
|
||||
"recording": "Regjistrim",
|
||||
@@ -399,8 +367,6 @@
|
||||
"removePassword": "Hiqe $t(lockRoomPassword)",
|
||||
"removeSharedVideoMsg": "Jeni i sigurt se doni të hiqni videon që keni ndarë me të tjerë?",
|
||||
"removeSharedVideoTitle": "Hiqe videon e ndarë me të tjerë",
|
||||
"renameBreakoutRoomLabel": "Emër dhome",
|
||||
"renameBreakoutRoomTitle": "Riemërtoni aneks konsultimesh",
|
||||
"reservationError": "Gabim sistemi rezervimi",
|
||||
"reservationErrorMsg": "Kod gabimi: {{code}}, mesazh: {{msg}}",
|
||||
"retry": "Riprovoni",
|
||||
@@ -420,10 +386,8 @@
|
||||
"sendPrivateMessageTitle": "Të dërgohet privatisht?",
|
||||
"serviceUnavailable": "Shërbim jashtë funksionimi",
|
||||
"sessTerminated": "Thirrja përfundoi",
|
||||
"sessTerminatedReason": "Takimi u përfundua",
|
||||
"sessionRestarted": "Thirrja rinisi për shkak të një problemi lidhjeje.",
|
||||
"shareAudio": "Vazhdoni",
|
||||
"shareAudioAltText": "që të ndani me të tjerë lëndën e dëshiruar, kaloni te \"Skedë Shfletuesi\", përzgjidhni lëndën, aktivizoni shenjën për \"ndani audio me të tjerë\" dhe mandej klikoni butonin \"ndaje me të tjerë\"",
|
||||
"shareAudio": "Vazhdo",
|
||||
"shareAudioTitle": "Si të ndahet audio me të tjerë",
|
||||
"shareAudioWarningD1": "lypset të ndalni tregim ekrani, para se të ndani audion tuaj me të tjerë.",
|
||||
"shareAudioWarningD2": "lypset të rinisni tregimin e ekranit tuaj dhe t’i vini shenjë mundësisë “ndani audio me të tjerë”.",
|
||||
@@ -453,25 +417,7 @@
|
||||
"thankYou": "Faleminderit që përdorni {{appName}}!",
|
||||
"token": "token",
|
||||
"tokenAuthFailed": "Na ndjeni, s’keni leje të merrni pjesë në këtë thirrje.",
|
||||
"tokenAuthFailedReason": {
|
||||
"audInvalid": "Vlerë `aud` e pavlefshme. Duhet të jetë `jitsi`.",
|
||||
"contextNotFound": "Prej ngarkesës mungon objekti `context`.",
|
||||
"expInvalid": "Vlerë `exp` e pavlefshme.",
|
||||
"featureInvalid": "Veçori e pavlefshme: {{feature}}, gjasat janë të mos jetë sendërtuar ende.",
|
||||
"featureValueInvalid": "Vlerë e pavlefshme për veçorinë: {{feature}}.",
|
||||
"featuresNotFound": "Prej ngarkesës mungon objekti `features`.",
|
||||
"headerNotFound": "Mungon krye.",
|
||||
"issInvalid": "Vlerë `iss` e pavlefshme. Duhet të jetë `chat`.",
|
||||
"kidMismatch": "ID kyçi (kid) nuk përputhet me sub.",
|
||||
"kidNotFound": "Mungon ID Kyçi (kid).",
|
||||
"nbfFuture": "Vlera `nbf` gjendet në të ardhmen.",
|
||||
"nbfInvalid": "Vlerë `nbf` e pavlefshme.",
|
||||
"payloadNotFound": "Mungon ngarkesë.",
|
||||
"tokenExpired": "Token-i ka skaduar."
|
||||
},
|
||||
"tokenAuthFailedTitle": "Mirëfilltësimi dështoi",
|
||||
"tokenAuthFailedWithReasons": "Na ndjeni, nuk keni leje të merrni pjesë në këtë thirrje. Arsye e mundshme: {{reason}}",
|
||||
"tokenAuthUnsupported": "Nuk mbulohet URL token-i.",
|
||||
"transcribing": "Transkriptim",
|
||||
"unlockRoom": "Hiq $t(lockRoomPassword) takimi",
|
||||
"user": "Përdorues",
|
||||
@@ -483,12 +429,8 @@
|
||||
"verifyParticipantTitle": "Verifikim përdoruesi",
|
||||
"videoLink": "Lidhje videoje",
|
||||
"viewUpgradeOptions": "Shihni mundësi përmirësimi",
|
||||
"viewUpgradeOptionsContent": "Që të përfitoni përdorim të pakufizuar veçorish me pagesë, të tilla si regjistrimi, transkriptime, RTMP Streaming & etj, duhet të përmirësoni planin tuaj.",
|
||||
"viewUpgradeOptionsContent": "Që të përfitoni përdorim të pakufizuar veçorish me pagesë, të tilla si regjistrimi, transcriptime, RTMP Streaming & etj, duhet të përmirësoni planin tuaj.",
|
||||
"viewUpgradeOptionsTitle": "Zbuluat një veçori me pagesë!",
|
||||
"whiteboardLimitContent": "Na ndjeni, është mbërritur te kufiri i tabelave të njëkohshme.",
|
||||
"whiteboardLimitReference": "Për më tepër hollësi, ju lutemi, vizitoni",
|
||||
"whiteboardLimitReferenceUrl": "sajtin tonë",
|
||||
"whiteboardLimitTitle": "Kufizim përdorimi tabele",
|
||||
"yourEntireScreen": "Krejt ekranin tuaj"
|
||||
},
|
||||
"documentSharing": {
|
||||
@@ -501,9 +443,6 @@
|
||||
"title": "Trupëzojeni këtë takim"
|
||||
},
|
||||
"feedback": {
|
||||
"accessibilityLabel": {
|
||||
"yourChoice": "Zgjedhja juaj: {{rating}}"
|
||||
},
|
||||
"average": "Çka",
|
||||
"bad": "I dobët",
|
||||
"detailsLabel": "Na thoni më tepër rreth tij.",
|
||||
@@ -560,16 +499,13 @@
|
||||
"noNumbers": "S’ka numra për përdorim.",
|
||||
"noPassword": "Asnjë",
|
||||
"noRoom": "S’u dha dhomë për të cilën të formësohet numri.",
|
||||
"noWhiteboard": "S’u ngarkua dot tabela.",
|
||||
"numbers": "Numra Për T’u Përdorur",
|
||||
"password": "$t(lockRoomPasswordUppercase): ",
|
||||
"reachedLimit": "Keni mbërritur në kufijtë e planit tuaj.",
|
||||
"sip": "Adresë SIP",
|
||||
"sipAudioOnly": "Adresë SIP vetëm për audio",
|
||||
"title": "Ndani me të tjerë",
|
||||
"tooltip": "Ndani me të tjerë lidhje dhe hollësi numrash për këtë takim",
|
||||
"upgradeOptions": "Ju lutemi, shihni mundësitë e përmirësimit, te",
|
||||
"whiteboardError": "Gabim në ngarkimin e tabelës. Ju lutemi, riprovoni më vonë."
|
||||
"upgradeOptions": "Ju lutemi, shihni mundësitë e përmirësimit, te"
|
||||
},
|
||||
"inlineDialogFailure": {
|
||||
"msg": "Ngecëm pak.",
|
||||
@@ -671,13 +607,13 @@
|
||||
"knockingParticipantList": "Listë pjesëmarrësish që duan të hyjnë",
|
||||
"lobbyChatStartedNotification": "{{moderator}} filloi një fjalosje në holl me {{attendee}}",
|
||||
"lobbyChatStartedTitle": "{{moderator}} ka filluar një fjalosje në holl me ju.",
|
||||
"lobbyClosed": "Dhoma holl u mbyll.",
|
||||
"nameField": "Jepni emrin tuaj",
|
||||
"notificationLobbyAccessDenied": "Hyrja e {{targetParticipantName}} është hedhur poshtë nga {{originParticipantName}}",
|
||||
"notificationLobbyAccessGranted": "{{targetParticipantName}} është lejuar të hyjë nga {{originParticipantName}}",
|
||||
"notificationLobbyDisabled": "Holli është çaktivizuar nga {{originParticipantName}}",
|
||||
"notificationLobbyEnabled": "Holli është aktivizuar nga {{originParticipantName}}",
|
||||
"notificationTitle": "Holl",
|
||||
"passwordField": "Jepni fjalëkalim takimi",
|
||||
"passwordJoinButton": "Hyni",
|
||||
"title": "Holl",
|
||||
"toggleLabel": "Aktivizoni hollin"
|
||||
@@ -710,8 +646,6 @@
|
||||
"sessionToken": "Token Sesioni",
|
||||
"start": "Nis Regjistrim",
|
||||
"stop": "Ndale Regjistrimin",
|
||||
"stopping": "Po ndalet Regjistrimi",
|
||||
"wait": "Ju lutemi, prisni, teksa ruajmë regjistrimin tuaj",
|
||||
"yes": "Po"
|
||||
},
|
||||
"lockRoomPassword": "fjalëkalim",
|
||||
@@ -733,11 +667,8 @@
|
||||
"connectedTwoMembers": "{{first}} dhe {{second}} tjetër hynë në takim",
|
||||
"dataChannelClosed": "Rënie cilësie videoje",
|
||||
"dataChannelClosedDescription": "Kanali urë u shkëput, kështu që cilësia e videos është kufizuar te vlera më e ulët.",
|
||||
"disabledIframe": "Trupëzimi është menduar vetëm për qëllime demonstrimi, ndaj kjo thirrje do të ndërpritet pas {{timeout}} minutash.",
|
||||
"disabledIframeSecondary": "Trupëzimi i {{domain}} është menduar vetëm për qëllime demonstrimi, ndaj kjo thirrje do të ndërpritet pas {{timeout}} minutash. Ju lutemi, për trupëzime të njëmendta përdorni <a href='{{jaasDomain}}' rel='noopener noreferrer' target='_blank'>Jitsi as a Service</a>!",
|
||||
"disconnected": "u shkëput",
|
||||
"displayNotifications": "Shfaq njoftime për",
|
||||
"dontRemindMe": "Mos ma kujto",
|
||||
"focus": "Fokusi te konferenca",
|
||||
"focusFail": "{{component}} jo i passhëm - riprovoni pas {{ms}} sekondash",
|
||||
"gifsMenu": "GIPHY",
|
||||
@@ -746,7 +677,6 @@
|
||||
"invitedOneMember": "{{name}} u ftua",
|
||||
"invitedThreePlusMembers": "{{name}} dhe {{count}} të tjerë u ftuan",
|
||||
"invitedTwoMembers": "{{first}} dhe {{second}} u ftuan",
|
||||
"joinMeeting": "Hyni",
|
||||
"kickParticipant": "{{kicked}} u përzu nga {{kicker}}",
|
||||
"leftOneMember": "{{name}} doli nga takimi",
|
||||
"leftThreePlusMembers": "{{name}} dhe mjaft të tjerë dolën nga takimi",
|
||||
@@ -781,6 +711,7 @@
|
||||
"newDeviceCameraTitle": "U pikas kamerë e re",
|
||||
"noiseSuppressionDesktopAudioDescription": "Mbytja e zhurmave s’mund të aktivizohet teksa ndahet me të tjerët audioja e desktopit, ju lutemi, çaktivizojeni dhe riprovoni.",
|
||||
"noiseSuppressionFailedTitle": "S’u arrit të nisej mbytja e zhurmave",
|
||||
"noiseSuppressionNoTrackDescription": "Ju lutemi, së pari, çheshtoni mikrofonin tuaj.",
|
||||
"noiseSuppressionStereoDescription": "Aktualisht nuk mbulohet mbytje zhurmash audioje stereo.",
|
||||
"oldElectronClientDescription1": "Duket se përdorni një version të vjetër të klientit Jitsi Meet, i cili ka cenueshmëri të ditura sigurie. Ju lutemi, siguroni përditësimin me ",
|
||||
"oldElectronClientDescription2": "montimin tonë më të ri",
|
||||
@@ -804,18 +735,13 @@
|
||||
"startSilentTitle": "Hytë pa zë në dalje!",
|
||||
"suboptimalBrowserWarning": "Kemi frikë se funksionimi i takimit për ju s’do të jetë kushedi këtu. Po kërkojmë rrugë për ta përmirësuar këtë punë, por deri atëherë, ju lutemi, provoni të përdorni një nga <a href='{{recommendedBrowserPageLink}}' target='_blank'>shfletuesit e mbuluar plotësisht</a>.",
|
||||
"suboptimalExperienceTitle": "Sinjalizim Mbi Shfletuesin",
|
||||
"suggestRecordingAction": "Niseni",
|
||||
"suggestRecordingDescription": "Do të donit të nisej një regjistrim?",
|
||||
"suggestRecordingTitle": "Regjistroje këtë takim",
|
||||
"unmute": "Çheshtoje",
|
||||
"videoMutedRemotelyDescription": "Mundeni përherë ta rihapni.",
|
||||
"videoMutedRemotelyTitle": "Videoja juaj u mbyll nga {{moderator}}",
|
||||
"videoUnmuteBlockedDescription": "Heqja e heshtimit të kamerës dhe veprimi i tregimit të desktopit janë bllokuar përkohësisht për shkak kufizimesh të sistemit.",
|
||||
"videoUnmuteBlockedTitle": "Heqja e heshtimit të kamerës dhe tregimi i desktopit janë bllokuar!",
|
||||
"viewLobby": "Shihni hollin",
|
||||
"waitingParticipants": "{{waitingParticipants}} vetë",
|
||||
"whiteboardLimitDescription": "Ju lutemi, ruani ç’keni bërë, ngaqë së shpejti do të mbërrihet në kufi përdoruesi dhe tabela do të mbyllet.",
|
||||
"whiteboardLimitTitle": "Përdorim tabele"
|
||||
"waitingParticipants": "{{waitingParticipants}} vetë"
|
||||
},
|
||||
"participantsPane": {
|
||||
"actions": {
|
||||
@@ -826,7 +752,6 @@
|
||||
"askUnmute": "Kërkoni heqje heshtimi",
|
||||
"audioModeration": "Heqin heshtim të vetes",
|
||||
"blockEveryoneMicCamera": "Bllokoni mikrofonin dhe kamerën e gjithkujt",
|
||||
"breakoutRooms": "Dhoma anekse konsultimesh",
|
||||
"invite": "Ftoni Dikë",
|
||||
"moreModerationActions": "Më tepër mundësi moderimi",
|
||||
"moreModerationControls": "Më tepër kontrolle moderimi",
|
||||
@@ -844,8 +769,7 @@
|
||||
"headings": {
|
||||
"lobby": "Holli ({{count}})",
|
||||
"participantsList": "Pjesëmarrës në takim ({{count}})",
|
||||
"visitorRequests": " (requests {{count}})",
|
||||
"visitors": "Vizitorë {{count}}",
|
||||
"visitors": "Vizitorë ({{count}})",
|
||||
"waitingLobby": "Duke pritur në holl ({{count}})"
|
||||
},
|
||||
"search": "Kërkoni te pjesëmarrësit",
|
||||
@@ -935,15 +859,12 @@
|
||||
"joinWithoutAudio": "Merrni pjesë pa audio",
|
||||
"keyboardShortcuts": "Aktivizo shkurtore tastiere",
|
||||
"linkCopied": "Lidhja u kopjua në të papastër",
|
||||
"lookGood": "Gjithçka po punon si duhet",
|
||||
"lookGood": "Mikrofoni juaj po punon si duhet",
|
||||
"or": "ose",
|
||||
"premeeting": "Para takimit",
|
||||
"proceedAnyway": "Vazhdo, sido qoftë",
|
||||
"recordingWarning": "Këtë thirrje pjesëmarrës të tjerë mund ta regjistrojnë",
|
||||
"screenSharingError": "Gabim ndarjeje ekrani me të tjerë:",
|
||||
"showScreen": "Aktivizoni skenë para takimit",
|
||||
"startWithPhone": "Nise me audio telefoni",
|
||||
"unsafeRoomConsent": "I kuptoj rreziqet, dëshiroj të marr pjesë te takimi",
|
||||
"videoOnlyError": "Gabim video:",
|
||||
"videoTrackError": "S’u krijua dot pistë video.",
|
||||
"viewAllNumbers": "shihni krejt numrat"
|
||||
@@ -964,9 +885,9 @@
|
||||
},
|
||||
"profile": {
|
||||
"avatar": "avatar",
|
||||
"setDisplayNameLabel": "Emër",
|
||||
"setDisplayNameLabel": "Caktoni emrin tuaj për në ekran",
|
||||
"setEmailInput": "Jepni email",
|
||||
"setEmailLabel": "Jepni email të gravatarit tuaj",
|
||||
"setEmailLabel": "Caktoni email të gravatarit tuaj",
|
||||
"title": "Profil"
|
||||
},
|
||||
"raisedHand": "Do të donte të fliste",
|
||||
@@ -998,16 +919,17 @@
|
||||
"failedToStart": "S’u arrit të niset regjistrimi",
|
||||
"fileSharingdescription": "Ndajeni regjistrimin me pjesëmarrësit në takim",
|
||||
"highlight": "Nxjerrje në pah",
|
||||
"highlightMoment": "Nxirrni në pah një çast",
|
||||
"highlightMoment": "Nxirni në pah një çast",
|
||||
"highlightMomentDisabled": "Mund të nxirrni në pah çaste kur fillon regjistrimi",
|
||||
"highlightMomentSuccess": "Çasti u nxor në pah",
|
||||
"highlightMomentSuccess": "Çasti u nxorr në pah",
|
||||
"highlightMomentSucessDescription": "Çasti i nxjerrë në pah nga ju do të shtohet te përmbledhja e takimit.",
|
||||
"inProgress": "Regjistrim ose transmetim drejtpërsëdrejti në ecuri e sipër",
|
||||
"limitNotificationDescriptionNative": "Për shkak kërkesash të shumta, regjistrimi juaj do të kufizohet në {{limit}} min. Për regjistrime të pakufizuara provoni <3>{{app}}</3>.",
|
||||
"limitNotificationDescriptionWeb": "Për shkak kërkesash të shumta, regjistrimi juaj do të kufizohet në {{limit}} min. Për regjistrime të pakufizuara provoni <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"linkGenerated": "Kemi prodhuar një lidhje për te regjistrimi juaj.",
|
||||
"live": "DREJTPËRSËDREJTI",
|
||||
"localRecordingNoNotificationWarning": "Regjistrimi s’do t’u njoftohet pjesëmarrësve të tjerë. Do t’ju duhet t’i vini në dijeni se takimi po regjistrohet.",
|
||||
"localRecordingNoVideo": "Videoja s’po regjistrohet",
|
||||
"localRecordingNoVideo": "Videoja nuk po regjistrohet",
|
||||
"localRecordingStartWarning": "Ju lutemi, sigurohuni se e ndalni regjistrimin para se dilni nga takimi, që të mund ta ruani.",
|
||||
"localRecordingStartWarningTitle": "Ndaleni regjistrimin që ta ruani",
|
||||
"localRecordingVideoStop": "Ndalja e videos tuaj do të ndalë gjithashtu edhe regjistrimin vendor. Jeni i sigurt se doni të vazhdohet?",
|
||||
@@ -1022,15 +944,13 @@
|
||||
"onBy": "{{name}} nisi regjistrimin",
|
||||
"onlyRecordSelf": "Regjistro vetëm rrjedhat e mia audio dhe video",
|
||||
"pending": "Po përgatitet të regjistrohet takimi…",
|
||||
"recordAudioAndVideo": "Regjistro audio dhe video",
|
||||
"recordTranscription": "Regjistro transkriptimin",
|
||||
"rec": "REC",
|
||||
"saveLocalRecording": "Ruajeni lokalisht kartelën e regjistrimit (Beta)",
|
||||
"serviceDescription": "Regjistrimi juaj do të ruhet nga shërbimi i regjistrimit",
|
||||
"serviceDescriptionCloud": "Regjistrim në re",
|
||||
"serviceDescriptionCloudInfo": "Takimet e regjistruara spastrohen automatikisht 24h pas kohës së regjistrimit të tyre.",
|
||||
"serviceName": "Shërbim regjistrimi",
|
||||
"sessionAlreadyActive": "Ky sesion po regjistrohet ose transmetohet drejtpërsëdrejti tashmë.",
|
||||
"showAdvancedOptions": "Mundësi të mëtejshme",
|
||||
"signIn": "Hyni",
|
||||
"signOut": "Dilni",
|
||||
"surfaceError": "Ju lutemi, përdorni skedën e tanishme.",
|
||||
@@ -1046,17 +966,10 @@
|
||||
"security": {
|
||||
"about": "Takimit tuaj mund t’i shtoni një $t(lockRoomPassword). Pjesëmarrësve do t’u duhet të japin $t(lockRoomPassword) përpara se të lejohen të marrin pjesë në takim.",
|
||||
"aboutReadOnly": "Pjesëmarrësit moderatorë mund t’i shtojnë takimit një $t(lockRoomPassword). Pjesëmarrësve do t’u duhet të japin $t(lockRoomPassword) përpara se të lejohen të marrin pjesë në takim.",
|
||||
"insecureRoomNameWarningNative": "Emri i dhomës s’është pa rrezik. Pjesëmarrës të padëshiruar munden të hyjnë në takimin tuaj. {{recommendAction}} Mësoni më tepër rreth sigurimit të takimit tuaj ",
|
||||
"insecureRoomNameWarningWeb": "Emri i dhomës s’është pa rrezik. Pjesëmarrës të padëshiruar munden të hyjnë në takimin tuaj. {{recommendAction}} Mësoni më tepër rreth sigurimit të takimit tuaj <a href=\"{{securityUrl}}\" rel=\"security\" target=\"_blank\">këtu</a>.",
|
||||
"title": "Mundësi Sigurie",
|
||||
"unsafeRoomActions": {
|
||||
"meeting": "Shihni mundësinë e sigurimit të takimit tuaj, duke përdorur butonin e sigurisë.",
|
||||
"prejoin": "Shihni mundësinë e përdorimit për takimin të një emri më të veçantë.",
|
||||
"welcome": "Shihni mundësinë e përdorimit për takimin të një emri më të veçantë, ose zgjidhni një nga sugjerimet."
|
||||
}
|
||||
"insecureRoomNameWarning": "Emri i dhomës s’është pa rrezik. Pjesëmarrës të padëshiruar munden të marrin pjesë në konferencën tuaj. Shihni mundësinë e bërjes të sigurt të takimit tuaj, duke përdorur butonin e sigurisë.",
|
||||
"title": "Mundësi Sigurie"
|
||||
},
|
||||
"settings": {
|
||||
"audio": "Audio",
|
||||
"buttonLabel": "Rregullime",
|
||||
"calendar": {
|
||||
"about": "Integrimi me kalendar {{appName}} përdoret për të hyrë me sukses te kalendari juaj, që kështu të mund të lexohen veprimtari të ardhshme.",
|
||||
@@ -1077,11 +990,9 @@
|
||||
"maxStageParticipants": "Numër maksimum pjesëmarrësish që mund të fiksohen te skena kryesore (EKSPERIMENTALe)",
|
||||
"microphones": "Mikrofona",
|
||||
"moderator": "Moderator",
|
||||
"moderatorOptions": "Mundësi moderatori",
|
||||
"more": "Të përgjitshme",
|
||||
"more": "Më tepër",
|
||||
"name": "Emër",
|
||||
"noDevice": "Asnjë",
|
||||
"notifications": "Njoftime",
|
||||
"participantJoined": "Hyri Pjesëmarrës",
|
||||
"participantKnocking": "Pjesëmarrës hyri në holl",
|
||||
"participantLeft": "Doli Pjesëmarrës",
|
||||
@@ -1092,14 +1003,13 @@
|
||||
"selectCamera": "Kamerë",
|
||||
"selectMic": "Mikrofon",
|
||||
"selfView": "Parje e vetes",
|
||||
"shortcuts": "Shkurtore",
|
||||
"sounds": "Tinguj",
|
||||
"speakers": "Altoparlantë",
|
||||
"startAudioMuted": "Gjithkush fillon i heshtuar",
|
||||
"startReactionsMuted": "Heshto tinguj reagimesh për këdo",
|
||||
"startVideoMuted": "Gjithkush fillon i fshehur",
|
||||
"talkWhileMuted": "Flisni, teksa jeni i heshtuar",
|
||||
"title": "Rregullime",
|
||||
"video": "Video"
|
||||
"title": "Rregullime"
|
||||
},
|
||||
"settingsView": {
|
||||
"advanced": "Të mëtejshme",
|
||||
@@ -1107,7 +1017,6 @@
|
||||
"alertOk": "OK",
|
||||
"alertTitle": "Kujdes",
|
||||
"alertURLText": "URL-ja e dhënë për shërbyesin është e pavlefshme",
|
||||
"apply": "Aplikoji",
|
||||
"buildInfoSection": "Hollësi Montimi",
|
||||
"conferenceSection": "Konferencë",
|
||||
"disableCallIntegration": "Çaktivizo integrim thirrje me sistemin",
|
||||
@@ -1118,21 +1027,19 @@
|
||||
"displayNamePlaceholderText": "P.sh.: Zamir Gjoli",
|
||||
"email": "Email",
|
||||
"emailPlaceholderText": "email@example.com",
|
||||
"gavatarMessage": "Nëse emal-i juaj është i përshoqëruar me një llogari Gravatar, do ta përdorim për të shfaqur foton e profilit tuaj.",
|
||||
"goTo": "Kalo te",
|
||||
"header": "Rregullime",
|
||||
"help": "Ndihmë",
|
||||
"links": "Lidhje",
|
||||
"privacy": "Privatësi",
|
||||
"profileSection": "Profil",
|
||||
"sdkVersion": "Version SDK",
|
||||
"serverURL": "URL Shërbyesi",
|
||||
"showAdvanced": "Shfaq rregullime të mëtejshme",
|
||||
"startCarModeInLowBandwidthMode": "Nën mënyrën “gjerësi e ulët bande” nis mënyrën automjet",
|
||||
"startWithAudioMuted": "Fillo me audio të mbyllur",
|
||||
"startWithVideoMuted": "Fillo me video të mbyllur",
|
||||
"terms": "Terma",
|
||||
"version": "Version aplikacioni"
|
||||
"version": "Version"
|
||||
},
|
||||
"share": {
|
||||
"dialInfoText": "\n\n=====\n\nThjesht doni t’i bini numrit në telefonin tuaj?\n\n{{defaultDialInNumber}}Klikoni mbi këtë lidhje, që të shihni numra telefoni për këtë takim\n{{dialInfoPageUrl}}",
|
||||
@@ -1143,7 +1050,7 @@
|
||||
"angry": "I zemëruar",
|
||||
"disgusted": "I pështirosur",
|
||||
"displayEmotions": "Shfaq emocione",
|
||||
"fearful": "I frikësuar",
|
||||
"fearful": "I firkësuar",
|
||||
"happy": "I gëzuar",
|
||||
"hours": "{{count}}h",
|
||||
"minutes": "{{count}}m",
|
||||
@@ -1151,7 +1058,7 @@
|
||||
"neutral": "Asnjanës",
|
||||
"sad": "I trishtuar",
|
||||
"search": "Kërko",
|
||||
"searchHint": "Kërkoni për pjesëmarrës",
|
||||
"searchHint": "Kërkoni pjesëmarrësit",
|
||||
"seconds": "{{count}}s",
|
||||
"speakerStats": "Statistika Folësi",
|
||||
"speakerTime": "Kohë Folësi",
|
||||
@@ -1174,7 +1081,7 @@
|
||||
"toolbar": {
|
||||
"Settings": "Rregullime",
|
||||
"accessibilityLabel": {
|
||||
"Settings": "Hap rregullimet",
|
||||
"Settings": "Shfaq/Fshih rregullimet",
|
||||
"audioOnly": "Hap/Mbyll vetëm audion",
|
||||
"audioRoute": "Përzgjidhni pajisje zëri",
|
||||
"boo": "Ya",
|
||||
@@ -1184,20 +1091,11 @@
|
||||
"cc": "Shfaq/Fshih titra",
|
||||
"chat": "Hapni / Mbyllni fjalosje",
|
||||
"clap": "Duartrokitje",
|
||||
"closeChat": "Mbylle fjalosjen",
|
||||
"closeMoreActions": "Mbyll menunë Më Tepër Veprime",
|
||||
"closeParticipantsPane": "Mbyll kuadratin pjesëmarrës",
|
||||
"collapse": "Tkurre",
|
||||
"document": "Shfaq/Fshih dokument të ndarë",
|
||||
"documentClose": "Mbyll dokument të ndarë",
|
||||
"documentOpen": "Hap dokument të ndarë",
|
||||
"download": "Shkarkoni aplikacionet tona",
|
||||
"embedMeeting": "Trupëzoni takimin",
|
||||
"endConference": "Përfundoje takimin për të tërë",
|
||||
"enterFullScreen": "Shiheni sa krejt ekrani",
|
||||
"enterTileView": "Kaloni nën mënyrën me kuadrate",
|
||||
"exitFullScreen": "Dil nga mënyra “Sa krejt ekrani”",
|
||||
"exitTileView": "Dil nga mënyra me kuadrate",
|
||||
"expand": "Zgjeroje",
|
||||
"feedback": "Lini përshtypje",
|
||||
"fullScreen": "Kalo nën/Dil nga mënyra “Sa krejt ekrani”",
|
||||
@@ -1206,7 +1104,6 @@
|
||||
"hangup": "Braktiseni takimin",
|
||||
"heading": "Panel",
|
||||
"help": "Ndihmë",
|
||||
"hideWhiteboard": "Fshihe tabelën",
|
||||
"invite": "Ftoni njerëz",
|
||||
"kick": "Përzëre pjesëmarrësin",
|
||||
"laugh": "E qeshur",
|
||||
@@ -1216,25 +1113,21 @@
|
||||
"lobbyButton": "Aktivizo/Çaktivizoni mënyrën holl",
|
||||
"localRecording": "Shfaq/Fshih kontrolle regjistrimi vendor",
|
||||
"lockRoom": "Aktivizo/Çaktivizo fjalëkalim takimi",
|
||||
"lowerHand": "Ulni dorën",
|
||||
"moreActions": "Më tepër veprime",
|
||||
"moreActionsMenu": "Menu “Më tepër veprime”",
|
||||
"moreOptions": "Shfaq më tepër mundësi",
|
||||
"mute": "Heshto mikrofonin",
|
||||
"mute": "Heshtoje / Çheshtoje",
|
||||
"muteEveryone": "Heshto gjithkënd",
|
||||
"muteEveryoneElse": "Heshto gjithkënd tjetër",
|
||||
"muteEveryoneElsesVideoStream": "Ndal videon e gjithkujt tjetër",
|
||||
"muteEveryonesVideoStream": "Ndal videon e gjithkujt",
|
||||
"muteGUMPending": "Po lidhet mikrofoni juaj",
|
||||
"noiseSuppression": "Mbytje zhurmash",
|
||||
"openChat": "Hapni fjalosje",
|
||||
"participants": "Hapni kuadrat pjesëmarrësish",
|
||||
"participants": "Pjesëmarrës",
|
||||
"pip": "Aktivizo/Çaktivizo mënyrën “Picture-in-Picture”",
|
||||
"privateMessage": "Dërgoni mesazh privat",
|
||||
"profile": "Përpunoni profilin tuaj",
|
||||
"raiseHand": "Ngrini dorën",
|
||||
"reactions": "Reagime",
|
||||
"reactionsMenu": "Menu reagimesh",
|
||||
"raiseHand": "Ngrini / Ulni dorën tuaj",
|
||||
"reactionsMenu": "Hap / Mbyll menu reagimesh",
|
||||
"recording": "Nis/Ndal regjistrimin",
|
||||
"remoteMute": "Heshto pjesëmarrësin",
|
||||
"remoteVideoMute": "Çaktivizo kamerën e pjesëmarrësit",
|
||||
@@ -1242,25 +1135,20 @@
|
||||
"selectBackground": "Përzgjidhni Sfond",
|
||||
"selfView": "Shfaq/Fshih pamje të vetes",
|
||||
"shareRoom": "Ftoni dikë",
|
||||
"shareYourScreen": "Nisni tregimin e ekranit tuaj",
|
||||
"shareYourScreen": "Nisni / Ndalni tregimin e ekranit tuaj",
|
||||
"shareaudio": "Ndani audio me të tjerë",
|
||||
"sharedvideo": "Ndani video me të tjerë",
|
||||
"sharedvideo": "Aktivizo/Çaktivizo ndarje videoje me të tjerë",
|
||||
"shortcuts": "Shfaq/Fshih shkurtore",
|
||||
"show": "Shfaqe në skenë",
|
||||
"showWhiteboard": "Shfaq tabelë",
|
||||
"silence": "Heshtje",
|
||||
"speakerStats": "Shfaq/Fshih statistika folësi",
|
||||
"stopScreenSharing": "Ndalni tregimin e ekranit tuaj",
|
||||
"stopSharedVideo": "Ndalni videon",
|
||||
"surprised": "I befasuar",
|
||||
"tileView": "Kalo në/Dil nga mënyra mozaik",
|
||||
"toggleCamera": "Hap/Mbyll kamerën",
|
||||
"toggleFilmstrip": "Shfaq/Fshih shirit filmi",
|
||||
"unmute": "Hiqni heshtim mikrofoni",
|
||||
"videoblur": "Aktivizo/Çaktivizo turbullim videoje",
|
||||
"videomute": "Ndal kamerën",
|
||||
"videomuteGUMPending": "Po lidhet kamera juaj",
|
||||
"videounmute": "Nis kamerën"
|
||||
"videomute": "Nis / Ndal kamerën",
|
||||
"whiteboard": "Shfaq / Fshih tabelën"
|
||||
},
|
||||
"addPeople": "Shtoni persona te thirrja juaj",
|
||||
"audioOnlyOff": "Çaktivizo mënyrën “Sasi e ulët të dhënash trafiku”",
|
||||
@@ -1273,7 +1161,6 @@
|
||||
"chat": "Hap / Mbyll fjalosje",
|
||||
"clap": "Duartrokitje",
|
||||
"closeChat": "Mbyll fjalosjen",
|
||||
"closeParticipantsPane": "Mbylle kuadratin e pjesëmarrësve",
|
||||
"closeReactionsMenu": "Mbyll menu reagimesh",
|
||||
"disableNoiseSuppression": "Çaktivizo mbytje zhurmash",
|
||||
"disableReactionSounds": "Mund të çaktivizoni tinguj reagimesh për këtë takim",
|
||||
@@ -1282,7 +1169,6 @@
|
||||
"download": "Shkarkoni aplikacione tonat",
|
||||
"e2ee": "Fshehtëzim Skaj-Më-Skaj",
|
||||
"embedMeeting": "Trupëzoni takim",
|
||||
"enableNoiseSuppression": "Aktivizoni mbytje zhurmash",
|
||||
"endConference": "Përfundoje takimin për të tërë",
|
||||
"enterFullScreen": "Shiheni sa krejt ekrani",
|
||||
"enterTileView": "Kalo te pamja me kuadrate",
|
||||
@@ -1307,10 +1193,9 @@
|
||||
"lowerYourHand": "Ulni dorën",
|
||||
"moreActions": "Më tepër veprime",
|
||||
"moreOptions": "Më tepër veprime",
|
||||
"mute": "Heshto mikrofonin",
|
||||
"mute": "Heshtoje / Hiqi heshtimin",
|
||||
"muteEveryone": "Heshto gjithkënd",
|
||||
"muteEveryonesVideo": "Çaktivizo videon e gjithkujt",
|
||||
"muteGUMPending": "Po lidhet mikrofoni juaj",
|
||||
"noAudioSignalDesc": "Nëse s’e keni heshtuar që nga rregullimet e sistemit, ose nga hardware-i, shihni mundësinë e ndërrimit të pajisjes.",
|
||||
"noAudioSignalDescSuggestion": "Nëse s’e keni heshtuar që nga rregullimet e sistemit, ose nga hardware-i, shihni mundësinë e kalimit te pajisja e sugjeruar.",
|
||||
"noAudioSignalDialInDesc": "Mund t’i bini numrit edhe duke përdorur:",
|
||||
@@ -1325,7 +1210,7 @@
|
||||
"pip": "Kalo nën mënyrën “Picture-in-Picture”",
|
||||
"privateMessage": "Dërgo mesazh privat",
|
||||
"profile": "Përpunoni profilin tuaj",
|
||||
"raiseHand": "Ngrini dorën",
|
||||
"raiseHand": "Ngrini / Ulni dorën",
|
||||
"raiseYourHand": "Ngrini dorën",
|
||||
"reactionBoo": "Dërgoni reagim me ya",
|
||||
"reactionClap": "Dërgoni reagim me duartrokitje",
|
||||
@@ -1333,7 +1218,6 @@
|
||||
"reactionLike": "Dërgoni reagim me “thumbs up”",
|
||||
"reactionSilence": "Dërgoni reagim me heshtje",
|
||||
"reactionSurprised": "Dërgoni reagim të befasuari",
|
||||
"reactions": "Reagime",
|
||||
"security": "Mundësi sigurie",
|
||||
"selectBackground": "Përzgjidhni sfond",
|
||||
"shareRoom": "Ftoni dikë",
|
||||
@@ -1353,17 +1237,17 @@
|
||||
"talkWhileMutedPopup": "Po provoni të flisni? Jeni i heshtuar.",
|
||||
"tileViewToggle": "Kalo në/Dil nga mënyra mozaik",
|
||||
"toggleCamera": "Hapni/Mbyllni kamerën",
|
||||
"unmute": "Hiqni heshtimin e mikrofonit",
|
||||
"videoSettings": "Rregullime videoje",
|
||||
"videomute": "Ndalni kamerën",
|
||||
"videomuteGUMPending": "Po lidhet kamera juaj",
|
||||
"videounmute": "Nisni kamerën"
|
||||
"videoSetting": "Rregullime videoje",
|
||||
"videomute": "Nisni / Ndalni kamerën"
|
||||
},
|
||||
"transcribing": {
|
||||
"ccButtonTooltip": "Ndali / Nisi titrat",
|
||||
"error": "Transkriptimi dështoi. Ju lutemi, riprovoni.",
|
||||
"expandedLabel": "Transkriptimi aktualisht është aktiv",
|
||||
"failedToStart": "S’u arrit të nisej transkriptim",
|
||||
"labelToolTip": "Takimit po i bëhet transkriptim",
|
||||
"off": "Transkriptimi u ndal",
|
||||
"pending": "Po përgatitet të transkriptohet takimi…",
|
||||
"sourceLanguageDesc": "Aktualisht si gjuhë takimi është caktuar <b>{{sourceLanguage}}</b>. <br/> Mund ta ndryshoni që nga ",
|
||||
"sourceLanguageHere": "këtu",
|
||||
"start": "Fillo shfaqje titrash",
|
||||
@@ -1400,7 +1284,7 @@
|
||||
"audioOnly": "AUD",
|
||||
"audioOnlyExpanded": "Gjendeni nën mënyrën “gjerësi e ulët bande”. Nën këtë mënyrë, do të merrni vetëm audio dhe tregim ekrani.",
|
||||
"bestPerformance": "Punimi më i mirë",
|
||||
"callQuality": "Cilësi Videoje (0 për punimin më të mirë, 3 për cilësinë më të lartë)",
|
||||
"callQuality": "Cilësi videoje",
|
||||
"hd": "CL",
|
||||
"hdTooltip": "Po shihet video në cilësi të lartë",
|
||||
"highDefinition": "Cilësi e Lartë",
|
||||
@@ -1442,10 +1326,6 @@
|
||||
"videomute": "Pjesëmarrësi ka ndalur kamerën"
|
||||
},
|
||||
"virtualBackground": {
|
||||
"accessibilityLabel": {
|
||||
"currentBackground": "Sfondi i tanishëm: {{background}}",
|
||||
"selectBackground": "Përzgjidhni një sfond"
|
||||
},
|
||||
"addBackground": "Shtoni sfond",
|
||||
"apply": "Zbatoje",
|
||||
"backgroundEffectError": "S’u arrit të zbatohej efekt sfondi.",
|
||||
@@ -1463,20 +1343,13 @@
|
||||
"none": "Asnjë",
|
||||
"pleaseWait": "Ju lutemi, pritni…",
|
||||
"removeBackground": "Hiqe sfondin",
|
||||
"slightBlur": "Gjysmë-Turbullim",
|
||||
"slightBlur": "Turbullim Paksa",
|
||||
"title": "Sfonde virtualë",
|
||||
"uploadedImage": "Ngarkoi figurën {{index}}",
|
||||
"webAssemblyWarning": "Nuk mbulohet WebAssembly",
|
||||
"webAssemblyWarningDescription": "WebAssembly e çaktivizuar ose e pambuluar nga ky shfletues"
|
||||
},
|
||||
"visitors": {
|
||||
"chatIndicator": "(vizitor)",
|
||||
"labelTooltip": "Numër vizitorësh: {{count}}",
|
||||
"notification": {
|
||||
"description": "Që të merrni pjesë, ngrini dorën",
|
||||
"title": "Jeni vizitor në takim"
|
||||
}
|
||||
},
|
||||
"visitorsLabel": "Numër vizitorësh: {{count}}",
|
||||
"volumeSlider": "Rrëshqitës volumi",
|
||||
"welcomepage": {
|
||||
"accessibilityLabel": {
|
||||
@@ -1509,7 +1382,6 @@
|
||||
"microsoftLogo": "Stemë Microsoft-i",
|
||||
"policyLogo": "Stemë Rregullash"
|
||||
},
|
||||
"meetingsAccessibilityLabel": "Takime",
|
||||
"mobileDownLoadLinkAndroid": "Shkarkoni aplikacionin për celular me Android",
|
||||
"mobileDownLoadLinkFDroid": "Shkarkoni aplikacionin për celular me F-Droid",
|
||||
"mobileDownLoadLinkIos": "Shkarkoni aplikacionin për celular me iOS",
|
||||
@@ -1533,7 +1405,6 @@
|
||||
"whiteboard": {
|
||||
"accessibilityLabel": {
|
||||
"heading": "Tabelë shënimesh"
|
||||
},
|
||||
"screenTitle": "Tabelë shënimesh"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,7 +222,6 @@
|
||||
"Share": "Paylaş",
|
||||
"Submit": "Gönder",
|
||||
"WaitForHostMsg": "Toplantısı henüz başlamadı. Toplantı sahibi sizseniz, lütfen kimlik doğrulaması yapın. Değilseniz lütfen toplantı sahibinin gelmesini bekleyin.",
|
||||
"WaitingForHostButton": "Toplantı sahibini bekle",
|
||||
"WaitingForHostTitle": "Toplantı sahibi bekleniyor ...",
|
||||
"Yes": "Evet",
|
||||
"accessibilityLabel": {
|
||||
|
||||
@@ -219,9 +219,7 @@
|
||||
"joinInBrowser": "Join in browser",
|
||||
"launchMeetingLabel": "How do you want to join this meeting?",
|
||||
"launchWebButton": "Launch in web",
|
||||
"noDesktopApp": "You don’t have the app?",
|
||||
"noMobileApp": "You don’t have the app?",
|
||||
"or": "OR",
|
||||
"termsAndConditions": "By continuing you agree to our <a href='{{termsAndConditionsLink}}' rel='noopener noreferrer' target='_blank'>terms & conditions.</a>",
|
||||
"title": "Launching your meeting in {{app}}...",
|
||||
"titleNew": "Launching your meeting ...",
|
||||
@@ -305,8 +303,6 @@
|
||||
"contactSupport": "Contact support",
|
||||
"copied": "Copied",
|
||||
"copy": "Copy",
|
||||
"demoteParticipantDialog": "Are you sure you want to move this participant to visitor?",
|
||||
"demoteParticipantTitle": "Move to visitor",
|
||||
"dismiss": "Dismiss",
|
||||
"displayNameRequired": "Hi! What’s your name?",
|
||||
"done": "Done",
|
||||
@@ -562,7 +558,6 @@
|
||||
"noNumbers": "No dial-in numbers.",
|
||||
"noPassword": "None",
|
||||
"noRoom": "No room was specified to dial-in into.",
|
||||
"noWhiteboard": "Could not load the whiteboard.",
|
||||
"numbers": "Dial-in Numbers",
|
||||
"password": "$t(lockRoomPasswordUppercase): ",
|
||||
"reachedLimit": "You have reached the limit of your plan.",
|
||||
@@ -570,8 +565,7 @@
|
||||
"sipAudioOnly": "SIP audio only address",
|
||||
"title": "Share",
|
||||
"tooltip": "Share link and dial-in info for this meeting",
|
||||
"upgradeOptions": "Please check the upgrade options on",
|
||||
"whiteboardError": "Error loading the whiteboard. Please try again later."
|
||||
"upgradeOptions": "Please check the upgrade options on"
|
||||
},
|
||||
"inlineDialogFailure": {
|
||||
"msg": "We stumbled a bit.",
|
||||
@@ -621,7 +615,7 @@
|
||||
"errorAPI": "An error occurred while accessing your YouTube broadcasts. Please try logging in again.",
|
||||
"errorLiveStreamNotEnabled": "Live Streaming is not enabled on {{email}}. Please enable live streaming or log into an account with live streaming enabled.",
|
||||
"expandedOff": "The live streaming has stopped",
|
||||
"expandedOn": "The meeting is currently being live streamed",
|
||||
"expandedOn": "The meeting is currently being streamed to YouTube.",
|
||||
"expandedPending": "The live streaming is being started...",
|
||||
"failedToStart": "Live Streaming failed to start",
|
||||
"getStreamKeyManually": "We weren’t able to fetch any live streams. Try getting your live stream key from YouTube.",
|
||||
@@ -815,7 +809,6 @@
|
||||
"videoUnmuteBlockedDescription": "Camera unmute and desktop sharing operation have been temporarily blocked because of system limits.",
|
||||
"videoUnmuteBlockedTitle": "Camera unmute and desktop sharing blocked!",
|
||||
"viewLobby": "View lobby",
|
||||
"viewVisitors": "View visitors",
|
||||
"waitingParticipants": "{{waitingParticipants}} people",
|
||||
"whiteboardLimitDescription": "Please save your progress, as the user limit will soon be reached and the whiteboard will close.",
|
||||
"whiteboardLimitTitle": "Whiteboard usage"
|
||||
@@ -942,7 +935,6 @@
|
||||
"or": "or",
|
||||
"premeeting": "Pre meeting",
|
||||
"proceedAnyway": "Proceed anyway",
|
||||
"recordingWarning": "Other participants may be recording this call",
|
||||
"screenSharingError": "Screen sharing error:",
|
||||
"showScreen": "Enable pre meeting screen",
|
||||
"startWithPhone": "Start with phone audio",
|
||||
@@ -996,7 +988,7 @@
|
||||
"error": "Recording failed. Please try again.",
|
||||
"errorFetchingLink": "Error fetching recording link.",
|
||||
"expandedOff": "Recording has stopped",
|
||||
"expandedOn": "The meeting is currently being recorded",
|
||||
"expandedOn": "The meeting is currently being recorded.",
|
||||
"expandedPending": "Recording is being started...",
|
||||
"failedToStart": "Recording failed to start",
|
||||
"fileSharingdescription": "Share the recording link with the meeting participants",
|
||||
@@ -1364,9 +1356,13 @@
|
||||
},
|
||||
"transcribing": {
|
||||
"ccButtonTooltip": "Start / Stop subtitles",
|
||||
"error": "Transcribing failed. Please try again.",
|
||||
"expandedLabel": "Transcribing is currently on",
|
||||
"failedToStart": "Transcribing failed to start",
|
||||
"labelToolTip": "The meeting is being transcribed",
|
||||
"off": "Transcribing stopped",
|
||||
"on": "Transcribing started",
|
||||
"pending": "Preparing to transcribe the meeting...",
|
||||
"sourceLanguageDesc": "Currently the meeting language is set to <b>{{sourceLanguage}}</b>. <br/> You can change it from ",
|
||||
"sourceLanguageHere": "here",
|
||||
"start": "Start showing subtitles",
|
||||
@@ -1422,7 +1418,6 @@
|
||||
},
|
||||
"videothumbnail": {
|
||||
"connectionInfo": "Connection Info",
|
||||
"demote": "Move to visitor",
|
||||
"domute": "Mute",
|
||||
"domuteOthers": "Mute everyone else",
|
||||
"domuteVideo": "Disable camera",
|
||||
@@ -1477,7 +1472,6 @@
|
||||
"chatIndicator": "(visitor)",
|
||||
"labelTooltip": "Number of visitors: {{count}}",
|
||||
"notification": {
|
||||
"demoteDescription": "Sent here by {{actor}}, raise your hand to participate",
|
||||
"description": "To participate raise your hand",
|
||||
"title": "You are a visitor in the meeting"
|
||||
}
|
||||
@@ -1538,7 +1532,6 @@
|
||||
"whiteboard": {
|
||||
"accessibilityLabel": {
|
||||
"heading": "Whiteboard"
|
||||
},
|
||||
"screenTitle": "Whiteboard"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ import { isAudioMuteButtonDisabled } from '../../react/features/toolbox/function
|
||||
import { setTileView, toggleTileView } from '../../react/features/video-layout/actions.any';
|
||||
import { muteAllParticipants } from '../../react/features/video-menu/actions';
|
||||
import { setVideoQuality } from '../../react/features/video-quality/actions';
|
||||
import { toggleWhiteboard } from '../../react/features/whiteboard/actions.web';
|
||||
import { toggleWhiteboard } from '../../react/features/whiteboard/actions.any';
|
||||
import { getJitsiMeetTransport } from '../transport';
|
||||
|
||||
import {
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
} from '../../react/features/base/conference/actions';
|
||||
import { isMobileBrowser } from '../../react/features/base/environment/utils';
|
||||
import { setColorAlpha } from '../../react/features/base/util/helpers';
|
||||
import { sanitizeUrl } from '../../react/features/base/util/uri';
|
||||
import { setDocumentUrl } from '../../react/features/etherpad/actions';
|
||||
import { setFilmstripVisible } from '../../react/features/filmstrip/actions.any';
|
||||
import {
|
||||
@@ -136,16 +135,14 @@ UI.unbindEvents = () => {
|
||||
* @param {string} name etherpad id
|
||||
*/
|
||||
UI.initEtherpad = name => {
|
||||
const etherpadBaseUrl = sanitizeUrl(config.etherpad_base);
|
||||
|
||||
if (etherpadManager || !etherpadBaseUrl || !name) {
|
||||
if (etherpadManager || !config.etherpad_base || !name) {
|
||||
return;
|
||||
}
|
||||
logger.log('Etherpad is enabled');
|
||||
|
||||
etherpadManager = new EtherpadManager(eventEmitter);
|
||||
|
||||
const url = new URL(name, etherpadBaseUrl);
|
||||
const url = new URL(name, config.etherpad_base);
|
||||
|
||||
APP.store.dispatch(setDocumentUrl(url.toString()));
|
||||
|
||||
|
||||
@@ -229,9 +229,6 @@ export default class LargeVideoManager {
|
||||
|
||||
preUpdate.then(() => {
|
||||
const { id, stream, videoType, resolve } = this.newStreamData;
|
||||
|
||||
this.newStreamData = null;
|
||||
|
||||
const state = APP.store.getState();
|
||||
const shouldHideSelfView = getHideSelfView(state);
|
||||
const localId = getLocalParticipant(state)?.id;
|
||||
@@ -242,6 +239,8 @@ export default class LargeVideoManager {
|
||||
// the video container type (Etherpad, SharedVideo, VideoContainer).
|
||||
const isVideoContainer = LargeVideoManager.isVideoContainer(videoType);
|
||||
|
||||
this.newStreamData = null;
|
||||
|
||||
logger.debug(`Scheduled large video update for ${id}`);
|
||||
this.state = videoType;
|
||||
// eslint-disable-next-line no-shadow
|
||||
@@ -288,6 +287,10 @@ export default class LargeVideoManager {
|
||||
|| streamingStatusActive
|
||||
);
|
||||
|
||||
this.videoTrack?.jitsiTrack?.getVideoType() === VIDEO_TYPE.DESKTOP
|
||||
&& logger.debug(`Remote track ${videoTrack?.jitsiTrack}, isVideoMuted=${isVideoMuted},`
|
||||
+ ` streamingStatusActive=${streamingStatusActive}, isVideoRenderable=${isVideoRenderable}`);
|
||||
|
||||
const isAudioOnly = APP.conference.isAudioOnly();
|
||||
|
||||
// Multi-stream is not supported on plan-b endpoints even if its is enabled via config.js. A virtual
|
||||
@@ -300,10 +303,6 @@ export default class LargeVideoManager {
|
||||
= isVideoContainer
|
||||
&& ((isAudioOnly && videoType !== VIDEO_TYPE.DESKTOP) || !isVideoRenderable || legacyScreenshare);
|
||||
|
||||
logger.debug(`scheduleLargeVideoUpdate: Remote track ${videoTrack?.jitsiTrack}, isVideoMuted=${
|
||||
isVideoMuted}, streamingStatusActive=${streamingStatusActive}, isVideoRenderable=${
|
||||
isVideoRenderable}, showAvatar=${showAvatar}`);
|
||||
|
||||
let promise;
|
||||
|
||||
// do not show stream if video is muted
|
||||
|
||||
@@ -26,13 +26,6 @@ const FADE_DURATION_MS = 300;
|
||||
|
||||
const logger = Logger.getLogger(__filename);
|
||||
|
||||
/**
|
||||
* List of container events that we are going to process for the large video.
|
||||
*
|
||||
* NOTE: Currently used only for logging for debug purposes.
|
||||
*/
|
||||
const containerEvents = [ 'abort', 'canplaythrough', 'ended', 'error', 'stalled', 'suspend', 'waiting' ];
|
||||
|
||||
/**
|
||||
* Returns an array of the video dimensions, so that it keeps it's aspect
|
||||
* ratio and fits available area with it's larger dimension. This method
|
||||
@@ -249,18 +242,11 @@ export class VideoContainer extends LargeContainer {
|
||||
this.wrapperParent = document.getElementById('largeVideoElementsContainer');
|
||||
this.avatarHeight = document.getElementById('dominantSpeakerAvatarContainer').getBoundingClientRect().height;
|
||||
this.video.onplaying = function(event) {
|
||||
logger.debug('Large video is playing!');
|
||||
if (typeof resizeContainer === 'function') {
|
||||
resizeContainer(event);
|
||||
}
|
||||
};
|
||||
|
||||
containerEvents.forEach(event => {
|
||||
this.video.addEventListener(event, () => {
|
||||
logger.debug(`${event} handler was called for the large video.`);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* A Set of functions to invoke when the video element resizes.
|
||||
*
|
||||
@@ -269,7 +255,6 @@ export class VideoContainer extends LargeContainer {
|
||||
this._resizeListeners = new Set();
|
||||
|
||||
this.video.onresize = this._onResize.bind(this);
|
||||
this._play = this._play.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -470,30 +455,6 @@ export class VideoContainer extends LargeContainer {
|
||||
this._resizeListeners.delete(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays the large video element.
|
||||
*
|
||||
* @param {number} retries - Number of retries to play the large video if play fails.
|
||||
* @returns {void}
|
||||
*/
|
||||
_play(retries = 0) {
|
||||
this.video.play()
|
||||
.then(() => {
|
||||
logger.debug(`Successfully played large video after ${retries + 1} retries!`);
|
||||
})
|
||||
.catch(e => {
|
||||
if (retries < 3) {
|
||||
logger.debug(`Error while trying to playing the large video. Will retry after 1s. Retries: ${
|
||||
retries}. Error: ${e}`);
|
||||
window.setTimeout(() => {
|
||||
this._play(retries + 1);
|
||||
}, 1000);
|
||||
} else {
|
||||
logger.error(`Error while trying to playing the large video after 3 retries: ${e}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update video stream.
|
||||
* @param {string} userID
|
||||
@@ -503,8 +464,6 @@ export class VideoContainer extends LargeContainer {
|
||||
setStream(userID, stream, videoType) {
|
||||
this.userId = userID;
|
||||
if (this.stream === stream && !stream?.forceStreamToReattach) {
|
||||
logger.debug(`SetStream on the large video for user ${userID} ignored: the stream is not changed!`);
|
||||
|
||||
// Handles the use case for the remote participants when the
|
||||
// videoType is received with delay after turning on/off the
|
||||
// desktop sharing.
|
||||
@@ -529,28 +488,22 @@ export class VideoContainer extends LargeContainer {
|
||||
this.videoType = videoType;
|
||||
|
||||
if (!stream) {
|
||||
logger.debug('SetStream on the large video is called without a stream argument!');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.video) {
|
||||
logger.debug(`Attaching a remote track to the large video for user ${userID}`);
|
||||
stream.attach(this.video).catch(error => {
|
||||
logger.error(`Attaching the remote track ${stream} to large video has failed with `, error);
|
||||
logger.error(`Attaching the remote track ${stream} has failed with `, error);
|
||||
});
|
||||
|
||||
// Ensure large video gets play() called on it when a new stream is attached to it. This is necessary in the
|
||||
// case of Safari as autoplay doesn't kick-in automatically on Safari 15 and newer versions.
|
||||
browser.isWebKitBased() && this._play();
|
||||
browser.isWebKitBased() && this.video.play();
|
||||
|
||||
const flipX = stream.isLocal() && this.localFlipX && !this.isScreenSharing();
|
||||
|
||||
this.video.style.transform = flipX ? 'scaleX(-1)' : 'none';
|
||||
this._updateBackground();
|
||||
} else {
|
||||
logger.debug(`SetStream on the large video won't attach a track for ${
|
||||
userID} because no large video element was found!`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -154,8 +154,6 @@ const VideoLayout = {
|
||||
|
||||
updateLargeVideo(id, forceUpdate, forceStreamToReattach = false) {
|
||||
if (!largeVideo) {
|
||||
logger.debug(`Ignoring large video update with user id ${id}: large video not initialized yet!`);
|
||||
|
||||
return;
|
||||
}
|
||||
const currentContainer = largeVideo.getCurrentContainer();
|
||||
|
||||
1088
package-lock.json
generated
1088
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
22
package.json
22
package.json
@@ -17,13 +17,12 @@
|
||||
"readmeFilename": "README.md",
|
||||
"dependencies": {
|
||||
"@amplitude/react-native": "2.7.0",
|
||||
"@braintree/sanitize-url": "7.0.0",
|
||||
"@emotion/react": "11.10.6",
|
||||
"@emotion/styled": "11.10.6",
|
||||
"@giphy/js-fetch-api": "4.7.1",
|
||||
"@giphy/react-components": "6.8.1",
|
||||
"@giphy/react-native-sdk": "2.3.0",
|
||||
"@jitsi/excalidraw": "https://github.com/jitsi/excalidraw/releases/download/v0.0.17/jitsi-excalidraw-0.0.17.tgz",
|
||||
"@jitsi/excalidraw": "https://github.com/jitsi/excalidraw/releases/download/v0.0.16/jitsi-excalidraw-0.0.16.tgz",
|
||||
"@jitsi/js-utils": "2.2.1",
|
||||
"@jitsi/logger": "2.0.2",
|
||||
"@jitsi/rnnoise-wasm": "0.1.0",
|
||||
@@ -31,6 +30,7 @@
|
||||
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.3.tgz",
|
||||
"@microsoft/microsoft-graph-client": "3.0.1",
|
||||
"@mui/material": "5.12.1",
|
||||
"@mui/styles": "5.12.0",
|
||||
"@react-native-async-storage/async-storage": "1.19.4",
|
||||
"@react-native-community/clipboard": "1.5.1",
|
||||
"@react-native-community/netinfo": "11.1.0",
|
||||
@@ -48,8 +48,7 @@
|
||||
"@vladmandic/human": "2.6.5",
|
||||
"@vladmandic/human-models": "2.5.9",
|
||||
"@xmldom/xmldom": "0.8.7",
|
||||
"abab": "2.0.6",
|
||||
"amplitude-js": "8.21.9",
|
||||
"amplitude-js": "8.2.1",
|
||||
"base64-js": "1.5.1",
|
||||
"bc-css-flags": "3.0.0",
|
||||
"clipboard-copy": "4.0.1",
|
||||
@@ -60,14 +59,14 @@
|
||||
"i18n-iso-countries": "6.8.0",
|
||||
"i18next": "17.0.6",
|
||||
"i18next-browser-languagedetector": "3.0.1",
|
||||
"i18next-http-backend": "2.2.1",
|
||||
"i18next-http-backend": "^2.2.1",
|
||||
"image-capture": "0.4.0",
|
||||
"jquery": "3.6.1",
|
||||
"jquery-i18next": "1.2.1",
|
||||
"js-md5": "0.6.1",
|
||||
"js-sha512": "0.8.0",
|
||||
"jwt-decode": "2.2.0",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1790.0.0+311766e3/lib-jitsi-meet.tgz",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet#release-7762",
|
||||
"lodash": "4.17.21",
|
||||
"moment": "2.29.4",
|
||||
"moment-duration-format": "2.2.2",
|
||||
@@ -106,7 +105,7 @@
|
||||
"react-native-url-polyfill": "2.0.0",
|
||||
"react-native-video": "6.0.0-alpha.11",
|
||||
"react-native-watch-connectivity": "1.1.0",
|
||||
"react-native-webrtc": "118.0.3",
|
||||
"react-native-webrtc": "118.0.0",
|
||||
"react-native-webview": "13.5.1",
|
||||
"react-native-youtube-iframe": "2.3.0",
|
||||
"react-redux": "7.2.9",
|
||||
@@ -117,8 +116,7 @@
|
||||
"redux-thunk": "2.4.1",
|
||||
"seamless-scroll-polyfill": "2.1.8",
|
||||
"semver": "7.5.4",
|
||||
"text-encoding": "0.7.0",
|
||||
"tss-react": "4.9.4",
|
||||
"tss-react": "4.4.4",
|
||||
"util": "0.12.1",
|
||||
"uuid": "8.3.2",
|
||||
"wasm-check": "2.0.1",
|
||||
@@ -132,8 +130,8 @@
|
||||
"@babel/plugin-proposal-export-default-from": "7.22.5",
|
||||
"@babel/preset-env": "7.21.5",
|
||||
"@babel/preset-react": "7.16.0",
|
||||
"@jitsi/eslint-config": "4.1.10",
|
||||
"@types/amplitude-js": "8.16.5",
|
||||
"@jitsi/eslint-config": "4.1.5",
|
||||
"@types/amplitude-js": "8.16.2",
|
||||
"@types/audioworklet": "0.0.29",
|
||||
"@types/dom-screen-wake-lock": "1.0.1",
|
||||
"@types/js-md5": "0.4.3",
|
||||
@@ -164,7 +162,7 @@
|
||||
"css-loader": "6.8.1",
|
||||
"eslint": "8.40.0",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
"eslint-plugin-jsdoc": "46.2.6",
|
||||
"eslint-plugin-jsdoc": "37.0.3",
|
||||
"eslint-plugin-react": "7.32.2",
|
||||
"eslint-plugin-react-native": "4.0.0",
|
||||
"eslint-plugin-typescript-sort-keys": "2.3.0",
|
||||
|
||||
@@ -133,7 +133,7 @@ dependencies {
|
||||
|
||||
if (isNewArchitectureEnabled()) {
|
||||
react {
|
||||
jsRootDir = file("../")
|
||||
jsRootDir = file("../src/")
|
||||
libraryName = "JitsiMeetReactNative"
|
||||
codegenJavaPackageName = "org.jitsi.meet.sdk"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
|
||||
|
||||
@ReactModule(name = JMOngoingConferenceModule.NAME)
|
||||
class JMOngoingConferenceModule
|
||||
extends ReactContextBaseJavaModule {
|
||||
|
||||
public static final String NAME = "JMOngoingConference";
|
||||
|
||||
public JMOngoingConferenceModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void launch() {
|
||||
Context context = getReactApplicationContext();
|
||||
Activity currentActivity = getCurrentActivity();
|
||||
|
||||
JitsiMeetOngoingConferenceService.launch(context, currentActivity);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void abort() {
|
||||
Context context = getReactApplicationContext();
|
||||
|
||||
JitsiMeetOngoingConferenceService.abort(context);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright @ 2019-present 8x8, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* This class implements an Android {@link Service}, a foreground one specifically, and it's
|
||||
* responsible for presenting an ongoing notification when a conference is in progress.
|
||||
* The service will help keep the app running while in the background.
|
||||
*
|
||||
* See: https://developer.android.com/guide/components/services
|
||||
*/
|
||||
public class JitsiMeetOngoingConferenceService extends Service {
|
||||
private static final String TAG = JitsiMeetOngoingConferenceService.class.getSimpleName();
|
||||
|
||||
public static void launch(Context context, Activity currentActivity) {
|
||||
|
||||
RNOngoingNotification.createOngoingConferenceNotificationChannel(currentActivity);
|
||||
|
||||
Intent intent = new Intent(context, JitsiMeetOngoingConferenceService.class);
|
||||
|
||||
ComponentName componentName;
|
||||
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
componentName = context.startForegroundService(intent);
|
||||
} else {
|
||||
componentName = context.startService(intent);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
// Avoid crashing due to ForegroundServiceStartNotAllowedException (API level 31).
|
||||
// See: https://developer.android.com/guide/components/foreground-services#background-start-restrictions
|
||||
JitsiMeetLogger.w(TAG + " Ongoing conference service not started", e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (componentName == null) {
|
||||
JitsiMeetLogger.w(TAG + " Ongoing conference service not started");
|
||||
}
|
||||
}
|
||||
|
||||
public static void abort(Context context) {
|
||||
Intent intent = new Intent(context, JitsiMeetOngoingConferenceService.class);
|
||||
context.stopService(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
Notification notification = RNOngoingNotification.buildOngoingConferenceNotification(this);
|
||||
|
||||
if (notification == null) {
|
||||
stopSelf();
|
||||
JitsiMeetLogger.w(TAG + " Couldn't start service, notification is null");
|
||||
} else {
|
||||
startForeground(RNOngoingNotification.NOTIFICATION_ID, notification);
|
||||
JitsiMeetLogger.i(TAG + " Service started");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ public class JitsiMeetReactNativePackage implements ReactPackage {
|
||||
new AndroidSettingsModule(reactContext),
|
||||
new AppInfoModule(reactContext),
|
||||
new AudioModeModule(reactContext),
|
||||
new JMOngoingConferenceModule(reactContext),
|
||||
new JavaScriptSandboxModule(reactContext),
|
||||
new LocaleDetector(reactContext),
|
||||
new LogBridgeModule(reactContext),
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright @ 2019-present 8x8, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Helper class for creating the ongoing notification which is used with
|
||||
* {@link JitsiMeetOngoingConferenceService}. It allows the user to easily get back to the app
|
||||
* and to hangup from within the notification itself.
|
||||
*/
|
||||
class RNOngoingNotification {
|
||||
private static final String TAG = RNOngoingNotification.class.getSimpleName();
|
||||
|
||||
static final int NOTIFICATION_ID = new Random().nextInt(99999) + 10000;
|
||||
|
||||
static void createOngoingConferenceNotificationChannel(Activity currentActivity) {
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentActivity == null) {
|
||||
JitsiMeetLogger.w(TAG + " Cannot create notification channel: no current context");
|
||||
return;
|
||||
}
|
||||
|
||||
NotificationManager notificationManager
|
||||
= (NotificationManager) currentActivity.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
NotificationChannel channel
|
||||
= notificationManager.getNotificationChannel("JitsiOngoingConferenceChannel");
|
||||
if (channel != null) {
|
||||
// The channel was already created, no need to do it again.
|
||||
return;
|
||||
}
|
||||
|
||||
channel = new NotificationChannel("JitsiOngoingConferenceChannel", currentActivity.getString(R.string.ongoing_notification_channel_name), NotificationManager.IMPORTANCE_DEFAULT);
|
||||
channel.enableLights(false);
|
||||
channel.enableVibration(false);
|
||||
channel.setShowBadge(false);
|
||||
|
||||
notificationManager.createNotificationChannel(channel);
|
||||
}
|
||||
|
||||
static Notification buildOngoingConferenceNotification(Context context) {
|
||||
|
||||
if (context == null) {
|
||||
JitsiMeetLogger.w(TAG + " Cannot create notification: no current context");
|
||||
return null;
|
||||
}
|
||||
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "JitsiOngoingConferenceChannel");
|
||||
|
||||
builder
|
||||
.setCategory(NotificationCompat.CATEGORY_CALL)
|
||||
.setContentTitle(context.getString(R.string.ongoing_notification_title))
|
||||
.setContentText(context.getString(R.string.ongoing_notification_text))
|
||||
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||
.setOngoing(true)
|
||||
.setWhen(System.currentTimeMillis())
|
||||
.setUsesChronometer(true)
|
||||
.setAutoCancel(false)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.setOnlyAlertOnce(true)
|
||||
.setSmallIcon(context.getResources().getIdentifier("ic_notification", "drawable", context.getPackageName()));
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
2493
react-native-sdk/package-lock.json
generated
2493
react-native-sdk/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@jitsi/react-native-sdk",
|
||||
"version": "2.0.2",
|
||||
"version": "0.0.0",
|
||||
"description": "React Native SDK for Jitsi Meet.",
|
||||
"main": "index.tsx",
|
||||
"license": "Apache-2.0",
|
||||
@@ -11,7 +11,7 @@
|
||||
"url": "git+https://github.com/jitsi/jitsi-meet.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jitsi/js-utils": "2.2.1",
|
||||
"@jitsi/js-utils": "2.1.3",
|
||||
"@jitsi/logger": "2.0.2",
|
||||
"@jitsi/rtcstats": "9.5.1",
|
||||
"@react-navigation/bottom-tabs": "6.5.8",
|
||||
@@ -20,7 +20,7 @@
|
||||
"@react-navigation/native": "6.1.7",
|
||||
"@react-navigation/stack": "6.3.17",
|
||||
"@xmldom/xmldom": "0.8.7",
|
||||
"base64-js": "1.5.1",
|
||||
"base64-js": "1.3.1",
|
||||
"grapheme-splitter": "1.0.4",
|
||||
"i18n-iso-countries": "6.8.0",
|
||||
"i18next": "17.0.6",
|
||||
@@ -28,7 +28,7 @@
|
||||
"i18next-http-backend": "^2.2.1",
|
||||
"js-sha512": "0.8.0",
|
||||
"jwt-decode": "2.2.0",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1784.0.0+639ad566/lib-jitsi-meet.tgz",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1687.0.0+cafe30d7/lib-jitsi-meet.tgz",
|
||||
"lodash": "4.17.21",
|
||||
"moment": "2.29.4",
|
||||
"moment-duration-format": "2.2.2",
|
||||
@@ -53,14 +53,12 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@amplitude/react-native": "2.7.0",
|
||||
"@braintree/sanitize-url": "7.0.0",
|
||||
"@giphy/react-native-sdk": "2.3.0",
|
||||
"@react-native/metro-config": "0.72.9",
|
||||
"@react-native-async-storage/async-storage": "1.19.4",
|
||||
"@react-native-async-storage/async-storage": "1.19.3",
|
||||
"@react-native-community/clipboard": "1.5.1",
|
||||
"@react-native-community/netinfo": "11.1.0",
|
||||
"@react-native-community/netinfo": "9.4.1",
|
||||
"@react-native-community/slider": "4.4.3",
|
||||
"@react-native-google-signin/google-signin": "10.1.0",
|
||||
"@react-native-google-signin/google-signin": "10.0.1",
|
||||
"react-native": "*",
|
||||
"react": "*",
|
||||
"react-native-background-timer": "2.4.1",
|
||||
@@ -74,17 +72,16 @@
|
||||
"react-native-pager-view": "6.2.0",
|
||||
"react-native-paper": "5.10.3",
|
||||
"react-native-performance": "5.0.0",
|
||||
"react-native-orientation-locker": "1.6.0",
|
||||
"react-native-orientation-locker": "1.5.0",
|
||||
"react-native-safe-area-context": "4.7.1",
|
||||
"react-native-screens": "3.24.0",
|
||||
"react-native-sound": "0.11.2",
|
||||
"react-native-splash-screen": "3.3.0",
|
||||
"react-native-svg": "13.13.0",
|
||||
"react-native-video": "6.0.0-alpha.11",
|
||||
"react-native-video": "6.0.0-alpha.7",
|
||||
"react-native-watch-connectivity": "1.1.0",
|
||||
"react-native-webrtc": "118.0.2",
|
||||
"react-native-webview": "13.5.1",
|
||||
"text-encoding": "0.7.0"
|
||||
"react-native-webrtc": "111.0.3",
|
||||
"react-native-webview": "13.5.1"
|
||||
},
|
||||
"overrides": {
|
||||
"@xmldom/xmldom": "0.8.7"
|
||||
@@ -99,4 +96,4 @@
|
||||
"keywords": [
|
||||
"react-native"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
7
react-native-sdk/prepare_sdk.js
vendored
7
react-native-sdk/prepare_sdk.js
vendored
@@ -79,13 +79,6 @@ function mergeDependencyVersions() {
|
||||
}
|
||||
}
|
||||
|
||||
// Updates SDK overrides dependencies.
|
||||
for (const key in packageJSON.overrides) {
|
||||
if (SDKPackageJSON.overrides.hasOwnProperty(key)) {
|
||||
SDKPackageJSON.overrides[key] = packageJSON.overrides[key];
|
||||
}
|
||||
}
|
||||
|
||||
const data = JSON.stringify(SDKPackageJSON, null, 4);
|
||||
|
||||
fs.writeFileSync('package.json', data);
|
||||
|
||||
@@ -328,22 +328,6 @@ export function createNetworkInfoEvent({ isOnline, networkType, details }:
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a "not allowed error" event.
|
||||
*
|
||||
* @param {string} reason - The reason for the error.
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createNotAllowedErrorEvent(reason: string) {
|
||||
return {
|
||||
action: 'not.allowed.error',
|
||||
attributes: {
|
||||
reason
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an "offer/answer failure" event.
|
||||
*
|
||||
|
||||
@@ -14,7 +14,7 @@ export default class AmplitudeHandler extends AbstractHandler {
|
||||
/**
|
||||
* Creates new instance of the Amplitude analytics handler.
|
||||
*
|
||||
* @param {Object} options - The amplitude options.
|
||||
* @param {Object} options -
|
||||
* @param {string} options.amplitudeAPPKey - The Amplitude app key required by the Amplitude API.
|
||||
* @param {boolean} options.amplitudeIncludeUTM - Whether to include UTM parameters
|
||||
* in the Amplitude events.
|
||||
@@ -35,12 +35,6 @@ export default class AmplitudeHandler extends AbstractHandler {
|
||||
this._enabled = false;
|
||||
};
|
||||
|
||||
// Forces sending all events on exit (flushing) via sendBeacon
|
||||
const onExitPage = () => {
|
||||
// @ts-ignore
|
||||
amplitude.getInstance().sendEvents();
|
||||
};
|
||||
|
||||
if (navigator.product === 'ReactNative') {
|
||||
amplitude.getInstance().init(amplitudeAPPKey);
|
||||
fixDeviceID(amplitude.getInstance()).then(() => {
|
||||
@@ -56,8 +50,7 @@ export default class AmplitudeHandler extends AbstractHandler {
|
||||
includeReferrer: true,
|
||||
includeUtm,
|
||||
saveParamsReferrerOncePerSession: false,
|
||||
onError,
|
||||
onExitPage
|
||||
onError
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
|
||||
@@ -14,7 +14,7 @@ class GoogleAnalyticsHandler extends AbstractHandler {
|
||||
/**
|
||||
* Creates new instance of the GA analytics handler.
|
||||
*
|
||||
* @param {Object} options - The Google Analytics options.
|
||||
* @param {Object} options -
|
||||
* @param {string} options.googleAnalyticsTrackingId - The GA track id
|
||||
* required by the GA API.
|
||||
*/
|
||||
@@ -34,7 +34,7 @@ class GoogleAnalyticsHandler extends AbstractHandler {
|
||||
/**
|
||||
* Initializes the ga object.
|
||||
*
|
||||
* @param {Object} options - The Google Analytics options.
|
||||
* @param {Object} options -
|
||||
* @param {string} options.googleAnalyticsTrackingId - The GA track id
|
||||
* required by the GA API.
|
||||
* @returns {void}
|
||||
|
||||
@@ -13,7 +13,7 @@ export default class MatomoHandler extends AbstractHandler {
|
||||
/**
|
||||
* Creates new instance of the Matomo handler.
|
||||
*
|
||||
* @param {Object} options - The matomo options.
|
||||
* @param {Object} options -
|
||||
* @param {string} options.matomoEndpoint - The Matomo endpoint.
|
||||
* @param {string} options.matomoSiteID - The site ID.
|
||||
*/
|
||||
@@ -39,7 +39,7 @@ export default class MatomoHandler extends AbstractHandler {
|
||||
/**
|
||||
* Initializes the _paq object.
|
||||
*
|
||||
* @param {Object} options - The matomo options.
|
||||
* @param {Object} options -
|
||||
* @param {string} options.matomoEndpoint - The Matomo endpoint.
|
||||
* @param {string} options.matomoSiteID - The site ID.
|
||||
* @returns {void}
|
||||
|
||||
@@ -3,7 +3,6 @@ import '../authentication/middleware';
|
||||
import '../av-moderation/middleware';
|
||||
import '../base/conference/middleware';
|
||||
import '../base/config/middleware';
|
||||
import '../base/i18n/middleware';
|
||||
import '../base/jwt/middleware';
|
||||
import '../base/known-domains/middleware';
|
||||
import '../base/lastn/middleware';
|
||||
@@ -52,6 +51,5 @@ import '../video-layout/middleware';
|
||||
import '../video-quality/middleware';
|
||||
import '../videosipgw/middleware';
|
||||
import '../visitors/middleware';
|
||||
import '../whiteboard/middleware.any';
|
||||
|
||||
import './middleware';
|
||||
|
||||
@@ -13,6 +13,5 @@ import '../mobile/react-native-sdk/middleware';
|
||||
import '../mobile/watchos/middleware';
|
||||
import '../share-room/middleware';
|
||||
import '../shared-video/middleware';
|
||||
import '../whiteboard/middleware.native';
|
||||
|
||||
import './middlewares.any';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import '../base/app/middleware';
|
||||
import '../base/connection/middleware';
|
||||
import '../base/i18n/middleware';
|
||||
import '../base/devices/middleware';
|
||||
import '../base/media/middleware';
|
||||
import '../dynamic-branding/middleware';
|
||||
@@ -21,6 +22,6 @@ import '../talk-while-muted/middleware';
|
||||
import '../toolbox/middleware';
|
||||
import '../face-landmarks/middleware';
|
||||
import '../gifs/middleware';
|
||||
import '../whiteboard/middleware.web';
|
||||
import '../whiteboard/middleware';
|
||||
|
||||
import './middlewares.any';
|
||||
|
||||
@@ -55,4 +55,3 @@ import '../video-layout/reducer';
|
||||
import '../video-quality/reducer';
|
||||
import '../videosipgw/reducer';
|
||||
import '../visitors/reducer';
|
||||
import '../whiteboard/reducer';
|
||||
|
||||
@@ -16,6 +16,7 @@ import '../noise-suppression/reducer';
|
||||
import '../screenshot-capture/reducer';
|
||||
import '../talk-while-muted/reducer';
|
||||
import '../virtual-background/reducer';
|
||||
import '../whiteboard/reducer';
|
||||
import '../web-hid/reducer';
|
||||
|
||||
import './reducers.any';
|
||||
|
||||
@@ -133,7 +133,7 @@ function _upgradeRoleStarted(thenableWithCancel: Object) {
|
||||
* Hides an authentication dialog where the local participant
|
||||
* should authenticate.
|
||||
*
|
||||
* @returns {Function}
|
||||
* @returns {Function}.
|
||||
*/
|
||||
export function hideLoginDialog() {
|
||||
return hideDialog(LoginDialog);
|
||||
|
||||
@@ -18,7 +18,7 @@ interface IProps {
|
||||
* Implements the dialog that warns the user that the login will leave the conference.
|
||||
*
|
||||
* @param {Object} props - The props of the component.
|
||||
* @returns {React$Element}
|
||||
* @returns {React$Element}.
|
||||
*/
|
||||
const LoginQuestionDialog = ({ handler }: IProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -178,18 +178,6 @@ export const DATA_CHANNEL_OPENED = 'DATA_CHANNEL_OPENED';
|
||||
*/
|
||||
export const DATA_CHANNEL_CLOSED = 'DATA_CHANNEL_CLOSED';
|
||||
|
||||
/**
|
||||
* The type of (redux) action which indicates that an endpoint message
|
||||
* sent by another participant to the data channel is received.
|
||||
*
|
||||
* {
|
||||
* type: ENDPOINT_MESSAGE_RECEIVED,
|
||||
* participant: Object,
|
||||
* data: Object
|
||||
* }
|
||||
*/
|
||||
export const ENDPOINT_MESSAGE_RECEIVED = 'ENDPOINT_MESSAGE_RECEIVED';
|
||||
|
||||
/**
|
||||
* The type of action which signals that the user has been kicked out from
|
||||
* the conference.
|
||||
@@ -345,13 +333,3 @@ export const SET_START_MUTED_POLICY = 'SET_START_MUTED_POLICY';
|
||||
* }
|
||||
*/
|
||||
export const SET_ASSUMED_BANDWIDTH_BPS = 'SET_ASSUMED_BANDWIDTH_BPS';
|
||||
|
||||
/**
|
||||
* The type of (redux) action which updated the conference metadata.
|
||||
*
|
||||
* {
|
||||
* type: UPDATE_CONFERENCE_METADATA,
|
||||
* metadata: Object
|
||||
* }
|
||||
*/
|
||||
export const UPDATE_CONFERENCE_METADATA = 'UPDATE_CONFERENCE_METADATA';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { createStartMutedConfigurationEvent } from '../../analytics/AnalyticsEvents';
|
||||
import { sendAnalytics } from '../../analytics/functions';
|
||||
import { IReduxState, IStore } from '../../app/types';
|
||||
import { endpointMessageReceived } from '../../subtitles/actions.any';
|
||||
import { setIAmVisitor } from '../../visitors/actions';
|
||||
import { iAmVisitor } from '../../visitors/functions';
|
||||
import { overwriteConfig } from '../config/actions';
|
||||
@@ -8,15 +9,8 @@ import { getReplaceParticipant } from '../config/functions';
|
||||
import { connect, disconnect, hangup } from '../connection/actions';
|
||||
import { JITSI_CONNECTION_CONFERENCE_KEY } from '../connection/constants';
|
||||
import { JitsiConferenceEvents, JitsiE2ePingEvents } from '../lib-jitsi-meet';
|
||||
import {
|
||||
gumPending,
|
||||
setAudioMuted,
|
||||
setAudioUnmutePermissions,
|
||||
setVideoMuted,
|
||||
setVideoUnmutePermissions
|
||||
} from '../media/actions';
|
||||
import { setAudioMuted, setAudioUnmutePermissions, setVideoMuted, setVideoUnmutePermissions } from '../media/actions';
|
||||
import { MEDIA_TYPE } from '../media/constants';
|
||||
import { IGUMPendingState } from '../media/types';
|
||||
import {
|
||||
dominantSpeakerChanged,
|
||||
participantKicked,
|
||||
@@ -54,7 +48,6 @@ import {
|
||||
DATA_CHANNEL_CLOSED,
|
||||
DATA_CHANNEL_OPENED,
|
||||
E2E_RTT_CHANGED,
|
||||
ENDPOINT_MESSAGE_RECEIVED,
|
||||
KICKED_OUT,
|
||||
LOCK_STATE_CHANGED,
|
||||
NON_PARTICIPANT_MESSAGE_RECEIVED,
|
||||
@@ -68,8 +61,7 @@ import {
|
||||
SET_PENDING_SUBJECT_CHANGE,
|
||||
SET_ROOM,
|
||||
SET_START_MUTED_POLICY,
|
||||
SET_START_REACTIONS_MUTED,
|
||||
UPDATE_CONFERENCE_METADATA
|
||||
SET_START_REACTIONS_MUTED
|
||||
} from './actionTypes';
|
||||
import {
|
||||
AVATAR_URL_COMMAND,
|
||||
@@ -87,7 +79,7 @@ import {
|
||||
sendLocalParticipant
|
||||
} from './functions';
|
||||
import logger from './logger';
|
||||
import { IConferenceMetadata, IJitsiConference } from './reducer';
|
||||
import { IJitsiConference } from './reducer';
|
||||
|
||||
/**
|
||||
* Adds conference (event) listeners.
|
||||
@@ -283,21 +275,6 @@ function _addConferenceListeners(conference: IJitsiConference, dispatch: IStore[
|
||||
})));
|
||||
}
|
||||
|
||||
/**
|
||||
* Action for updating the conference metadata.
|
||||
*
|
||||
* @param {IConferenceMetadata} metadata - The metadata object.
|
||||
* @returns {{
|
||||
* type: UPDATE_CONFERENCE_METADATA,
|
||||
* metadata: IConferenceMetadata
|
||||
* }}
|
||||
*/
|
||||
export function updateConferenceMetadata(metadata: IConferenceMetadata | null) {
|
||||
return {
|
||||
type: UPDATE_CONFERENCE_METADATA,
|
||||
metadata
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an action for when the end-to-end RTT against a specific remote participant has changed.
|
||||
@@ -653,25 +630,6 @@ export function dataChannelClosed(code: number, reason: string) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals that a participant sent an endpoint message on the data channel.
|
||||
*
|
||||
* @param {Object} participant - The participant details sending the message.
|
||||
* @param {Object} data - The data carried by the endpoint message.
|
||||
* @returns {{
|
||||
* type: ENDPOINT_MESSAGE_RECEIVED,
|
||||
* participant: Object,
|
||||
* data: Object
|
||||
* }}
|
||||
*/
|
||||
export function endpointMessageReceived(participant: Object, data: Object) {
|
||||
return {
|
||||
type: ENDPOINT_MESSAGE_RECEIVED,
|
||||
participant,
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to end a conference for all participants.
|
||||
*
|
||||
@@ -1059,11 +1017,6 @@ export function redirect(vnode: string, focusJid: string, username: string) {
|
||||
.then(() => dispatch(conferenceWillInit()))
|
||||
.then(() => dispatch(connect()))
|
||||
.then(() => {
|
||||
|
||||
// Clear the gum pending state in case we have set it to pending since we are starting the
|
||||
// conference without tracks.
|
||||
dispatch(gumPending([ MEDIA_TYPE.AUDIO, MEDIA_TYPE.VIDEO ], IGUMPendingState.NONE));
|
||||
|
||||
// FIXME: Workaround for the web version. To be removed once we get rid of conference.js
|
||||
if (typeof APP !== 'undefined') {
|
||||
APP.conference.startConference([]);
|
||||
|
||||
@@ -6,7 +6,6 @@ import { MIN_ASSUMED_BANDWIDTH_BPS } from '../../../../modules/API/constants';
|
||||
import {
|
||||
ACTION_PINNED,
|
||||
ACTION_UNPINNED,
|
||||
createNotAllowedErrorEvent,
|
||||
createOfferAnswerFailedEvent,
|
||||
createPinnedEvent
|
||||
} from '../../analytics/AnalyticsEvents';
|
||||
@@ -26,7 +25,7 @@ import { overwriteConfig } from '../config/actions';
|
||||
import { CONNECTION_ESTABLISHED, CONNECTION_FAILED } from '../connection/actionTypes';
|
||||
import { connect, connectionDisconnected, disconnect } from '../connection/actions';
|
||||
import { validateJwt } from '../jwt/functions';
|
||||
import { JitsiConferenceErrors, JitsiConferenceEvents, JitsiConnectionErrors } from '../lib-jitsi-meet';
|
||||
import { JitsiConferenceErrors, JitsiConnectionErrors } from '../lib-jitsi-meet';
|
||||
import { PARTICIPANT_UPDATED, PIN_PARTICIPANT } from '../participants/actionTypes';
|
||||
import { PARTICIPANT_ROLE } from '../participants/constants';
|
||||
import {
|
||||
@@ -35,7 +34,6 @@ import {
|
||||
getPinnedParticipant
|
||||
} from '../participants/functions';
|
||||
import MiddlewareRegistry from '../redux/MiddlewareRegistry';
|
||||
import StateListenerRegistry from '../redux/StateListenerRegistry';
|
||||
import { TRACK_ADDED, TRACK_REMOVED } from '../tracks/actionTypes';
|
||||
import { getLocalTracks } from '../tracks/functions.any';
|
||||
|
||||
@@ -56,8 +54,7 @@ import {
|
||||
conferenceWillLeave,
|
||||
createConference,
|
||||
setLocalSubject,
|
||||
setSubject,
|
||||
updateConferenceMetadata
|
||||
setSubject
|
||||
} from './actions';
|
||||
import { CONFERENCE_LEAVE_REASONS } from './constants';
|
||||
import {
|
||||
@@ -68,7 +65,6 @@ import {
|
||||
restoreConferenceOptions
|
||||
} from './functions';
|
||||
import logger from './logger';
|
||||
import { IConferenceMetadata } from './reducer';
|
||||
|
||||
/**
|
||||
* Handler for before unload event.
|
||||
@@ -128,24 +124,6 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
return next(action);
|
||||
});
|
||||
|
||||
/**
|
||||
* Set up state change listener to perform maintenance tasks when the conference
|
||||
* is left or failed.
|
||||
*/
|
||||
StateListenerRegistry.register(
|
||||
state => getCurrentConference(state),
|
||||
(conference, { dispatch }, previousConference): void => {
|
||||
if (conference && !previousConference) {
|
||||
conference.on(JitsiConferenceEvents.METADATA_UPDATED, (metadata: IConferenceMetadata) => {
|
||||
dispatch(updateConferenceMetadata(metadata));
|
||||
});
|
||||
}
|
||||
|
||||
if (conference !== previousConference) {
|
||||
dispatch(updateConferenceMetadata(null));
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Makes sure to leave a failed conference in order to release any allocated
|
||||
* resources like peer connections, emit participant left events, etc.
|
||||
@@ -219,12 +197,6 @@ function _conferenceFailed({ dispatch, getState }: IStore, next: Function, actio
|
||||
|
||||
break;
|
||||
}
|
||||
case JitsiConferenceErrors.NOT_ALLOWED_ERROR: {
|
||||
const [ msg ] = error.params;
|
||||
|
||||
sendAnalytics(createNotAllowedErrorEvent(msg));
|
||||
break;
|
||||
}
|
||||
case JitsiConferenceErrors.OFFER_ANSWER_FAILED:
|
||||
sendAnalytics(createOfferAnswerFailedEvent());
|
||||
break;
|
||||
@@ -400,7 +372,7 @@ function _connectionFailed({ dispatch, getState }: IStore, next: Function, actio
|
||||
descriptionKey: errors ? 'dialog.tokenAuthFailedWithReasons' : 'dialog.tokenAuthFailed',
|
||||
descriptionArguments: { reason: errors },
|
||||
titleKey: 'dialog.tokenAuthFailedTitle'
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.STICKY));
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.LONG));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,8 +27,7 @@ import {
|
||||
SET_PENDING_SUBJECT_CHANGE,
|
||||
SET_ROOM,
|
||||
SET_START_MUTED_POLICY,
|
||||
SET_START_REACTIONS_MUTED,
|
||||
UPDATE_CONFERENCE_METADATA
|
||||
SET_START_REACTIONS_MUTED
|
||||
} from './actionTypes';
|
||||
import { isRoomValid } from './functions';
|
||||
|
||||
@@ -40,23 +39,10 @@ const DEFAULT_STATE = {
|
||||
leaving: undefined,
|
||||
locked: undefined,
|
||||
membersOnly: undefined,
|
||||
metadata: undefined,
|
||||
password: undefined,
|
||||
passwordRequired: undefined
|
||||
};
|
||||
|
||||
export interface IConferenceMetadata {
|
||||
recording?: {
|
||||
isTranscribingEnabled: boolean;
|
||||
};
|
||||
whiteboard?: {
|
||||
collabDetails: {
|
||||
roomId: string;
|
||||
roomKey: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface IJitsiConference {
|
||||
addCommandListener: Function;
|
||||
addLobbyMessageListener: Function;
|
||||
@@ -155,7 +141,6 @@ export interface IConferenceState {
|
||||
localSubject?: string;
|
||||
locked?: string;
|
||||
membersOnly?: IJitsiConference;
|
||||
metadata?: IConferenceMetadata;
|
||||
obfuscatedRoom?: string;
|
||||
obfuscatedRoomSource?: string;
|
||||
p2p?: Object;
|
||||
@@ -262,12 +247,6 @@ ReducerRegistry.register<IConferenceState>('features/base/conference',
|
||||
startAudioMutedPolicy: action.startAudioMutedPolicy,
|
||||
startVideoMutedPolicy: action.startVideoMutedPolicy
|
||||
};
|
||||
|
||||
case UPDATE_CONFERENCE_METADATA:
|
||||
return {
|
||||
...state,
|
||||
metadata: action.metadata
|
||||
};
|
||||
}
|
||||
|
||||
return state;
|
||||
@@ -596,10 +575,7 @@ function _setRoom(state: IConferenceState, action: AnyAction) {
|
||||
*/
|
||||
return assign(state, {
|
||||
error: undefined,
|
||||
localSubject: undefined,
|
||||
pendingSubjectChange: undefined,
|
||||
room,
|
||||
subject: undefined
|
||||
room
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,40 @@
|
||||
import { ToolbarButton } from '../../toolbox/types';
|
||||
export type ToolbarButton = 'camera' |
|
||||
'chat' |
|
||||
'closedcaptions' |
|
||||
'desktop' |
|
||||
'download' |
|
||||
'embedmeeting' |
|
||||
'etherpad' |
|
||||
'feedback' |
|
||||
'filmstrip' |
|
||||
'fullscreen' |
|
||||
'hangup' |
|
||||
'help' |
|
||||
'highlight' |
|
||||
'invite' |
|
||||
'linktosalesforce' |
|
||||
'livestreaming' |
|
||||
'microphone' |
|
||||
'mute-everyone' |
|
||||
'mute-video-everyone' |
|
||||
'noisesuppression' |
|
||||
'participants-pane' |
|
||||
'profile' |
|
||||
'raisehand' |
|
||||
'reactions' |
|
||||
'recording' |
|
||||
'security' |
|
||||
'select-background' |
|
||||
'settings' |
|
||||
'shareaudio' |
|
||||
'sharedvideo' |
|
||||
'shortcuts' |
|
||||
'stats' |
|
||||
'tileview' |
|
||||
'toggle-camera' |
|
||||
'videoquality' |
|
||||
'whiteboard' |
|
||||
'__end';
|
||||
|
||||
type ButtonsWithNotifyClick = 'camera' |
|
||||
'chat' |
|
||||
@@ -105,14 +141,7 @@ export interface IDeeplinkingMobileConfig extends IDeeplinkingPlatformConfig {
|
||||
fDroidUrl?: string;
|
||||
}
|
||||
|
||||
export interface IDesktopDownloadConfig {
|
||||
linux?: string;
|
||||
macos?: string;
|
||||
windows?: string;
|
||||
}
|
||||
|
||||
export interface IDeeplinkingDesktopConfig extends IDeeplinkingPlatformConfig {
|
||||
download?: IDesktopDownloadConfig;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
@@ -467,7 +496,6 @@ export interface IConfig {
|
||||
preventExecution: boolean;
|
||||
}>;
|
||||
participantsPane?: {
|
||||
enabled?: boolean;
|
||||
hideModeratorSettingsTab?: boolean;
|
||||
hideMoreActionsButton?: boolean;
|
||||
hideMuteAllButton?: boolean;
|
||||
@@ -496,12 +524,9 @@ export interface IConfig {
|
||||
};
|
||||
recordingSharingUrl?: string;
|
||||
recordings?: {
|
||||
recordAudioAndVideo?: boolean;
|
||||
showPrejoinWarning?: boolean;
|
||||
suggestRecording?: boolean;
|
||||
};
|
||||
remoteVideoMenu?: {
|
||||
disableDemote?: boolean;
|
||||
disableGrantModerator?: boolean;
|
||||
disableKick?: boolean;
|
||||
disablePrivateChat?: boolean;
|
||||
@@ -541,7 +566,6 @@ export interface IConfig {
|
||||
testing?: {
|
||||
assumeBandwidth?: boolean;
|
||||
disableE2EE?: boolean;
|
||||
dumpTranscript?: boolean;
|
||||
mobileXmppWsThreshold?: number;
|
||||
noAutoPlayVideo?: boolean;
|
||||
p2pTestMode?: boolean;
|
||||
@@ -566,6 +590,7 @@ export interface IConfig {
|
||||
transcribingEnabled?: boolean;
|
||||
transcription?: {
|
||||
autoTranscribeOnRecord?: boolean;
|
||||
disableStartForAll?: boolean;
|
||||
enabled?: boolean;
|
||||
preferredLanguage?: string;
|
||||
translationLanguages?: Array<string>;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ToolbarButton } from './configType';
|
||||
|
||||
/**
|
||||
* The prefix of the {@code localStorage} key into which {@link storeConfig}
|
||||
* stores and from which {@link restoreConfig} restores.
|
||||
@@ -7,6 +9,50 @@
|
||||
*/
|
||||
export const _CONFIG_STORE_PREFIX = 'config.js';
|
||||
|
||||
/**
|
||||
* The list of all possible UI buttons.
|
||||
*
|
||||
* @protected
|
||||
* @type Array<string>
|
||||
*/
|
||||
export const TOOLBAR_BUTTONS: ToolbarButton[] = [
|
||||
'camera',
|
||||
'chat',
|
||||
'closedcaptions',
|
||||
'desktop',
|
||||
'download',
|
||||
'embedmeeting',
|
||||
'etherpad',
|
||||
'feedback',
|
||||
'filmstrip',
|
||||
'fullscreen',
|
||||
'hangup',
|
||||
'help',
|
||||
'highlight',
|
||||
'invite',
|
||||
'linktosalesforce',
|
||||
'livestreaming',
|
||||
'microphone',
|
||||
'mute-everyone',
|
||||
'mute-video-everyone',
|
||||
'participants-pane',
|
||||
'profile',
|
||||
'raisehand',
|
||||
'recording',
|
||||
'security',
|
||||
'select-background',
|
||||
'settings',
|
||||
'shareaudio',
|
||||
'noisesuppression',
|
||||
'sharedvideo',
|
||||
'shortcuts',
|
||||
'stats',
|
||||
'tileview',
|
||||
'toggle-camera',
|
||||
'videoquality',
|
||||
'whiteboard'
|
||||
];
|
||||
|
||||
/**
|
||||
* The toolbar buttons to show on premeeting screens.
|
||||
*/
|
||||
@@ -17,6 +63,11 @@ export const PREMEETING_BUTTONS = [ 'microphone', 'camera', 'select-background',
|
||||
*/
|
||||
export const THIRD_PARTY_PREJOIN_BUTTONS = [ 'microphone', 'camera', 'select-background' ];
|
||||
|
||||
/**
|
||||
* The toolbar buttons to show when in visitors mode.
|
||||
*/
|
||||
export const VISITORS_MODE_BUTTONS = [ 'chat', 'hangup', 'raisehand', 'settings', 'tileview' ];
|
||||
|
||||
/**
|
||||
* The set of feature flags.
|
||||
*
|
||||
|
||||
@@ -65,7 +65,7 @@ export function getMeetingRegion(state: IReduxState) {
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function getSsrcRewritingFeatureFlag(state: IReduxState) {
|
||||
return getFeatureFlag(state, FEATURE_FLAGS.SSRC_REWRITING) ?? true;
|
||||
return getFeatureFlag(state, FEATURE_FLAGS.SSRC_REWRITING);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,8 +7,10 @@ import {
|
||||
IDeeplinkingConfig,
|
||||
IDeeplinkingDesktopConfig,
|
||||
IDeeplinkingMobileConfig,
|
||||
NotifyClickButton
|
||||
NotifyClickButton,
|
||||
ToolbarButton
|
||||
} from './configType';
|
||||
import { TOOLBAR_BUTTONS } from './constants';
|
||||
|
||||
export * from './functions.any';
|
||||
|
||||
@@ -32,6 +34,25 @@ export function getReplaceParticipant(state: IReduxState): string | undefined {
|
||||
return state['features/base/config'].replaceParticipant;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of enabled toolbar buttons.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @returns {Array<string>} - The list of enabled toolbar buttons.
|
||||
*/
|
||||
export function getToolbarButtons(state: IReduxState): Array<string> {
|
||||
const { toolbarButtons, customToolbarButtons } = state['features/base/config'];
|
||||
const customButtons = customToolbarButtons?.map(({ id }) => id);
|
||||
|
||||
const buttons = Array.isArray(toolbarButtons) ? toolbarButtons : TOOLBAR_BUTTONS;
|
||||
|
||||
if (customButtons) {
|
||||
buttons.push(...customButtons as ToolbarButton[]);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configuration value of web-hid feature.
|
||||
*
|
||||
@@ -42,6 +63,20 @@ export function getWebHIDFeatureConfig(state: IReduxState): boolean {
|
||||
return state['features/base/config'].enableWebHIDFeature || false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified button is enabled.
|
||||
*
|
||||
* @param {string} buttonName - The name of the button.
|
||||
* {@link interfaceConfig}.
|
||||
* @param {Object|Array<string>} state - The redux state or the array with the enabled buttons.
|
||||
* @returns {boolean} - True if the button is enabled and false otherwise.
|
||||
*/
|
||||
export function isToolbarButtonEnabled(buttonName: string, state: IReduxState | Array<string>) {
|
||||
const buttons = Array.isArray(state) ? state : getToolbarButtons(state);
|
||||
|
||||
return buttons.includes(buttonName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether audio level measurement is enabled or not.
|
||||
*
|
||||
@@ -59,21 +94,14 @@ export function areAudioLevelsEnabled(state: IReduxState): boolean {
|
||||
* @returns {void}
|
||||
*/
|
||||
export function _setDeeplinkingDefaults(deeplinking: IDeeplinkingConfig) {
|
||||
deeplinking.desktop = deeplinking.desktop || {} as IDeeplinkingDesktopConfig;
|
||||
deeplinking.android = deeplinking.android || {} as IDeeplinkingMobileConfig;
|
||||
deeplinking.ios = deeplinking.ios || {} as IDeeplinkingMobileConfig;
|
||||
|
||||
const { android, desktop, ios } = deeplinking;
|
||||
const {
|
||||
desktop = {} as IDeeplinkingDesktopConfig,
|
||||
android = {} as IDeeplinkingMobileConfig,
|
||||
ios = {} as IDeeplinkingMobileConfig
|
||||
} = deeplinking;
|
||||
|
||||
desktop.appName = desktop.appName || 'Jitsi Meet';
|
||||
desktop.appScheme = desktop.appScheme || 'jitsi-meet';
|
||||
desktop.download = desktop.download || {};
|
||||
desktop.download.windows = desktop.download.windows
|
||||
|| 'https://github.com/jitsi/jitsi-meet-electron/releases/latest/download/jitsi-meet.exe';
|
||||
desktop.download.macos = desktop.download.macos
|
||||
|| 'https://github.com/jitsi/jitsi-meet-electron/releases/latest/download/jitsi-meet.dmg';
|
||||
desktop.download.linux = desktop.download.linux
|
||||
|| 'https://github.com/jitsi/jitsi-meet-electron/releases/latest/download/jitsi-meet-x86_64.AppImage';
|
||||
|
||||
ios.appName = ios.appName || 'Jitsi Meet';
|
||||
ios.appScheme = ios.appScheme || 'org.jitsi.meet';
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
import { CONFERENCE_INFO } from '../../conference/components/constants';
|
||||
import { TOOLBAR_BUTTONS } from '../../toolbox/constants';
|
||||
import { ToolbarButton } from '../../toolbox/types';
|
||||
import ReducerRegistry from '../redux/ReducerRegistry';
|
||||
import { equals } from '../redux/functions';
|
||||
|
||||
@@ -18,8 +16,10 @@ import {
|
||||
IDeeplinkingConfig,
|
||||
IDeeplinkingDesktopConfig,
|
||||
IDeeplinkingMobileConfig,
|
||||
IMobileDynamicLink
|
||||
IMobileDynamicLink,
|
||||
ToolbarButton
|
||||
} from './configType';
|
||||
import { TOOLBAR_BUTTONS } from './constants';
|
||||
import { _cleanupConfig, _setDeeplinkingDefaults } from './functions';
|
||||
|
||||
/**
|
||||
|
||||
@@ -52,16 +52,6 @@ export const CONNECTION_WILL_CONNECT = 'CONNECTION_WILL_CONNECT';
|
||||
*/
|
||||
export const SET_LOCATION_URL = 'SET_LOCATION_URL';
|
||||
|
||||
/**
|
||||
* The type of (redux) action which sets the preferVisitor in store.
|
||||
*
|
||||
* {
|
||||
* type: SET_PREFER_VISITOR,
|
||||
* preferVisitor: ?boolean
|
||||
* }
|
||||
*/
|
||||
export const SET_PREFER_VISITOR = 'SET_PREFER_VISITOR';
|
||||
|
||||
/**
|
||||
* The type of (redux) action which tells whether connection info should be displayed
|
||||
* on context menu.
|
||||
|
||||
@@ -16,8 +16,7 @@ import {
|
||||
CONNECTION_ESTABLISHED,
|
||||
CONNECTION_FAILED,
|
||||
CONNECTION_WILL_CONNECT,
|
||||
SET_LOCATION_URL,
|
||||
SET_PREFER_VISITOR
|
||||
SET_LOCATION_URL
|
||||
} from './actionTypes';
|
||||
import { JITSI_CONNECTION_URL_KEY } from './constants';
|
||||
import logger from './logger';
|
||||
@@ -181,22 +180,6 @@ export function setLocationURL(locationURL?: URL) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* To change prefer visitor in the store. Used later to decide what to request from jicofo on connection.
|
||||
*
|
||||
* @param {boolean} preferVisitor - The value to set.
|
||||
* @returns {{
|
||||
* type: SET_PREFER_VISITOR,
|
||||
* preferVisitor: boolean
|
||||
* }}
|
||||
*/
|
||||
export function setPreferVisitor(preferVisitor: boolean) {
|
||||
return {
|
||||
type: SET_PREFER_VISITOR,
|
||||
preferVisitor
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens new connection.
|
||||
*
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
CONNECTION_FAILED,
|
||||
CONNECTION_WILL_CONNECT,
|
||||
SET_LOCATION_URL,
|
||||
SET_PREFER_VISITOR,
|
||||
SHOW_CONNECTION_INFO
|
||||
} from './actionTypes';
|
||||
import { ConnectionFailedError } from './types';
|
||||
@@ -58,11 +57,6 @@ ReducerRegistry.register<IConnectionState>(
|
||||
case SET_LOCATION_URL:
|
||||
return _setLocationURL(state, action);
|
||||
|
||||
case SET_PREFER_VISITOR:
|
||||
return assign(state, {
|
||||
preferVisitor: action.preferVisitor
|
||||
});
|
||||
|
||||
case SET_ROOM:
|
||||
return _setRoom(state);
|
||||
|
||||
|
||||
@@ -164,12 +164,6 @@ export const NOTIFICATIONS_ENABLED = 'notifications.enabled';
|
||||
*/
|
||||
export const OVERFLOW_MENU_ENABLED = 'overflow-menu.enabled';
|
||||
|
||||
/**
|
||||
* Flag indicating if participants should be enabled.
|
||||
* Default: enabled (true).
|
||||
*/
|
||||
export const PARTICIPANTS_ENABLED = 'participants.enabled';
|
||||
|
||||
/**
|
||||
* Flag indicating if Picture-in-Picture should be enabled.
|
||||
* Default: auto-detected.
|
||||
|
||||
@@ -8,7 +8,7 @@ import { toState } from '../../redux/functions';
|
||||
* @param {(Function|Object)} stateful - The (whole) redux state, or redux's
|
||||
* {@code getState} function to be used to retrieve the state
|
||||
* features/base/config.
|
||||
* @returns {number}
|
||||
* @returns {number}.
|
||||
*/
|
||||
export function getClientWidth(stateful: IStateful) {
|
||||
const state = toState(stateful)['features/base/responsive-ui'];
|
||||
@@ -23,7 +23,7 @@ export function getClientWidth(stateful: IStateful) {
|
||||
* @param {(Function|Object)} stateful - The (whole) redux state, or redux's
|
||||
* {@code getState} function to be used to retrieve the state
|
||||
* features/base/config.
|
||||
* @returns {number}
|
||||
* @returns {number}.
|
||||
*/
|
||||
export function getClientHeight(stateful: IStateful) {
|
||||
const state = toState(stateful)['features/base/responsive-ui'];
|
||||
|
||||
@@ -683,7 +683,7 @@ function _participantJoinedOrUpdated(store: IStore, next: Function, action: AnyA
|
||||
|
||||
// Only run this if the config is populated, otherwise we preload external resources
|
||||
// even if disableThirdPartyRequests is set to true in config
|
||||
if (getState()['features/base/config']?.hosts) {
|
||||
if (Object.keys(getState()['features/base/config']).length) {
|
||||
const { disableThirdPartyRequests } = getState()['features/base/config'];
|
||||
|
||||
if (!disableThirdPartyRequests && (avatarURL || email || id || name)) {
|
||||
|
||||
@@ -5,16 +5,14 @@ import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { IReduxState } from '../../../../app/types';
|
||||
import DeviceStatus from '../../../../prejoin/components/web/preview/DeviceStatus';
|
||||
import { isRoomNameEnabled } from '../../../../prejoin/functions';
|
||||
import Toolbox from '../../../../toolbox/components/web/Toolbox';
|
||||
import { isButtonEnabled } from '../../../../toolbox/functions.web';
|
||||
import { getConferenceName } from '../../../conference/functions';
|
||||
import { PREMEETING_BUTTONS, THIRD_PARTY_PREJOIN_BUTTONS } from '../../../config/constants';
|
||||
import { getToolbarButtons, isToolbarButtonEnabled } from '../../../config/functions.web';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
|
||||
import ConnectionStatus from './ConnectionStatus';
|
||||
import Preview from './Preview';
|
||||
import RecordingWarning from './RecordingWarning';
|
||||
import UnsafeRoomWarning from './UnsafeRoomWarning';
|
||||
|
||||
interface IProps {
|
||||
@@ -59,11 +57,6 @@ interface IProps {
|
||||
*/
|
||||
showDeviceStatus: boolean;
|
||||
|
||||
/**
|
||||
* Indicates whether to display the recording warning.
|
||||
*/
|
||||
showRecordingWarning?: boolean;
|
||||
|
||||
/**
|
||||
* If should show unsafe room warning when joining.
|
||||
*/
|
||||
@@ -174,7 +167,6 @@ const PreMeetingScreen = ({
|
||||
children,
|
||||
className,
|
||||
showDeviceStatus,
|
||||
showRecordingWarning,
|
||||
showUnsafeRoomWarning,
|
||||
skipPrejoinButton,
|
||||
title,
|
||||
@@ -208,7 +200,6 @@ const PreMeetingScreen = ({
|
||||
{skipPrejoinButton}
|
||||
{showUnsafeRoomWarning && <UnsafeRoomWarning />}
|
||||
{showDeviceStatus && <DeviceStatus />}
|
||||
{showRecordingWarning && <RecordingWarning />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -228,8 +219,8 @@ const PreMeetingScreen = ({
|
||||
* @returns {Object}
|
||||
*/
|
||||
function mapStateToProps(state: IReduxState, ownProps: Partial<IProps>) {
|
||||
const { hiddenPremeetingButtons } = state['features/base/config'];
|
||||
const { toolbarButtons } = state['features/toolbox'];
|
||||
const { hiddenPremeetingButtons, hideConferenceSubject } = state['features/base/config'];
|
||||
const toolbarButtons = getToolbarButtons(state);
|
||||
const premeetingButtons = (ownProps.thirdParty
|
||||
? THIRD_PARTY_PREJOIN_BUTTONS
|
||||
: PREMEETING_BUTTONS).filter((b: any) => !(hiddenPremeetingButtons || []).includes(b));
|
||||
@@ -244,9 +235,9 @@ function mapStateToProps(state: IReduxState, ownProps: Partial<IProps>) {
|
||||
// toolbarButtons config overwrite.
|
||||
_buttons: hiddenPremeetingButtons
|
||||
? premeetingButtons
|
||||
: premeetingButtons.filter(b => isButtonEnabled(b, toolbarButtons)),
|
||||
: premeetingButtons.filter(b => isToolbarButtonEnabled(b, toolbarButtons)),
|
||||
_premeetingBackground: premeetingBackground,
|
||||
_roomName: isRoomNameEnabled(state) ? getConferenceName(state) : ''
|
||||
_roomName: (hideConferenceSubject ? undefined : getConferenceName(state)) ?? ''
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
warning: {
|
||||
bottom: 0,
|
||||
color: theme.palette.text03,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
marginBottom: theme.spacing(3),
|
||||
marginTop: theme.spacing(2),
|
||||
paddingLeft: theme.spacing(3),
|
||||
paddingRight: theme.spacing(3),
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
|
||||
'@media (max-width: 720px)': {
|
||||
position: 'relative'
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const RecordingWarning = () => {
|
||||
const { t } = useTranslation();
|
||||
const { classes } = useStyles();
|
||||
|
||||
return (
|
||||
<div className = { classes.warning }>
|
||||
{t('prejoin.recordingWarning')}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default RecordingWarning;
|
||||
@@ -10,8 +10,6 @@ if (userAgent.match(/Android/i)) {
|
||||
OS = 'macos';
|
||||
} else if (userAgent.match(/Windows/i)) {
|
||||
OS = 'windows';
|
||||
} else if (userAgent.match(/Linux/i)) {
|
||||
OS = 'linux';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { NativeModules, Platform } from 'react-native';
|
||||
|
||||
import { IReduxState, IStore } from '../../app/types';
|
||||
import { setPictureInPictureEnabled } from '../../mobile/picture-in-picture/functions';
|
||||
import { showNotification } from '../../notifications/actions';
|
||||
import { NOTIFICATION_TIMEOUT_TYPE } from '../../notifications/constants';
|
||||
import { PIP_WHILE_SCREEN_SHARING_ENABLED } from '../flags/constants';
|
||||
import { getFeatureFlag } from '../flags/functions';
|
||||
import JitsiMeetJS from '../lib-jitsi-meet';
|
||||
import {
|
||||
setScreenshareMuted,
|
||||
@@ -14,6 +14,7 @@ import { VIDEO_MUTISM_AUTHORITY } from '../media/constants';
|
||||
import { addLocalTrack, replaceLocalTrack } from './actions.any';
|
||||
import { getLocalDesktopTrack, getTrackState, isLocalVideoTrackDesktop } from './functions.native';
|
||||
|
||||
const { JitsiMeetMediaProjectionModule } = NativeModules;
|
||||
|
||||
export * from './actions.any';
|
||||
|
||||
@@ -34,7 +35,10 @@ export function toggleScreensharing(enabled: boolean, _ignore1?: boolean, _ignor
|
||||
|
||||
if (!isSharing) {
|
||||
_startScreenSharing(dispatch, state);
|
||||
Platform.OS === 'android' && JitsiMeetMediaProjectionModule.launch();
|
||||
}
|
||||
|
||||
Platform.OS === 'android' && JitsiMeetMediaProjectionModule.abort();
|
||||
} else {
|
||||
dispatch(setScreenshareMuted(true));
|
||||
dispatch(setVideoMuted(false, VIDEO_MUTISM_AUTHORITY.SCREEN_SHARE));
|
||||
@@ -52,11 +56,7 @@ export function toggleScreensharing(enabled: boolean, _ignore1?: boolean, _ignor
|
||||
* @returns {void}
|
||||
*/
|
||||
async function _startScreenSharing(dispatch: IStore['dispatch'], state: IReduxState) {
|
||||
const pipWhileScreenSharingEnabled = getFeatureFlag(state, PIP_WHILE_SCREEN_SHARING_ENABLED, false);
|
||||
|
||||
if (!pipWhileScreenSharingEnabled) {
|
||||
setPictureInPictureEnabled(false);
|
||||
}
|
||||
setPictureInPictureEnabled(false);
|
||||
|
||||
try {
|
||||
const tracks: any[] = await JitsiMeetJS.createLocalTracks({ devices: [ 'desktop' ] });
|
||||
|
||||
@@ -145,24 +145,6 @@ const useStyles = makeStyles()(theme => {
|
||||
pointerEvents: 'none'
|
||||
},
|
||||
|
||||
contextMenuItemIconDisabled: {
|
||||
'& svg': {
|
||||
fill: `${theme.palette.text03} !important`
|
||||
}
|
||||
},
|
||||
|
||||
contextMenuItemLabelDisabled: {
|
||||
color: theme.palette.text03,
|
||||
|
||||
'&:hover': {
|
||||
background: 'none'
|
||||
},
|
||||
|
||||
'& svg': {
|
||||
fill: theme.palette.text03
|
||||
}
|
||||
},
|
||||
|
||||
contextMenuItemDrawer: {
|
||||
padding: '13px 16px'
|
||||
},
|
||||
@@ -251,15 +233,13 @@ const ContextMenuItem = ({
|
||||
tabIndex = { onClick ? tabIndex : undefined }>
|
||||
{customIcon ? customIcon
|
||||
: icon && <Icon
|
||||
className = { cx(styles.contextMenuItemIcon,
|
||||
disabled && styles.contextMenuItemIconDisabled) }
|
||||
className = { styles.contextMenuItemIcon }
|
||||
size = { 20 }
|
||||
src = { icon } />}
|
||||
{text && (
|
||||
<TextWithOverflow
|
||||
className = { cx(styles.text,
|
||||
_overflowDrawer && styles.drawerText,
|
||||
disabled && styles.contextMenuItemLabelDisabled,
|
||||
textClassName) }
|
||||
overflowType = { overflowType } >
|
||||
{text}
|
||||
|
||||
@@ -145,7 +145,7 @@ export function setColorAlpha(color: string, opacity: number) {
|
||||
/**
|
||||
* Gets the hexa rgb values for a shorthand css color.
|
||||
*
|
||||
* @param {string} color - The shorthand css color.
|
||||
* @param {string} color -
|
||||
* @returns {Array<number>} - Array containing parsed r, g, b values of the color.
|
||||
*/
|
||||
function parseShorthandColor(color: string) {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import base64js from 'base64-js';
|
||||
|
||||
import { timeoutPromise } from './timeoutPromise';
|
||||
|
||||
/**
|
||||
@@ -45,37 +43,3 @@ export function doGetJSON(url: string, retry?: boolean, options?: Object) {
|
||||
|
||||
return fetchPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes strings to Base64URL.
|
||||
*
|
||||
* @param {any} data - The byte array to encode.
|
||||
* @returns {string}
|
||||
*/
|
||||
export const encodeToBase64URL = (data: string): string => base64js
|
||||
.fromByteArray(new window.TextEncoder().encode(data))
|
||||
.replace(/=/g, '')
|
||||
.replace(/\+/g, '-')
|
||||
.replace(/\//g, '_');
|
||||
|
||||
/**
|
||||
* Decodes strings from Base64URL.
|
||||
*
|
||||
* @param {string} data - The byte array to decode.
|
||||
* @returns {string}
|
||||
*/
|
||||
export const decodeFromBase64URL = (data: string): string => {
|
||||
let s = data;
|
||||
|
||||
// Convert from Base64URL to Base64.
|
||||
if (s.length % 4 === 2) {
|
||||
s += '==';
|
||||
} else if (s.length % 4 === 3) {
|
||||
s += '=';
|
||||
}
|
||||
|
||||
s = s.replace(/-/g, '+').replace(/_/g, '/');
|
||||
|
||||
// Convert Base64 to a byte array.
|
||||
return new window.TextDecoder().decode(base64js.toByteArray(s));
|
||||
};
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { sanitizeUrl as _sanitizeUrl } from '@braintree/sanitize-url';
|
||||
|
||||
import { parseURLParams } from './parseURLParams';
|
||||
import { normalizeNFKC } from './strings';
|
||||
|
||||
@@ -659,25 +657,3 @@ export function appendURLHashParam(url: string, name: string, value: string) {
|
||||
|
||||
return newUrl.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes the given URL so that it's safe to use. If it's unsafe, null is returned.
|
||||
*
|
||||
* @param {string|URL} url - The URL that needs to be sanitized.
|
||||
*
|
||||
* @returns {URL?} - The sanitized URL, or null otherwise.
|
||||
*/
|
||||
export function sanitizeUrl(url?: string | URL): URL | null {
|
||||
if (!url) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const urlStr = url.toString();
|
||||
const result = _sanitizeUrl(urlStr);
|
||||
|
||||
if (result === 'about:blank') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new URL(result);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import { getFeatureFlag } from '../../../base/flags/functions';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import { IconChatUnread, IconMessage } from '../../../base/icons/svg';
|
||||
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
|
||||
import { arePollsDisabled } from '../../../conference/functions.any';
|
||||
import { navigate } from '../../../mobile/navigation/components/conference/ConferenceNavigationContainerRef';
|
||||
import { screen } from '../../../mobile/navigation/routes';
|
||||
import { getUnreadPollCount } from '../../../polls/functions';
|
||||
@@ -66,10 +65,11 @@ class ChatButton extends AbstractButton<IProps> {
|
||||
*/
|
||||
function _mapStateToProps(state: IReduxState, ownProps: any) {
|
||||
const enabled = getFeatureFlag(state, CHAT_ENABLED, true);
|
||||
const { disablePolls } = state['features/base/config'];
|
||||
const { visible = enabled } = ownProps;
|
||||
|
||||
return {
|
||||
_isPollsDisabled: arePollsDisabled(state),
|
||||
_isPollsDisabled: disablePolls,
|
||||
|
||||
// The toggled icon should also be available for new polls
|
||||
_unreadMessageCount: getUnreadCount(state) || getUnreadPollCount(state),
|
||||
|
||||
@@ -8,7 +8,6 @@ import { IconMessage, IconReply } from '../../../base/icons/svg';
|
||||
import { getParticipantById } from '../../../base/participants/functions';
|
||||
import { IParticipant } from '../../../base/participants/types';
|
||||
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
|
||||
import { arePollsDisabled } from '../../../conference/functions.any';
|
||||
import { navigate } from '../../../mobile/navigation/components/conference/ConferenceNavigationContainerRef';
|
||||
import { screen } from '../../../mobile/navigation/routes';
|
||||
import { handleLobbyChatInitialized, openChat } from '../../actions.native';
|
||||
@@ -97,10 +96,11 @@ class PrivateMessageButton extends AbstractButton<IProps, any> {
|
||||
*/
|
||||
export function _mapStateToProps(state: IReduxState, ownProps: any) {
|
||||
const enabled = getFeatureFlag(state, CHAT_ENABLED, true);
|
||||
const { disablePolls } = state['features/base/config'];
|
||||
const { visible = enabled, isLobbyMessage, participantID } = ownProps;
|
||||
|
||||
return {
|
||||
_isPollsDisabled: arePollsDisabled(state),
|
||||
_isPollsDisabled: disablePolls,
|
||||
_participant: getParticipantById(state, participantID),
|
||||
_isLobbyMessage: isLobbyMessage,
|
||||
visible
|
||||
|
||||
@@ -7,7 +7,6 @@ import { translate } from '../../../base/i18n/functions';
|
||||
import { getLocalParticipant } from '../../../base/participants/functions';
|
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web';
|
||||
import Tabs from '../../../base/ui/components/web/Tabs';
|
||||
import { arePollsDisabled } from '../../../conference/functions.any';
|
||||
import PollsPane from '../../../polls/components/web/PollsPane';
|
||||
import { sendMessage, setIsPollsTabFocused, toggleChat } from '../../actions.web';
|
||||
import { CHAT_SIZE, CHAT_TABS, SMALL_WIDTH_THRESHOLD } from '../../constants';
|
||||
@@ -317,11 +316,12 @@ function _mapStateToProps(state: IReduxState, _ownProps: any) {
|
||||
const { isOpen, isPollsTabFocused, messages, nbUnreadMessages } = state['features/chat'];
|
||||
const { nbUnreadPolls } = state['features/polls'];
|
||||
const _localParticipant = getLocalParticipant(state);
|
||||
const { disablePolls } = state['features/base/config'];
|
||||
|
||||
return {
|
||||
_isModal: window.innerWidth <= SMALL_WIDTH_THRESHOLD,
|
||||
_isOpen: isOpen,
|
||||
_isPollsEnabled: !arePollsDisabled(state),
|
||||
_isPollsEnabled: !disablePolls,
|
||||
_isPollsTabFocused: isPollsTabFocused,
|
||||
_messages: messages,
|
||||
_nbUnreadMessages: nbUnreadMessages,
|
||||
|
||||
@@ -295,7 +295,7 @@ export default class MessageContainer extends AbstractMessageContainer<IProps, I
|
||||
/**
|
||||
* Check if a message is visible in view.
|
||||
*
|
||||
* @param {Element} message - The message.
|
||||
* @param {Element} message -
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@ import { AnyAction } from 'redux';
|
||||
|
||||
import { IReduxState, IStore } from '../app/types';
|
||||
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app/actionTypes';
|
||||
import { CONFERENCE_JOINED, ENDPOINT_MESSAGE_RECEIVED } from '../base/conference/actionTypes';
|
||||
import { CONFERENCE_JOINED } from '../base/conference/actionTypes';
|
||||
import { getCurrentConference } from '../base/conference/functions';
|
||||
import { IJitsiConference } from '../base/conference/reducer';
|
||||
import { openDialog } from '../base/dialog/actions';
|
||||
@@ -29,6 +29,7 @@ import { ADD_REACTION_MESSAGE } from '../reactions/actionTypes';
|
||||
import { pushReactions } from '../reactions/actions.any';
|
||||
import { ENDPOINT_REACTION_NAME } from '../reactions/constants';
|
||||
import { getReactionMessageFromBuffer, isReactionsEnabled } from '../reactions/functions.any';
|
||||
import { endpointMessageReceived } from '../subtitles/actions.any';
|
||||
import { showToolbox } from '../toolbox/actions';
|
||||
|
||||
|
||||
@@ -92,6 +93,14 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
_addChatMsgListener(action.conference, store);
|
||||
break;
|
||||
|
||||
case OPEN_CHAT:
|
||||
unreadCount = 0;
|
||||
|
||||
if (typeof APP !== 'undefined') {
|
||||
APP.API.notifyChatUpdated(unreadCount, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case CLOSE_CHAT: {
|
||||
const isPollTabOpen = getState()['features/chat'].isPollsTabFocused;
|
||||
|
||||
@@ -107,38 +116,6 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
break;
|
||||
}
|
||||
|
||||
case ENDPOINT_MESSAGE_RECEIVED: {
|
||||
const state = store.getState();
|
||||
|
||||
if (!isReactionsEnabled(state)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { participant, data } = action;
|
||||
|
||||
if (data?.name === ENDPOINT_REACTION_NAME) {
|
||||
store.dispatch(pushReactions(data.reactions));
|
||||
|
||||
_handleReceivedMessage(store, {
|
||||
id: participant.getId(),
|
||||
message: getReactionMessageFromBuffer(data.reactions),
|
||||
privateMessage: false,
|
||||
lobbyChat: false,
|
||||
timestamp: data.timestamp
|
||||
}, false, true);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case OPEN_CHAT:
|
||||
unreadCount = 0;
|
||||
|
||||
if (typeof APP !== 'undefined') {
|
||||
APP.API.notifyChatUpdated(unreadCount, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case SET_IS_POLL_TAB_FOCUSED: {
|
||||
dispatch(resetNbUnreadPollsMessages());
|
||||
break;
|
||||
@@ -276,6 +253,35 @@ function _addChatMsgListener(conference: IJitsiConference, store: IStore) {
|
||||
}
|
||||
);
|
||||
|
||||
conference.on(
|
||||
JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
|
||||
(...args: any) => {
|
||||
const state = store.getState();
|
||||
|
||||
if (!isReactionsEnabled(state)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
store.dispatch(endpointMessageReceived(...args));
|
||||
|
||||
if (args && args.length >= 2) {
|
||||
const [ { _id }, eventData ] = args;
|
||||
|
||||
if (eventData.name === ENDPOINT_REACTION_NAME) {
|
||||
store.dispatch(pushReactions(eventData.reactions));
|
||||
|
||||
_handleReceivedMessage(store, {
|
||||
id: _id,
|
||||
message: getReactionMessageFromBuffer(eventData.reactions),
|
||||
privateMessage: false,
|
||||
lobbyChat: false,
|
||||
timestamp: eventData.timestamp
|
||||
}, false, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
conference.on(
|
||||
JitsiConferenceEvents.CONFERENCE_ERROR, (errorType: string, error: Error) => {
|
||||
errorType === JitsiConferenceErrors.CHAT_ERROR && _handleChatError(store, error);
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import { TouchableOpacity } from 'react-native';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
|
||||
import { openHighlightDialog } from '../../../recording/actions.native';
|
||||
import HighlightButton from '../../../recording/components/Recording/native/HighlightButton';
|
||||
import RecordingLabel from '../../../recording/components/native/RecordingLabel';
|
||||
import { getActiveSession } from '../../../recording/functions';
|
||||
import VisitorsCountLabel from '../../../visitors/components/native/VisitorsCountLabel';
|
||||
|
||||
import RaisedHandsCountLabel from './RaisedHandsCountLabel';
|
||||
@@ -30,10 +28,7 @@ interface IProps {
|
||||
|
||||
const AlwaysOnLabels = ({ createOnPress }: IProps) => {
|
||||
const dispatch = useDispatch();
|
||||
const isStreaming = useSelector((state: IReduxState) =>
|
||||
Boolean(getActiveSession(state, JitsiRecordingConstants.mode.STREAM)));
|
||||
const openHighlightDialogCallback = useCallback(() =>
|
||||
dispatch(openHighlightDialog()), [ dispatch ]);
|
||||
const openHighlightDialogCallback = useCallback(() => dispatch(openHighlightDialog()), [ dispatch ]);
|
||||
|
||||
return (<>
|
||||
<TouchableOpacity
|
||||
@@ -41,14 +36,11 @@ const AlwaysOnLabels = ({ createOnPress }: IProps) => {
|
||||
onPress = { createOnPress(LABEL_ID_RECORDING) } >
|
||||
<RecordingLabel mode = { JitsiRecordingConstants.mode.FILE } />
|
||||
</TouchableOpacity>
|
||||
{
|
||||
isStreaming
|
||||
&& <TouchableOpacity
|
||||
hitSlop = { LabelHitSlop }
|
||||
onPress = { createOnPress(LABEL_ID_STREAMING) } >
|
||||
<RecordingLabel mode = { JitsiRecordingConstants.mode.STREAM } />
|
||||
</TouchableOpacity>
|
||||
}
|
||||
<TouchableOpacity
|
||||
hitSlop = { LabelHitSlop }
|
||||
onPress = { createOnPress(LABEL_ID_STREAMING) } >
|
||||
<RecordingLabel mode = { JitsiRecordingConstants.mode.STREAM } />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
hitSlop = { LabelHitSlop }
|
||||
onPress = { openHighlightDialogCallback }>
|
||||
|
||||
@@ -17,6 +17,7 @@ import { IReduxState, IStore } from '../../../app/types';
|
||||
import { CONFERENCE_BLURRED, CONFERENCE_FOCUSED } from '../../../base/conference/actionTypes';
|
||||
import { FULLSCREEN_ENABLED, PIP_ENABLED } from '../../../base/flags/constants';
|
||||
import { getFeatureFlag } from '../../../base/flags/functions';
|
||||
import { getParticipantCount } from '../../../base/participants/functions';
|
||||
import Container from '../../../base/react/components/native/Container';
|
||||
import LoadingIndicator from '../../../base/react/components/native/LoadingIndicator';
|
||||
import TintedView from '../../../base/react/components/native/TintedView';
|
||||
@@ -100,6 +101,11 @@ interface IProps extends AbstractProps {
|
||||
*/
|
||||
_fullscreenEnabled: boolean;
|
||||
|
||||
/**
|
||||
* The indicator which determines if the conference type is one to one.
|
||||
*/
|
||||
_isOneToOneConference: boolean;
|
||||
|
||||
/**
|
||||
* The indicator which determines if the participants pane is open.
|
||||
*/
|
||||
@@ -364,6 +370,7 @@ class Conference extends AbstractConference<IProps, State> {
|
||||
_aspectRatio,
|
||||
_connecting,
|
||||
_filmstripVisible,
|
||||
_isOneToOneConference,
|
||||
_largeVideoParticipantId,
|
||||
_reducedUI,
|
||||
_shouldDisplayTileView,
|
||||
@@ -419,11 +426,13 @@ class Conference extends AbstractConference<IProps, State> {
|
||||
<Captions onPress = { this._onClick } />
|
||||
|
||||
{
|
||||
_shouldDisplayTileView
|
||||
|| <Container style = { styles.displayNameContainer }>
|
||||
<DisplayNameLabel
|
||||
participantId = { _largeVideoParticipantId } />
|
||||
</Container>
|
||||
_shouldDisplayTileView || (
|
||||
!_isOneToOneConference
|
||||
&& <Container style = { styles.displayNameContainer }>
|
||||
<DisplayNameLabel
|
||||
participantId = { _largeVideoParticipantId } />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
{ !_shouldDisplayTileView && <LonelyMeetingExperience /> }
|
||||
@@ -564,6 +573,7 @@ function _mapStateToProps(state: IReduxState, _ownProps: any) {
|
||||
const { backgroundColor } = state['features/dynamic-branding'];
|
||||
const { startCarMode } = state['features/base/settings'];
|
||||
const { enabled: audioOnlyEnabled } = state['features/base/audio-only'];
|
||||
const participantCount = getParticipantCount(state);
|
||||
const brandingStyles = backgroundColor ? {
|
||||
backgroundColor
|
||||
} : undefined;
|
||||
@@ -577,6 +587,7 @@ function _mapStateToProps(state: IReduxState, _ownProps: any) {
|
||||
_connecting: isConnecting(state),
|
||||
_filmstripVisible: isFilmstripVisible(state),
|
||||
_fullscreenEnabled: getFeatureFlag(state, FULLSCREEN_ENABLED, true),
|
||||
_isOneToOneConference: Boolean(participantCount === 2),
|
||||
_isParticipantsPaneOpen: isOpen,
|
||||
_largeVideoParticipantId: state['features/large-video'].participantId,
|
||||
_pictureInPictureEnabled: getFeatureFlag(state, PIP_ENABLED),
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import React, { Component } from 'react';
|
||||
import { TouchableOpacity, View, ViewStyle } from 'react-native';
|
||||
|
||||
import TranscribingLabel from '../../../transcribing/components/TranscribingLabel.native';
|
||||
import VideoQualityLabel from '../../../video-quality/components/VideoQualityLabel.native';
|
||||
|
||||
import InsecureRoomNameLabel from './InsecureRoomNameLabel';
|
||||
import { LABEL_ID_INSECURE_ROOM_NAME, LABEL_ID_QUALITY, LabelHitSlop } from './constants';
|
||||
import { LABEL_ID_INSECURE_ROOM_NAME, LABEL_ID_QUALITY, LABEL_ID_TRANSCRIBING, LabelHitSlop } from './constants';
|
||||
import styles from './styles';
|
||||
|
||||
interface IProps {
|
||||
@@ -32,6 +33,13 @@ class Labels extends Component<IProps> {
|
||||
<View
|
||||
pointerEvents = 'box-none'
|
||||
style = { styles.indicatorContainer as ViewStyle }>
|
||||
<TouchableOpacity
|
||||
hitSlop = { LabelHitSlop }
|
||||
onPress = {
|
||||
this.props.createOnPress(LABEL_ID_TRANSCRIBING)
|
||||
} >
|
||||
<TranscribingLabel />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
hitSlop = { LabelHitSlop }
|
||||
onPress = {
|
||||
|
||||
@@ -4,13 +4,11 @@ import { connect } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { getConferenceName, getConferenceTimestamp } from '../../../base/conference/functions';
|
||||
import { CONFERENCE_TIMER_ENABLED } from '../../../base/flags/constants';
|
||||
import { CONFERENCE_TIMER_ENABLED, MEETING_NAME_ENABLED } from '../../../base/flags/constants';
|
||||
import { getFeatureFlag } from '../../../base/flags/functions';
|
||||
import AudioDeviceToggleButton from '../../../mobile/audio-mode/components/AudioDeviceToggleButton';
|
||||
import PictureInPictureButton from '../../../mobile/picture-in-picture/components/PictureInPictureButton';
|
||||
import ParticipantsPaneButton from '../../../participants-pane/components/native/ParticipantsPaneButton';
|
||||
import { isParticipantsPaneEnabled } from '../../../participants-pane/functions';
|
||||
import { isRoomNameEnabled } from '../../../prejoin/functions';
|
||||
import ToggleCameraButton from '../../../toolbox/components/native/ToggleCameraButton';
|
||||
import { isToolboxVisible } from '../../../toolbox/functions.native';
|
||||
import ConferenceTimer from '../ConferenceTimer';
|
||||
@@ -18,7 +16,6 @@ import ConferenceTimer from '../ConferenceTimer';
|
||||
import Labels from './Labels';
|
||||
import styles from './styles';
|
||||
|
||||
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
@@ -32,20 +29,15 @@ interface IProps {
|
||||
*/
|
||||
_createOnPress: Function;
|
||||
|
||||
/**
|
||||
* Whether participants feature is enabled or not.
|
||||
*/
|
||||
_isParticipantsPaneEnabled: boolean;
|
||||
|
||||
/**
|
||||
* Name of the meeting we're currently in.
|
||||
*/
|
||||
_meetingName: string;
|
||||
|
||||
/**
|
||||
* Whether displaying the current room name is enabled or not.
|
||||
* Whether displaying the current meeting name is enabled or not.
|
||||
*/
|
||||
_roomNameEnabled: boolean;
|
||||
_meetingNameEnabled: boolean;
|
||||
|
||||
/**
|
||||
* True if the navigation bar should be visible.
|
||||
@@ -61,7 +53,7 @@ interface IProps {
|
||||
* @returns {JSX.Element}
|
||||
*/
|
||||
const TitleBar = (props: IProps) => {
|
||||
const { _isParticipantsPaneEnabled, _visible } = props;
|
||||
const { _visible } = props;
|
||||
|
||||
if (!_visible) {
|
||||
return null;
|
||||
@@ -83,7 +75,7 @@ const TitleBar = (props: IProps) => {
|
||||
</View>
|
||||
}
|
||||
{
|
||||
props._roomNameEnabled
|
||||
props._meetingNameEnabled
|
||||
&& <View style = { styles.roomNameView as ViewStyle }>
|
||||
<Text
|
||||
numberOfLines = { 1 }
|
||||
@@ -101,13 +93,9 @@ const TitleBar = (props: IProps) => {
|
||||
<View style = { styles.titleBarButtonContainer }>
|
||||
<AudioDeviceToggleButton styles = { styles.titleBarButton } />
|
||||
</View>
|
||||
{
|
||||
_isParticipantsPaneEnabled
|
||||
&& <View style = { styles.titleBarButtonContainer }>
|
||||
<ParticipantsPaneButton
|
||||
styles = { styles.titleBarButton } />
|
||||
</View>
|
||||
}
|
||||
<View style = { styles.titleBarButtonContainer }>
|
||||
<ParticipantsPaneButton styles = { styles.titleBarButton } />
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
@@ -119,15 +107,15 @@ const TitleBar = (props: IProps) => {
|
||||
* @returns {IProps}
|
||||
*/
|
||||
function _mapStateToProps(state: IReduxState) {
|
||||
const { hideConferenceTimer } = state['features/base/config'];
|
||||
const { hideConferenceTimer, hideConferenceSubject } = state['features/base/config'];
|
||||
const startTimestamp = getConferenceTimestamp(state);
|
||||
|
||||
return {
|
||||
_conferenceTimerEnabled:
|
||||
Boolean(getFeatureFlag(state, CONFERENCE_TIMER_ENABLED, true) && !hideConferenceTimer && startTimestamp),
|
||||
_isParticipantsPaneEnabled: isParticipantsPaneEnabled(state),
|
||||
_meetingName: getConferenceName(state),
|
||||
_roomNameEnabled: isRoomNameEnabled(state),
|
||||
_meetingNameEnabled:
|
||||
getFeatureFlag(state, MEETING_NAME_ENABLED, true) && !hideConferenceSubject,
|
||||
_visible: isToolboxVisible(state)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import BaseTheme from '../../../../base/ui/components/BaseTheme.native';
|
||||
* React component for Audio icon.
|
||||
*
|
||||
* @returns {JSX.Element} - The Audio icon.
|
||||
*
|
||||
*/
|
||||
const AudioIcon = (): JSX.Element => (<Icon
|
||||
color = { BaseTheme.palette.ui02 }
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
|
||||
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
|
||||
import RecordingExpandedLabel from '../../../recording/components/native/RecordingExpandedLabel';
|
||||
import TranscribingExpandedLabel from '../../../transcribing/components/TranscribingExpandedLabel.native';
|
||||
import VideoQualityExpandedLabel from '../../../video-quality/components/VideoQualityExpandedLabel.native';
|
||||
|
||||
import InsecureRoomNameExpandedLabel from './InsecureRoomNameExpandedLabel';
|
||||
@@ -22,6 +23,7 @@ export const EXPANDED_LABEL_TIMEOUT = 5000;
|
||||
export const LABEL_ID_QUALITY = 'quality';
|
||||
export const LABEL_ID_RECORDING = 'recording';
|
||||
export const LABEL_ID_STREAMING = 'streaming';
|
||||
export const LABEL_ID_TRANSCRIBING = 'transcribing';
|
||||
export const LABEL_ID_INSECURE_ROOM_NAME = 'insecure-room-name';
|
||||
export const LABEL_ID_RAISED_HANDS_COUNT = 'raised-hands-count';
|
||||
export const LABEL_ID_VISITORS_COUNT = 'visitors-count';
|
||||
@@ -56,6 +58,9 @@ export const EXPANDED_LABELS: {
|
||||
},
|
||||
alwaysOn: true
|
||||
},
|
||||
[LABEL_ID_TRANSCRIBING]: {
|
||||
component: TranscribingExpandedLabel
|
||||
},
|
||||
[LABEL_ID_INSECURE_ROOM_NAME]: {
|
||||
component: InsecureRoomNameExpandedLabel
|
||||
},
|
||||
|
||||
@@ -23,7 +23,6 @@ import { getOverlayToRender } from '../../../overlay/functions.web';
|
||||
import ParticipantsPane from '../../../participants-pane/components/web/ParticipantsPane';
|
||||
import Prejoin from '../../../prejoin/components/web/Prejoin';
|
||||
import { isPrejoinPageVisible } from '../../../prejoin/functions';
|
||||
import ReactionAnimations from '../../../reactions/components/web/ReactionsAnimations';
|
||||
import { toggleToolboxVisible } from '../../../toolbox/actions.any';
|
||||
import { fullScreenChanged, showToolbox } from '../../../toolbox/actions.web';
|
||||
import JitsiPortal from '../../../toolbox/components/web/JitsiPortal';
|
||||
@@ -261,7 +260,6 @@ class Conference extends AbstractConference<IProps, any> {
|
||||
{ _showLobby && <LobbyScreen />}
|
||||
</div>
|
||||
<ParticipantsPane />
|
||||
<ReactionAnimations />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import HighlightButton from '../../../recording/components/Recording/web/Highlig
|
||||
import RecordingLabel from '../../../recording/components/web/RecordingLabel';
|
||||
import { showToolbox } from '../../../toolbox/actions.web';
|
||||
import { isToolboxVisible } from '../../../toolbox/functions.web';
|
||||
import TranscribingLabel from '../../../transcribing/components/TranscribingLabel.web';
|
||||
import VideoQualityLabel from '../../../video-quality/components/VideoQualityLabel.web';
|
||||
import VisitorsCountLabel from '../../../visitors/components/web/VisitorsCountLabel';
|
||||
import ConferenceTimer from '../ConferenceTimer';
|
||||
@@ -82,6 +83,10 @@ const COMPONENTS: Array<{
|
||||
Component: RaisedHandsCountLabel,
|
||||
id: 'raised-hands-count'
|
||||
},
|
||||
{
|
||||
Component: TranscribingLabel,
|
||||
id: 'transcribing'
|
||||
},
|
||||
{
|
||||
Component: VideoQualityLabel,
|
||||
id: 'video-quality'
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { IStateful } from '../base/app/types';
|
||||
import { toState } from '../base/redux/functions';
|
||||
import { iAmVisitor } from '../visitors/functions';
|
||||
|
||||
|
||||
/**
|
||||
@@ -16,19 +15,3 @@ export function shouldDisplayNotifications(stateful: IStateful) {
|
||||
|
||||
return !calleeInfoVisible;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns true if polls feature is disabled.
|
||||
*
|
||||
* @param {(Function|Object)} stateful - The (whole) redux state, or redux's
|
||||
* {@code getState} function to be used to retrieve the state
|
||||
* features/base/config.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function arePollsDisabled(stateful: IStateful) {
|
||||
const state = toState(stateful);
|
||||
|
||||
return state['features/base/config']?.disablePolls || iAmVisitor(state);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user