Compare commits

..

1 Commits

Author SHA1 Message Date
Jaya Allamsetty
c67b4087fa fix(av-moderation) Check for moderation before unmuting mic/camera or starting share 2025-07-17 16:42:20 -04:00
393 changed files with 2722 additions and 6350 deletions

View File

@@ -152,13 +152,12 @@ jobs:
xcodebuild clean \
-workspace ios/jitsi-meet.xcworkspace \
-scheme JitsiMeetSDK
xcodebuild -downloadPlatform iOS -buildVersion 18.2
xcodebuild archive \
-workspace ios/jitsi-meet.xcworkspace \
-scheme JitsiMeetSDK \
-configuration Release \
-sdk iphoneos \
-destination 'generic/platform=iOS' \
-destination='generic/platform=iOS' \
-archivePath ios/sdk/out/ios-device \
SKIP_INSTALL=NO \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES

View File

@@ -28,14 +28,6 @@ android {
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
}
externalNativeBuild {
cmake {
arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON", "-DANDROID_STL=c++_shared"
cppFlags "-std=c++17"
cFlags "-DANDROID_PLATFORM=android-26"
}
}
}
signingConfigs {
@@ -54,8 +46,8 @@ android {
applicationIdSuffix ".debug"
}
release {
// Uncomment the following line for signing a test release build.
// signingConfig signingConfigs.debug
// Uncomment the following line for singing a test release build.
//signingConfig signingConfigs.debug
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-release.pro'
buildConfigField "boolean", "GOOGLE_SERVICES_ENABLED", "${googleServicesEnabled}"
@@ -110,6 +102,8 @@ dependencies {
gradle.projectsEvaluated {
// Dropbox integration
//
def dropboxAppKey
if (project.file('dropbox.key').exists()) {
dropboxAppKey = project.file('dropbox.key').text.trim() - 'db-'
@@ -180,6 +174,7 @@ gradle.projectsEvaluated {
packageTask.dependsOn(currentRunPackagerTask)
}
}
if (googleServicesEnabled) {

View File

@@ -6,5 +6,6 @@
-keep public class * extends java.lang.Exception
# R8 missing classes - suppress warnings
-dontwarn com.facebook.fresco.ui.common.LoggingListener
-dontwarn com.facebook.memory.config.MemorySpikeConfig
-dontwarn kotlinx.parcelize.Parcelize

View File

@@ -96,3 +96,8 @@
# Rule to avoid build errors related to SVGs.
-keep public class com.horcrux.svg.** {*;}
# https://github.com/facebook/fresco/issues/2638
-keep public class com.facebook.imageutils.** {
public *;
}

View File

@@ -7,11 +7,11 @@ import org.gradle.util.VersionNumber
buildscript {
ext {
kotlinVersion = "2.0.21"
gradlePluginVersion = "8.6.0"
buildToolsVersion = "35.0.0"
compileSdkVersion = 35
gradlePluginVersion = "8.4.2"
buildToolsVersion = "34.0.0"
compileSdkVersion = 34
minSdkVersion = 26
targetSdkVersion = 35
targetSdkVersion = 34
supportLibVersion = "28.0.0"
ndkVersion = "27.1.12297006"
@@ -75,6 +75,26 @@ allprojects {
}
}
// Due to a dependency conflict between React Native and the Fresco library used by GiphySDK,
// GIFs appear as static images instead of animating
// https://github.com/Giphy/giphy-react-native-sdk/commit/7fe466ed6fddfaec95f9cbc959d33bd75ad8f900
configurations.configureEach {
resolutionStrategy {
forcedModules = [
'com.facebook.fresco:fresco:3.2.0',
'com.facebook.fresco:animated-gif:3.2.0',
'com.facebook.fresco:animated-base:3.2.0',
'com.facebook.fresco:animated-drawable:3.2.0',
'com.facebook.fresco:animated-webp:3.2.0',
'com.facebook.fresco:webpsupport:3.2.0',
'com.facebook.fresco:imagepipeline-okhttp3:3.2.0',
'com.facebook.fresco:middleware:3.2.0',
'com.facebook.fresco:nativeimagetranscoder:3.2.0'
]
}
}
// Third-party react-native modules which Jitsi Meet SDK for Android depends
// on and which are not available in third-party Maven repositories need to
// be deployed in a Maven repository of ours.

View File

@@ -1,113 +0,0 @@
#!/bin/bash
progname="${0##*/}"
progname="${progname%.sh}"
# usage: check_elf_alignment.sh [path to *.so files|path to *.apk]
cleanup_trap() {
if [ -n "${tmp}" -a -d "${tmp}" ]; then
rm -rf ${tmp}
fi
exit $1
}
usage() {
echo "Host side script to check the ELF alignment of shared libraries."
echo "Shared libraries are reported ALIGNED when their ELF regions are"
echo "16 KB or 64 KB aligned. Otherwise they are reported as UNALIGNED."
echo
echo "Usage: ${progname} [input-path|input-APK|input-APEX]"
}
if [ ${#} -ne 1 ]; then
usage
exit
fi
case ${1} in
--help | -h | -\?)
usage
exit
;;
*)
dir="${1}"
;;
esac
if ! [ -f "${dir}" -o -d "${dir}" ]; then
echo "Invalid file: ${dir}" >&2
exit 1
fi
if [[ "${dir}" == *.apk ]]; then
trap 'cleanup_trap' EXIT
echo
echo "Recursively analyzing $dir"
echo
if { zipalign --help 2>&1 | grep -q "\-P <pagesize_kb>"; }; then
echo "=== APK zip-alignment ==="
zipalign -v -c -P 16 4 "${dir}" | egrep 'lib/arm64-v8a|lib/x86_64|Verification'
echo "========================="
else
echo "NOTICE: Zip alignment check requires build-tools version 35.0.0-rc3 or higher."
echo " You can install the latest build-tools by running the below command"
echo " and updating your \$PATH:"
echo
echo " sdkmanager \"build-tools;35.0.0-rc3\""
fi
dir_filename=$(basename "${dir}")
tmp=$(mktemp -d -t "${dir_filename%.apk}_out_XXXXX")
unzip "${dir}" lib/* -d "${tmp}" >/dev/null 2>&1
dir="${tmp}"
fi
if [[ "${dir}" == *.apex ]]; then
trap 'cleanup_trap' EXIT
echo
echo "Recursively analyzing $dir"
echo
dir_filename=$(basename "${dir}")
tmp=$(mktemp -d -t "${dir_filename%.apex}_out_XXXXX")
deapexer extract "${dir}" "${tmp}" || { echo "Failed to deapex." && exit 1; }
dir="${tmp}"
fi
RED="\e[31m"
GREEN="\e[32m"
ENDCOLOR="\e[0m"
unaligned_libs=()
echo
echo "=== ELF alignment ==="
matches="$(find "${dir}" -type f)"
IFS=$'\n'
for match in $matches; do
# We could recursively call this script or rewrite it to though.
[[ "${match}" == *".apk" ]] && echo "WARNING: doesn't recursively inspect .apk file: ${match}"
[[ "${match}" == *".apex" ]] && echo "WARNING: doesn't recursively inspect .apex file: ${match}"
[[ $(file "${match}") == *"ELF"* ]] || continue
res="$(objdump -p "${match}" | grep LOAD | awk '{ print $NF }' | head -1)"
if [[ $res =~ 2\*\*(1[4-9]|[2-9][0-9]|[1-9][0-9]{2,}) ]]; then
echo -e "${match}: ${GREEN}ALIGNED${ENDCOLOR} ($res)"
else
echo -e "${match}: ${RED}UNALIGNED${ENDCOLOR} ($res)"
unaligned_libs+=("${match}")
fi
done
if [ ${#unaligned_libs[@]} -gt 0 ]; then
echo -e "${RED}Found ${#unaligned_libs[@]} unaligned libs (only arm64-v8a/x86_64 libs need to be aligned).${ENDCOLOR}"
elif [ -n "${dir_filename}" ]; then
echo -e "ELF Verification Successful"
fi
echo "====================="

View File

@@ -44,8 +44,10 @@ dependencies {
api "com.facebook.react:react-android:$rootProject.ext.rnVersion"
api "com.facebook.react:hermes-android:$rootProject.ext.rnVersion"
implementation 'com.facebook.fresco:animated-gif:2.5.0'
implementation 'com.dropbox.core:dropbox-core-sdk:4.0.1'
implementation 'com.jakewharton.timber:timber:5.0.1'
implementation 'com.squareup.duktape:duktape-android:1.3.0'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'androidx.startup:startup-runtime:1.1.0'
implementation 'com.google.j2objc:j2objc-annotations:3.0.0'
@@ -86,7 +88,6 @@ dependencies {
implementation project(':react-native-svg')
implementation project(':react-native-video')
implementation project(':react-native-webview')
implementation project(':react-native-worklets-core')
// Use `api` here so consumers can use WebRTCModuleOptions.
api project(':react-native-webrtc')

View File

@@ -0,0 +1,57 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jitsi.meet.sdk;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.module.annotations.ReactModule;
import com.squareup.duktape.Duktape;
@ReactModule(name = JavaScriptSandboxModule.NAME)
class JavaScriptSandboxModule extends ReactContextBaseJavaModule {
public static final String NAME = "JavaScriptSandbox";
public JavaScriptSandboxModule(ReactApplicationContext reactContext) {
super(reactContext);
}
/**
* Evaluates the given code in a Duktape VM.
* @param code - The code that needs to evaluated.
* @param promise - Resolved with the output in case of success or rejected with an exception
* in case of failure.
*/
@ReactMethod
public void evaluate(String code, Promise promise) {
Duktape vm = Duktape.create();
try {
Object res = vm.evaluate(code);
promise.resolve(res.toString());
} catch (Throwable tr) {
promise.reject(tr);
} finally {
vm.close();
}
}
@Override
public String getName() {
return NAME;
}
}

View File

@@ -49,10 +49,6 @@ public class JitsiInitializer implements Initializer<Boolean> {
// Register activity lifecycle handler for the orientation locker module.
((Application) context).registerActivityLifecycleCallbacks(OrientationActivityLifecycle.getInstance());
// Initialize ReactInstanceManager during application startup
// This ensures it's ready before any Activity onCreate is called
ReactInstanceManagerHolder.initReactInstanceManager((Application) context);
return true;
}

View File

@@ -25,15 +25,9 @@ import android.content.IntentFilter;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.facebook.react.modules.core.PermissionListener;
@@ -93,28 +87,6 @@ public class JitsiMeetActivity extends AppCompatActivity
launch(context, options);
}
public static void addTopBottomInsets(@NonNull Window w, @NonNull View v) {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.VANILLA_ICE_CREAM) return;
View decorView = w.getDecorView();
decorView.post(() -> {
WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(decorView);
if (insets != null) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
params.topMargin = insets.getInsets(WindowInsetsCompat.Type.systemBars()).top;
params.bottomMargin = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
v.setLayoutParams(params);
decorView.setOnApplyWindowInsetsListener((view, windowInsets) -> {
view.setBackgroundColor(JitsiMeetView.BACKGROUND_COLOR);
return windowInsets;
});
}
});
}
// Overrides
//
@@ -130,12 +102,7 @@ public class JitsiMeetActivity extends AppCompatActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ReactInstanceManager is now initialized by JitsiInitializer during application startup
// Just call onHostResume since the manager is already ready
JitsiMeetActivityDelegate.onHostResume(this);
setContentView(R.layout.activity_jitsi_meet);
addTopBottomInsets(getWindow(),findViewById(android.R.id.content));
this.jitsiView = findViewById(R.id.jitsiView);
registerForBroadcastMessages();

View File

@@ -17,7 +17,6 @@
package org.jitsi.meet.sdk;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.os.Bundle;
import android.util.AttributeSet;
@@ -36,7 +35,7 @@ public class JitsiMeetView extends FrameLayout {
/**
* Background color. Should match the background color set in JS.
*/
public static final int BACKGROUND_COLOR = 0xFF040404;
private static final int BACKGROUND_COLOR = 0xFF040404;
/**
* React Native root view.
@@ -197,6 +196,8 @@ public class JitsiMeetView extends FrameLayout {
}
setBackgroundColor(BACKGROUND_COLOR);
ReactInstanceManagerHolder.initReactInstanceManager((Activity) context);
}
/**

View File

@@ -17,7 +17,7 @@
package org.jitsi.meet.sdk;
import android.annotation.SuppressLint;
import android.app.Application;
import android.app.Activity;
import androidx.annotation.Nullable;
@@ -64,6 +64,7 @@ class ReactInstanceManagerHolder {
new AudioModeModule(reactContext),
new DropboxModule(reactContext),
new ExternalAPIModule(reactContext),
new JavaScriptSandboxModule(reactContext),
new LocaleDetector(reactContext),
new LogBridgeModule(reactContext),
new PictureInPictureModule(reactContext),
@@ -108,7 +109,6 @@ class ReactInstanceManagerHolder {
new com.horcrux.svg.SvgPackage(),
new org.wonday.orientation.OrientationPackage(),
new com.splashview.SplashViewPackage(),
new com.worklets.WorkletsCorePackage(),
new ReactPackageAdapter() {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
@@ -207,9 +207,9 @@ class ReactInstanceManagerHolder {
* time. All {@code ReactRootView} instances will be tied to the one and
* only {@code ReactInstanceManager}.
*
* @param app {@code Application}
* @param activity {@code Activity} current running Activity.
*/
static void initReactInstanceManager(Application app) {
static void initReactInstanceManager(Activity activity) {
if (reactInstanceManager != null) {
return;
}
@@ -231,14 +231,14 @@ class ReactInstanceManagerHolder {
reactInstanceManager
= ReactInstanceManager.builder()
.setApplication(app)
.setCurrentActivity(null)
.setApplication(activity.getApplication())
.setCurrentActivity(activity)
.setBundleAssetName("index.android.bundle")
.setJSMainModulePath("index.android")
.setJavaScriptExecutorFactory(new HermesExecutorFactory())
.addPackages(getReactNativePackages())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.BEFORE_CREATE)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
}
}

View File

@@ -52,5 +52,3 @@ include ':react-native-webrtc'
project(':react-native-webrtc').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webrtc/android')
include ':react-native-webview'
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')
include ':react-native-worklets-core'
project(':react-native-worklets-core').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-worklets-core/android')

View File

@@ -8,13 +8,9 @@ module.exports = {
// This happens because react native has conflict with @babel/plugin-transform-private-methods plugin
// https://github.com/ethers-io/ethers.js/discussions/4309#discussioncomment-6694524
plugins: [
'optional-require',
[
'@babel/plugin-transform-private-methods', {
'loose': true
}
],
'react-native-worklets-core/plugin'
plugins: [ 'optional-require',
[ '@babel/plugin-transform-private-methods', {
'loose': true
} ]
]
};

View File

@@ -18,6 +18,8 @@ import {
maybeRedirectToWelcomePage,
reloadWithStoredParams
} from './react/features/app/actions';
import { showModeratedNotification } from './react/features/av-moderation/actions';
import { shouldShowModeratedNotification } from './react/features/av-moderation/functions';
import {
_conferenceWillJoin,
authStatusChanged,
@@ -50,8 +52,7 @@ import {
commonUserJoinedHandling,
commonUserLeftHandling,
getConferenceOptions,
sendLocalParticipant,
updateTrackMuteState
sendLocalParticipant
} from './react/features/base/conference/functions';
import { getReplaceParticipant, getSsrcRewritingFeatureFlag } from './react/features/base/config/functions';
import { connect } from './react/features/base/connection/actions.web';
@@ -134,7 +135,6 @@ import {
isLocalTrackMuted,
isUserInteractionRequiredForUnmute
} from './react/features/base/tracks/functions';
import { getLocalJitsiAudioTrackSettings } from './react/features/base/tracks/functions.web';
import { downloadJSON } from './react/features/base/util/downloadJSON';
import { getJitsiMeetGlobalNSConnectionTimes } from './react/features/base/util/helpers';
import { openLeaveReasonDialog } from './react/features/conference/actions.web';
@@ -153,20 +153,20 @@ import {
DATA_CHANNEL_CLOSED_NOTIFICATION_ID,
NOTIFICATION_TIMEOUT_TYPE
} from './react/features/notifications/constants';
import { isModerationNotificationDisplayed } from './react/features/notifications/functions';
import { suspendDetected } from './react/features/power-monitor/actions';
import { initPrejoin, isPrejoinPageVisible } from './react/features/prejoin/functions';
import { disableReceiver, stopReceiver } from './react/features/remote-control/actions';
import { setScreenAudioShareState } from './react/features/screen-share/actions.web';
import { isScreenAudioShared } from './react/features/screen-share/functions';
import { toggleScreenshotCaptureSummary } from './react/features/screenshot-capture/actions';
import { setAudioSettings } from './react/features/settings/actions.web';
import { AudioMixerEffect } from './react/features/stream-effects/audio-mixer/AudioMixerEffect';
import { createRnnoiseProcessor } from './react/features/stream-effects/rnnoise';
import { handleToggleVideoMuted } from './react/features/toolbox/actions.any';
import { transcriberJoined, transcriberLeft } from './react/features/transcribing/actions';
import { muteLocal } from './react/features/video-menu/actions.any';
const logger = Logger.getLogger('app:conference-web');
const logger = Logger.getLogger(__filename);
let room;
/*
@@ -568,15 +568,7 @@ export default {
if (browser.isWebKitBased()) {
this.muteAudio(true, true);
} else {
localTracks = localTracks.filter(track => {
if (track.getType() === MEDIA_TYPE.AUDIO) {
track.stopStream();
return false;
}
return true;
});
localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.AUDIO);
}
}
@@ -712,6 +704,14 @@ export default {
return;
}
if (!mute && shouldShowModeratedNotification(MEDIA_TYPE.AUDIO, state)) {
if (!isModerationNotificationDisplayed(MEDIA_TYPE.AUDIO, state)) {
APP.store.dispatch(showModeratedNotification(MEDIA_TYPE.AUDIO));
}
return;
}
await APP.store.dispatch(setAudioMuted(mute, true));
},
@@ -754,6 +754,15 @@ export default {
return;
}
// check for A/V Moderation when trying to unmute and return early
if (!mute && shouldShowModeratedNotification(MEDIA_TYPE.VIDEO, state)) {
if (!isModerationNotificationDisplayed(MEDIA_TYPE.VIDEO, state)) {
APP.store.dispatch(showModeratedNotification(MEDIA_TYPE.VIDEO));
}
return;
}
APP.store.dispatch(setVideoMuted(mute, VIDEO_MUTISM_AUTHORITY.USER, true));
},
@@ -1674,12 +1683,8 @@ export default {
room.on(
JitsiConferenceEvents.START_MUTED_POLICY_CHANGED,
({ audio, video }) => {
APP.store.dispatch(onStartMutedPolicyChanged(audio, video));
const state = APP.store.getState();
updateTrackMuteState(state, APP.store.dispatch, true);
updateTrackMuteState(state, APP.store.dispatch, false);
APP.store.dispatch(
onStartMutedPolicyChanged(audio, video));
}
);
@@ -1773,11 +1778,7 @@ export default {
return this.useAudioStream(stream);
})
.then(() => {
const state = APP.store.getState();
const localAudio = getLocalJitsiAudioTrack(state);
const settings = getLocalJitsiAudioTrackSettings(state);
APP.store.dispatch(setAudioSettings(settings));
const localAudio = getLocalJitsiAudioTrack(APP.store.getState());
if (localAudio && isDefaultMicSelected) {
// workaround for the default device to be shown as selected in the

View File

@@ -363,7 +363,6 @@ var config = {
// Desktop sharing
// Optional desktop sharing frame rate options. Default value: min:5, max:5.
// Setting higher min/max values will affect the resolution, it makes it worse.
// desktopSharingFrameRate: {
// min: 5,
// max: 5,
@@ -762,7 +761,7 @@ var config = {
// hideDominantSpeakerBadge: false,
// Default language for the user interface. Cannot be overwritten.
// For iframe integrations, use the `lang` option directly instead.
// DEPRECATED! Use the `lang` iframe option directly instead.
// defaultLanguage: 'en',
// Disables profile and the edit of all fields from the profile settings (display name and email)
@@ -792,6 +791,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.
// 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
@@ -1363,9 +1363,7 @@ var config = {
// disableGrantModerator: true,
// // If set to 'all' the 'Private chat' button will be disabled for all participants.
// // If set to 'allow-moderator-chat' the 'Private chat' button will be available for chats with moderators.
// // If set to 'disable-visitor-chat' the 'Private chat' button will be disabled for visitor-main participant
// // conversations.
// disablePrivateChat: 'all' | 'allow-moderator-chat' | 'disable-visitor-chat',
// disablePrivateChat: 'all' | 'allow-moderator-chat',
// },

View File

@@ -90,7 +90,7 @@ $welcomePageHeaderContainerMargin: $welcomePageHeaderContainerMarginTop auto 0;
$welcomePageHeaderTextTitleMarginBottom: 0;
$welcomePageHeaderTextTitleFontSize: 2.625rem;
$welcomePageHeaderTextTitleFontWeight: normal;
$welcomePageHeaderTextTitleLineHeight: 3.125rem;
$welcomePageHeaderTextTitleLineHeight: 50px;
$welcomePageHeaderTextTitleOpacity: 1;
$welcomePageEnterRoomDisplay: flex;

View File

@@ -1,16 +0,0 @@
// Stub replacement for @giphy/js-analytics to prevent beforeunload handlers
// This completely disables all Giphy analytics functionality
export const pingback = () => {
// Completely disabled - do nothing
};
export const mergeAttributes = (attributes, newAttributes) => {
// Return merged attributes without any analytics calls
return { ...attributes,
...newAttributes };
};
// Ensure no beforeunload handlers are ever registered
export default pingback;

View File

@@ -64,11 +64,11 @@ PODS:
- GoogleUtilities/UserDefaults (~> 7.7)
- PromisesObjC (< 3.0, >= 1.2)
- fmt (11.0.2)
- Giphy (2.2.16):
- Giphy (2.2.13):
- libwebp
- giphy-react-native-sdk (4.1.0):
- giphy-react-native-sdk (3.3.1):
- DoubleConversion
- Giphy (= 2.2.16)
- Giphy (= 2.2.13)
- glog
- hermes-engine
- RCT-Folly (= 2024.11.18.00)
@@ -1382,9 +1382,9 @@ PODS:
- React-Core
- react-native-netinfo (11.1.0):
- React-Core
- react-native-orientation-locker (1.5.0):
- react-native-orientation-locker (1.6.0):
- React-Core
- react-native-pager-view (6.8.1):
- react-native-pager-view (6.4.1):
- DoubleConversion
- glog
- hermes-engine
@@ -1407,7 +1407,7 @@ PODS:
- Yoga
- react-native-performance (5.1.2):
- React-Core
- react-native-safe-area-context (5.5.2):
- react-native-safe-area-context (5.4.0):
- React-Core
- react-native-slider (4.5.6):
- DoubleConversion
@@ -1497,27 +1497,6 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- react-native-worklets-core (1.6.2):
- DoubleConversion
- glog
- hermes-engine
- RCT-Folly (= 2024.11.18.00)
- RCTRequired
- RCTTypeSafety
- React-Core
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-NativeModulesApple
- React-RCTFabric
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- React-nativeconfig (0.77.2)
- React-NativeModulesApple (0.77.2):
- glog
@@ -1815,7 +1794,7 @@ PODS:
- React-Core
- RNDefaultPreference (1.4.4):
- React-Core
- RNDeviceInfo (12.1.0):
- RNDeviceInfo (10.9.0):
- React-Core
- RNGestureHandler (2.24.0):
- DoubleConversion
@@ -1953,7 +1932,6 @@ DEPENDENCIES:
- react-native-video (from `../node_modules/react-native-video`)
- react-native-webrtc (from `../node_modules/react-native-webrtc`)
- react-native-webview (from `../node_modules/react-native-webview`)
- react-native-worklets-core (from `../node_modules/react-native-worklets-core`)
- React-nativeconfig (from `../node_modules/react-native/ReactCommon`)
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
@@ -2123,8 +2101,6 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-webrtc"
react-native-webview:
:path: "../node_modules/react-native-webview"
react-native-worklets-core:
:path: "../node_modules/react-native-worklets-core"
React-nativeconfig:
:path: "../node_modules/react-native/ReactCommon"
React-NativeModulesApple:
@@ -2225,8 +2201,8 @@ SPEC CHECKSUMS:
FirebaseCrashlytics: feb07e4e9187be3c23c6a846cce4824e5ce2dd0b
FirebaseInstallations: 40bd9054049b2eae9a2c38ef1c3dd213df3605cd
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
Giphy: 55914215541027873875757f350530e6d8986fba
giphy-react-native-sdk: 733177b2537b527cfa55979c396cc1f2046eb457
Giphy: a11dd02b51ac2ec37b881de1717ebf2cc8e9df62
giphy-react-native-sdk: 678a115ea5a47a43d39d1b61703e0d08b1e48917
glog: eb93e2f488219332457c3c4eafd2738ddc7e80b8
GoogleAppMeasurement: 4c19f031220c72464d460c9daa1fb5d1acce958e
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
@@ -2273,15 +2249,14 @@ SPEC CHECKSUMS:
react-native-get-random-values: d16467cf726c618e9c7a8c3c39c31faa2244bbba
react-native-keep-awake: 03b74eebe4f2bb5e8478fc8f420651a92463b6f8
react-native-netinfo: 5364263f903da576bdef9c84a76fe243ab06812c
react-native-orientation-locker: dbd3f6ddbe9e62389cb0807dc2af63f6c36dec36
react-native-pager-view: 11662c698c8f11d39e05891316d2a144fa00adc4
react-native-orientation-locker: ee8bb2177365ca74f51dc1e11218fe544634d523
react-native-pager-view: 68e8a65a607a6f91a1e25865002192c3c4f53fcf
react-native-performance: 125a96c145e29918b55b45ce25cbba54f1e24dcd
react-native-safe-area-context: 0f7bf11598f9a61b7ceac8dc3f59ef98697e99e1
react-native-safe-area-context: 9d72abf6d8473da73033b597090a80b709c0b2f1
react-native-slider: 1205801a8d29b28cacc14eef08cb120015cdafcb
react-native-video: eb861d67a71dfef1bbf6086a811af5f338b13781
react-native-webrtc: 2261a482150195092246fe70b3aff976f2e11ec5
react-native-webview: 079eca50edf657503318b66687dadfb903731aa8
react-native-worklets-core: b59cf88762c8fb6132d8796babd4cec15217d6f0
React-nativeconfig: ecf4dc92c40b97e2b3f0c619938f78bfd6507b08
React-NativeModulesApple: f457bbfb30fb3bc41979b1a87b99d292d7340d39
React-perflogger: 1111b5feb064c4cc83df88fb403efda54b387951
@@ -2315,7 +2290,7 @@ SPEC CHECKSUMS:
RNCAsyncStorage: aa75595c1aefa18f868452091fa0c411a516ce11
RNCClipboard: 7c3e3b5f71d84ef61690ad377b6c50cf27864ff5
RNDefaultPreference: ee13d69e6693d193cd223d10e15e5b3c012d31ba
RNDeviceInfo: 723e97dd98af9b7913477e7a40252c15517c258c
RNDeviceInfo: 8af23685571b7867d8dc15fb89e7fb5fa8607e1e
RNGestureHandler: 9f3109e11ed88fe5bed280bf7762b25e4c52f396
RNGoogleSignin: 30e1aee80140dc0706cd78a4951c411376c88329
RNScreens: 9ef996b6041d0960a4794a845f7d0808b171b4ef

View File

@@ -30,14 +30,6 @@
<string>35F9.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>85F4.1</string>
</array>
</dict>
</array>
<key>NSPrivacyCollectedDataTypes</key>
<array/>

View File

@@ -51,6 +51,7 @@
C81E9AB925AC5AD800B134D9 /* ExternalAPI.h in Headers */ = {isa = PBXBuildFile; fileRef = C81E9AB825AC5AD800B134D9 /* ExternalAPI.h */; };
C8AFD27F2462C613000293D2 /* InfoPlistUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = C8AFD27D2462C613000293D2 /* InfoPlistUtil.h */; settings = {ATTRIBUTES = (Public, ); }; };
C8AFD2802462C613000293D2 /* InfoPlistUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = C8AFD27E2462C613000293D2 /* InfoPlistUtil.m */; };
DE438CDA2350934700DD541D /* JavaScriptSandbox.m in Sources */ = {isa = PBXBuildFile; fileRef = DE438CD82350934700DD541D /* JavaScriptSandbox.m */; };
DE65AACA2317FFCD00290BEC /* LogUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AAC92317FFCD00290BEC /* LogUtils.h */; };
DE65AACC2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */; };
DE762DB422AFDE76000DEBD6 /* JitsiMeetUserInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DE762DB322AFDE76000DEBD6 /* JitsiMeetUserInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -97,6 +98,7 @@
DE9A015C289A9A9A00E41CBB /* JitsiMeetLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = DE81A2D32316AC4D00AE1940 /* JitsiMeetLogger.m */; };
DE9A015E289A9A9A00E41CBB /* JitsiMeetView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B412F171EDEC65D00B1A0A6 /* JitsiMeetView.m */; };
DE9A015F289A9A9A00E41CBB /* JitsiMeet.m in Sources */ = {isa = PBXBuildFile; fileRef = DEFE535321FB1BF800011A3A /* JitsiMeet.m */; };
DE9A0160289A9A9A00E41CBB /* JavaScriptSandbox.m in Sources */ = {isa = PBXBuildFile; fileRef = DE438CD82350934700DD541D /* JavaScriptSandbox.m */; };
DE9A0162289A9A9A00E41CBB /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BB9AD781F5EC6D7001C08DB /* Intents.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
DE9A0163289A9A9A00E41CBB /* CallKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BB9AD761F5EC6CE001C08DB /* CallKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
DE9A0166289A9A9A00E41CBB /* CallKitIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 0BC4B8681F8C01E100CE8B21 /* CallKitIcon.png */; };
@@ -159,6 +161,7 @@
C81E9AB825AC5AD800B134D9 /* ExternalAPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExternalAPI.h; sourceTree = "<group>"; };
C8AFD27D2462C613000293D2 /* InfoPlistUtil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InfoPlistUtil.h; sourceTree = "<group>"; };
C8AFD27E2462C613000293D2 /* InfoPlistUtil.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InfoPlistUtil.m; sourceTree = "<group>"; };
DE438CD82350934700DD541D /* JavaScriptSandbox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JavaScriptSandbox.m; sourceTree = "<group>"; };
DE65AAC92317FFCD00290BEC /* LogUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LogUtils.h; sourceTree = "<group>"; };
DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetBaseLogHandler+Private.h"; sourceTree = "<group>"; };
DE762DB322AFDE76000DEBD6 /* JitsiMeetUserInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeetUserInfo.h; sourceTree = "<group>"; };
@@ -247,6 +250,7 @@
C69EFA02209A0EFD0027712B /* callkit */,
A4A934E7212F3AB8001E9388 /* dropbox */,
0BD906E91EC0C00300C8C18E /* Info.plist */,
DE438CD82350934700DD541D /* JavaScriptSandbox.m */,
0BD906E81EC0C00300C8C18E /* JitsiMeet.h */,
DEFE535821FB311F00011A3A /* JitsiMeet+Private.h */,
DEA9F283258A5D9900D4CD74 /* JitsiMeetSDK.h */,
@@ -677,6 +681,7 @@
DE81A2D52316AC4D00AE1940 /* JitsiMeetLogger.m in Sources */,
0B412F191EDEC65D00B1A0A6 /* JitsiMeetView.m in Sources */,
DEFE535421FB1BF800011A3A /* JitsiMeet.m in Sources */,
DE438CDA2350934700DD541D /* JavaScriptSandbox.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -709,6 +714,7 @@
4E0EF63328CA2FB3005D1B03 /* JMCallKitEmitter.m in Sources */,
DE9A015E289A9A9A00E41CBB /* JitsiMeetView.m in Sources */,
DE9A015F289A9A9A00E41CBB /* JitsiMeet.m in Sources */,
DE9A0160289A9A9A00E41CBB /* JavaScriptSandbox.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -0,0 +1,55 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@import JavaScriptCore;
#import <React/RCTBridgeModule.h>
@interface JavaScriptSandbox : NSObject<RCTBridgeModule>
@end
@implementation JavaScriptSandbox
RCT_EXPORT_MODULE();
+ (BOOL)requiresMainQueueSetup {
return NO;
}
#pragma mark - Exported methods
RCT_EXPORT_METHOD(evaluate:(NSString *)code
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {
__block BOOL hasError = NO;
JSContext *ctx = [[JSContext alloc] init];
ctx.exceptionHandler = ^(JSContext *context, JSValue *exception) {
hasError = YES;
reject(@"evaluate", [exception toString], nil);
};
JSValue *ret = [ctx evaluateScript:code];
if (!hasError) {
NSString *result = [ret toString];
if (result == nil) {
reject(@"evaluate", @"Error in string coercion", nil);
} else {
resolve(result);
}
}
}
@end

View File

@@ -112,9 +112,7 @@
"disabled": "L'invio di messaggi in chat è disabilitato.",
"enter": "Entra nella conversazione",
"error": "Errore: il tuo messaggio non è stato inviato. Motivo: {{error}}",
"everyone": "Tutti",
"fieldPlaceHolder": "Scrivi qui il tuo messaggio",
"guestsChatIndicator": "(ospite)",
"lobbyChatMessageTo": "Messaggio a {{recipient}} in sala d'attesa",
"message": "Messaggio",
"messageAccessibleTitle": "{{user}} dice:",
@@ -156,7 +154,7 @@
"installExtensionText": "Installa un'estensione per integrare Google Calendar e Office 365"
},
"closedCaptionsTab": {
"emptyState": "Il contenuto dei sottotitoli sarà disponibile una volta che l'organizzatore lo attiverà",
"emptyState": "Il contenuto dei sottotitoli sarà disponibile una volta che l'organizzatore lo attiva",
"startClosedCaptionsButton": "Attiva sottotitoli"
},
"connectingOverlay": {
@@ -302,12 +300,6 @@
"alreadySharedVideoTitle": "È permessa una sola condivisione video alla volta",
"applicationWindow": "Finestra dell'applicazione",
"authenticationRequired": "Richiesta autenticazione",
"cameraCaptureDialog": {
"description": "Scatta ed invia una foto usando la fotocamera del telefono",
"ok": "Apri la fotocamera",
"reject": "Non adesso",
"title": "Scatta una foto"
},
"cameraConstraintFailedError": "La tua videocamera non soddisfa alcuni dei requisiti.",
"cameraNotFoundError": "Videocamera non trovata.",
"cameraNotSendingData": "Impossibile accedere alla videocamera. Controlla che non sia in uso in un'altra applicazione, seleziona un altro dispositivo dalle impostazioni o prova a ricaricare l'applicazione.",
@@ -331,7 +323,7 @@
"contactSupport": "Contatta il supporto",
"copied": "Copiato",
"copy": "Copia",
"demoteParticipantDialog": "Vuoi far diventare questo partecipante uno spettatore?",
"demoteParticipantDialog": "Sei sicuro di voler far diventare questo partecipante uno spettatore?",
"demoteParticipantTitle": "Fai diventare spettatore",
"dismiss": "Scarta",
"displayNameRequired": "Ciao, qual è il tuo nome?",
@@ -346,8 +338,8 @@
"error": "Errore",
"errorRoomCreationRestriction": "Hai provato ad accedere alla riunione troppo presto, torna tra un po'.",
"gracefulShutdown": "Il nostro servizio è al momento inattivo per manutenzione. Si prega di riprovare più tardi.",
"grantModeratorDialog": "Vuoi rendere relatore questo partecipante?",
"grantModeratorTitle": "Fai diventare relatore",
"grantModeratorDialog": "Sei sicuro di voler rendere organizzatore questo partecipante?",
"grantModeratorTitle": "Fai diventare organizzatore",
"hide": "Nascondi",
"hideShareAudioHelper": "Non mostrare più questa finestra",
"incorrectPassword": "Nome utente o password errati",
@@ -356,7 +348,7 @@
"internalErrorTitle": "Errore interno",
"kickMessage": "Puoi contattare {{participantDisplayName}} per maggiori dettagli.",
"kickParticipantButton": "Espelli",
"kickParticipantDialog": "Vuoi espellere questo partecipante?",
"kickParticipantDialog": "Sei sicuro di voler espellere questo partecipante?",
"kickParticipantTitle": "Espellere questo partecipante?",
"kickSystemTitle": "Oh! Sei stato espulso dalla riunione",
"kickTitle": "Oh! {{participantDisplayName}} ti ha espulso dalla riunione.",
@@ -370,8 +362,8 @@
"lockRoom": "Aggiungi una $t(lockRoomPassword) alla riunione",
"lockTitle": "Blocco fallito",
"login": "Accesso",
"loginQuestion": "Vuoi fare l'accesso e abbandonare la riunione?",
"logoutQuestion": "Vuoi disconnetterti e abbandonare la riunione?",
"loginQuestion": "Sei sicuro di voler fare l'accesso e abbandonare la riunione?",
"logoutQuestion": "Sei sicuro di volerti disconnettere e abbandonare la riunione?",
"logoutTitle": "Disconnessione",
"maxUsersLimitReached": "È stato raggiunto il numero massimo di partecipanti. La riunione è al completo. Contatta l'organizzatore o riprova più tardi!",
"maxUsersLimitReachedTitle": "Raggiunto limite massimo partecipanti",
@@ -383,39 +375,27 @@
"micTimeoutError": "Impossibile avviare la sorgente audio. Tempo di attesa scaduto.",
"micUnknownError": "Impossibile usare il microfono per un motivo sconosciuto.",
"moderationAudioLabel": "Consenti ai partecipanti di attivare il microfono",
"moderationDesktopLabel": "Consenti ai partecipanti di condividere lo schermo",
"moderationVideoLabel": "Consenti ai partecipanti di attivare la videocamera",
"muteEveryoneDialog": "I partecipanti possono attivare il microfono in qualsiasi momento.",
"muteEveryoneDialogModerationOn": "I partecipanti possono chiedere di parlare in qualsiasi momento.",
"muteEveryoneElseDialog": "Una volta spenti i microfoni non potrai riattivarli, ma ogni partecipante potrà farlo da sé in qualsiasi momento.",
"muteEveryoneElseTitle": "Spegnere il microfono a tutti, tranne che a {{whom}}?",
"muteEveryoneElsesDesktopDialog": "Una volta interrotta la condivisione dello schermo non potrai riattivarla, ma ogni partecipante potrà farlo da sé in qualsiasi momento.",
"muteEveryoneElsesDesktopTitle": "Interrompere la condivisione dello schermo a tutti, tranne che a {{whom}}?",
"muteEveryoneElsesVideoDialog": "Una volta spente le videocamere non potrai riaccenderle, ma ogni partecipante potrà farlo da sé in qualsiasi momento.",
"muteEveryoneElsesVideoTitle": "Spegnere la videocamera a tutti, tranne che a {{whom}}?",
"muteEveryoneSelf": "tu",
"muteEveryoneStartMuted": "Tutti iniziano a microfono spento da adesso in avanti",
"muteEveryoneTitle": "Spegnere il microfono a tutti?",
"muteEveryonesDesktopDialog": "I partecipanti potranno condividere lo schermo in qualsiasi momento.",
"muteEveryonesDesktopDialogModerationOn": "I partecipanti possono inviare una richiesta per condividere lo schermo in ogni momento.",
"muteEveryonesDesktopTitle": "Interrompere la condivisione dello schermo a tutti?",
"muteEveryonesVideoDialog": "Ogni partecipante potrà riavviare il video da sé in qualsiasi momento.",
"muteEveryonesVideoDialogModerationOn": "I partecipanti possono chiedere di attivare il video in qualsiasi momento.",
"muteEveryonesVideoDialogOk": "Spegni",
"muteEveryonesVideoTitle": "Spegnere la videocamera a tutti?",
"muteParticipantBody": "Non potrai riattivare il loro microfono, ma loro potranno farlo in qualsiasi momento.",
"muteParticipantButton": "Silenzia",
"muteParticipantsDesktopBody": "Non potrai riavviare la loro condivisione dello schermo, ma loro potranno farlo in qualsiasi momento.",
"muteParticipantsDesktopBodyModerationOn": "Non potrai riavviare la loro condivisione dello schermo e nemmeno loro potranno.",
"muteParticipantsDesktopButton": "Interrompi la condivisione dello schermo",
"muteParticipantsDesktopDialog": "Vuoi interrompere la condivisione dello schermo di questo partecipante? Non potrai riattivarla, ma lui potrà farlo in qualsiasi momento.",
"muteParticipantsDesktopDialogModerationOn": "Vuoi interrompere la condivisione dello schermo di questo partecipante? Non potrai riattivarla e nemmeno loro potranno.",
"muteParticipantsDesktopTitle": "Disattivare la condivisione dello schermo di questo partecipante?",
"muteParticipantsVideoBody": "Non potrai riattivare le videocamere, ma loro potranno farlo in qualsiasi momento.",
"muteParticipantsVideoBodyModerationOn": "Non potrai riattivare le videocamere e nemmeno loro potranno.",
"muteParticipantsVideoButton": "Spegni videocamere",
"muteParticipantsVideoDialog": "Vuoi spegnere la videocamera di questo partecipante? Non potrai riattivarla, ma lui potrà farlo in qualsiasi momento.",
"muteParticipantsVideoDialogModerationOn": "Vuoi spegnere la videocamera di questo partecipante? Non potrai riattivarla e nemmeno lui potrà farlo.",
"muteParticipantsVideoDialog": "Sei sicuro di voler spegnere la videocamera di questo partecipante? Non potrai riattivarla, ma lui potrà farlo in qualsiasi momento.",
"muteParticipantsVideoDialogModerationOn": "Sei sicuro di voler spegnere la videocamera di questo partecipante? Non potrai riattivarla e nemmeno lui potrà farlo.",
"muteParticipantsVideoTitle": "Spegnere la videocamera di questo partecipante?",
"noDropboxToken": "Token Dropbox non valido",
"password": "Password",
@@ -444,7 +424,7 @@
"remoteControlTitle": "Connessione desktop remoto",
"remoteUserControls": "Controlli dell'utente remoto {{username}}",
"removePassword": "Rimuovi la $t(lockRoomPassword)",
"removeSharedVideoMsg": "Vuoi rimuovere il tuo video condiviso?",
"removeSharedVideoMsg": "Sei sicuro di voler rimuovere il tuo video condiviso?",
"removeSharedVideoTitle": "Rimuovi video condiviso",
"renameBreakoutRoomLabel": "Nome della stanza",
"renameBreakoutRoomTitle": "Rinomina stanza",
@@ -497,8 +477,8 @@
"startRemoteControlErrorMessage": "Si è verificato un errore nel tentativo di avviare la sessione di controllo remoto!",
"stopLiveStreaming": "Ferma la diretta",
"stopRecording": "Ferma registrazione",
"stopRecordingWarning": "Vuoi interrompere la registrazione?",
"stopStreamingWarning": "Vuoi interrompere la diretta?",
"stopRecordingWarning": "Sei sicuro di voler interrompere la registrazione?",
"stopStreamingWarning": "Sei sicuro di voler interrompere la diretta?",
"streamKey": "Chiave della diretta",
"thankYou": "Grazie per aver usato {{appName}}!",
"token": "token",
@@ -567,15 +547,11 @@
"downloadFailedDescription": "Si prega di riprovare.",
"downloadFailedTitle": "Download non riuscito",
"downloadFile": "Download",
"downloadStarted": "Download del file iniziato",
"dragAndDrop": "Trascina e rilascia i file qui o da qualsiasi altra parte nella schermata",
"fileAlreadyUploaded": "Questo file è già stato caricato nella riunione.",
"fileTooLargeDescription": "Assicurati che il file non superi {{ maxFileSize }}.",
"fileTooLargeTitle": "Il file selezionato è troppo grande",
"fileUploadProgress": "Caricamento del file in corso",
"fileUploadedSuccessfully": "Il file è stato caricato con successo",
"removeFile": "Rimuovi",
"removeFileSuccess": "File rimosso con successo",
"uploadFailedDescription": "Si prega di riprovare.",
"uploadFailedTitle": "Caricamento non riuscito",
"uploadFile": "Condividi file"
@@ -707,7 +683,7 @@
"signInCTA": "Accedi o inserisci la tua chiave della diretta su YouTube.",
"signOut": "Disconnetti",
"signedInAs": "Hai effettuato l'accesso come:",
"start": "Avvia una diretta",
"start": "Inizia una diretta",
"streamIdHelp": "Cos'è questo?",
"title": "Diretta",
"unavailableTitle": "La diretta non è disponibile",
@@ -768,9 +744,9 @@
"engaged": "Registrazione avviata.",
"finished": "La registrazione della sessione {{token}} è terminata. Invia il file della registrazione all'organizzatore.",
"finishedModerator": "La registrazione della sessione {{token}} è terminata. La registrazione della traccia è stata salvata. Chiedi ai partecipanti di inviare le loro registrazioni.",
"notModerator": "Non sei un relatore. Non puoi avviare o interrompere la registrazione."
"notModerator": "Non sei un organizzatore. Non puoi avviare o interrompere la registrazione."
},
"moderator": "Relatore",
"moderator": "Organizzatore",
"no": "No",
"participant": "Partecipante",
"participantStats": "Statistiche partecipante",
@@ -791,9 +767,8 @@
"me": "io",
"notify": {
"OldElectronAPPTitle": "Falla di sicurezza!",
"allowAll": "Consenti tutto",
"allowAudio": "Consenti l'audio",
"allowDesktop": "Consenti la condivisione dello schermo",
"allowBoth": "Entrambi",
"allowVideo": "Consenti il video",
"allowedUnmute": "Puoi accendere il microfono, avviare la videocamera o condividere il tuo schermo.",
"audioUnmuteBlockedDescription": "L'accensione dei microfoni è stata temporaneamente bloccata per i limiti del sistema.",
@@ -807,7 +782,6 @@
"dataChannelClosedDescription": "Il canale bridge è inattivo, quindi la qualità video potrebbe essere limitata all'impostazione più bassa.",
"dataChannelClosedDescriptionWithAudio": "Il canale bridge è inattivo, quindi potrebbero esserci interruzioni di audio e video",
"dataChannelClosedWithAudio": "La qualità audio e video potrebbe essere scarsa",
"desktopMutedRemotelyTitle": "La tua condivisione dello schermo è stata interrotta da {{participantDisplayName}}",
"disabledIframe": "L'incorporamento serve solo come dimostrazione, quindi questa chiamata si disconnetterà tra {{timeout}} minuti.",
"disabledIframeSecondaryNative": "L'incorporamento {{domain}} serve solo come dimostrazione, quindi questa chiamata si disconnetterà tra {{timeout}} minuti.",
"disabledIframeSecondaryWeb": "L'incorporamento {{domain}} serve solo come dimostrazione, quindi questa chiamata si disconnetterà tra {{timeout}} minuti. Si prega di usare <a href='{{jaasDomain}}' rel='noopener noreferrer' target='_blank'>Jitsi as a Service</a> per la produzione di riunioni incorporate!",
@@ -818,7 +792,7 @@
"focusFail": "{{component}} non disponibile - nuovo tentativo tra {{ms}} sec",
"gifsMenu": "GIPHY",
"groupTitle": "Notifiche",
"hostAskedUnmute": "Il relatore ti chiede di intervenire.",
"hostAskedUnmute": "L'organizzatore ti chiede di intervenire.",
"invalidTenant": "Nome non valido",
"invalidTenantHyphenDescription": "Il nome che hai scelto non è valido (inizia o finisce con '-').",
"invalidTenantLengthDescription": "Il nome che hai scelto è troppo lungo.",
@@ -840,17 +814,17 @@
"localRecordingStopped": "{{name}} ha smesso di registrare.",
"me": "Io",
"moderationInEffectCSDescription": "Alza la mano, se vuoi condividere lo schermo.",
"moderationInEffectCSTitle": "La condivisione schermo è stata bloccata dal relatore",
"moderationInEffectCSTitle": "La condivisione schermo è stata bloccata dall'organizzatore",
"moderationInEffectDescription": "Alza la mano, se vuoi prendere la parola.",
"moderationInEffectTitle": "Il tuo microfono è stato spento dal relatore",
"moderationInEffectTitle": "Il tuo microfono è stato spento dall'organizzatore",
"moderationInEffectVideoDescription": "Alza la mano, se vuoi avviare la tua videocamera.",
"moderationInEffectVideoTitle": "La tua videocamera è stata spenta dal relatore",
"moderationRequestFromModerator": "Il relatore vorrebbe che tu accendessi il microfono",
"moderationInEffectVideoTitle": "La tua videocamera è stata spenta dall'organizzatore",
"moderationRequestFromModerator": "L'organizzatore vorrebbe che tu accendessi il microfono",
"moderationRequestFromParticipant": "Vuole parlare",
"moderationStartedTitle": "Moderazione in corso",
"moderationStoppedTitle": "Moderazione interrotta",
"moderationToggleDescription": "da {{participantDisplayName}}",
"moderator": "Ora sei un relatore!",
"moderator": "Ora sei un organizzatore!",
"muted": "Hai iniziato la conversazione con il microfono disattivato.",
"mutedRemotelyDescription": "Puoi sempre attivare il microfono quando vuoi parlare. Spegni il microfono quando hai finito, per evitare rumori di fondo nella riunione.",
"mutedRemotelyTitle": "{{participantDisplayName}} ti ha spento il microfono",
@@ -865,7 +839,6 @@
"oldElectronClientDescription1": "Sembra che tu stia usando una versione obsoleta del client Jitsi Meet, che ha vulnerabilità note. Assicurati di aggiornarlo alla nostra ",
"oldElectronClientDescription2": "ultima versione",
"oldElectronClientDescription3": " ora!",
"openChat": "Apri chat",
"participantWantsToJoin": "Vuole unirsi alla riunione",
"participantsWantToJoin": "Vogliono unirsi alla riunione",
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) è stata rimossa da un altro partecipante",
@@ -889,7 +862,6 @@
"suggestRecordingDescription": "Vuoi avviare la registrazione?",
"suggestRecordingTitle": "Registra questa riunione",
"unmute": "Accendi il microfono",
"unmuteScreen": "Iniziata la condivisione dello schermo",
"unmuteVideo": "Accendi la videocamera",
"videoMutedRemotelyDescription": "Puoi riaccenderla in qualsiasi momento.",
"videoMutedRemotelyTitle": "{{participantDisplayName}} ti ha spento la videocamera",
@@ -909,14 +881,11 @@
"admit": "Ammetti",
"admitAll": "Ammetti tutti",
"allow": "Permetti ai partecipanti di:",
"allowDesktop": "Consenti la condivisione dello schermo",
"allowVideo": "Permetti videocamere",
"askDesktop": "Chiedi di condividere lo schermo",
"askUnmute": "Chiedi di accendere il microfono",
"audioModeration": "Riattivare il microfono",
"blockEveryoneMicCamera": "Blocca microfono e videocamera a tutti",
"breakoutRooms": "Stanze",
"desktopModeration": "Avvia la condivisione dello schermo",
"goLive": "Vai alla diretta",
"invite": "Invita partecipanti",
"lowerAllHands": "Abbassa tutte le mani",
@@ -928,8 +897,6 @@
"muteAll": "Silenzia tutti",
"muteEveryoneElse": "Silenzia tutti gli altri",
"reject": "Respingi",
"stopDesktop": "Interrompi la condivisione dello schermo",
"stopEveryonesDesktop": "Interrompi la condivisione dello schermo agli altri",
"stopEveryonesVideo": "Ferma il video di tutti",
"stopVideo": "Ferma il video",
"unblockEveryoneMicCamera": "Sblocca microfono e videocamera a tutti",
@@ -939,7 +906,6 @@
"headings": {
"lobby": "Sala d'attesa ({{count}})",
"participantsList": "Partecipanti alla riunione ({{count}})",
"viewerRequests": "Richieste spettatori ({{count}})",
"visitorInQueue": " ({{count}} in attesa)",
"visitorRequests": " ({{count}} richiesta/e)",
"visitors": "Spettatori {{count}}",
@@ -1107,7 +1073,7 @@
"fileSharingdescription": "Condividi la registrazione con i partecipanti alla riunione",
"highlight": "Evidenzia",
"highlightMoment": "Evidenzia momento",
"highlightMomentDisabled": "Puoi evidenziare i momenti in cui inizia la registrazione",
"highlightMomentDisabled": "Puoi evidenziare dei momenti quando inizia la registrazione",
"highlightMomentSuccess": "Momento evidenziato",
"highlightMomentSucessDescription": "Il tuo momento evidenziato sarà aggiunto al riepilogo della riunione.",
"inProgress": "Registrazione o diretta in corso",
@@ -1118,7 +1084,7 @@
"localRecordingNoVideo": "Il video non sta venendo registrato",
"localRecordingStartWarning": "Assicurati di interrompere la registrazione prima di uscire dalla riunione, altrimenti la registrazione non verrà salvata.",
"localRecordingStartWarningTitle": "Interrompi la registrazione per salvarla",
"localRecordingVideoStop": "Interrompere il video fermerà anche la registrazione. Vuoi continuare?",
"localRecordingVideoStop": "Interrompere il video fermerà anche la registrazione. Sei sicuro di voler continuare?",
"localRecordingVideoWarning": "Per registrare il video, deve essere già avviato prima dell'inizio della registrazione",
"localRecordingWarning": "Assicurati di aver selezionato la scheda corrente, per registrare gli audio e video corretti.",
"loggedIn": "Accesso effettuato come {{userName}}",
@@ -1187,8 +1153,8 @@
"loggedIn": "Connesso come {{name}}",
"maxStageParticipants": "Numero massimo di partecipanti che possono essere messi in evidenza nella schermata principale",
"microphones": "Microfoni",
"moderator": "Relatore",
"moderatorOptions": "Opzioni relatore",
"moderator": "Organizzatore",
"moderatorOptions": "Opzioni organizzatore",
"more": "Generali",
"name": "Nome",
"noDevice": "Nessuno",
@@ -1224,7 +1190,7 @@
"conferenceSection": "Riunione",
"disableCallIntegration": "Disattiva l'integrazione nativa delle chiamate",
"disableCrashReporting": "Disattiva la diagnostica dei crash",
"disableCrashReportingWarning": "Vuoi disattivare la diagnostica dei crash? Quest'impostazione verrà applicata al prossimo avvio dell'app.",
"disableCrashReportingWarning": "Sei sicuro di voler disattivare la diagnostica dei crash? Quest'impostazione verrà applicata al prossimo avvio dell'app.",
"disableP2P": "Disattiva la modalità Peer-to-Peer",
"displayName": "Nome visualizzato",
"displayNamePlaceholderText": "Es: Mario Rossi",
@@ -1241,8 +1207,8 @@
"serverURL": "URL del server",
"showAdvanced": "Mostra impostazioni avanzate",
"startCarModeInLowBandwidthMode": "Avvia modalità auto in modalità larghezza di banda limitata",
"startWithAudioMuted": "Avvia con audio disattivato",
"startWithVideoMuted": "Avvia con video disattivato",
"startWithAudioMuted": "Inizia con audio disattivato",
"startWithVideoMuted": "Inizia con video disattivato",
"terms": "Termini",
"version": "Versione"
},
@@ -1317,7 +1283,7 @@
"feedback": "Lascia un feedback",
"fullScreen": "Attiva modalità a schermo intero",
"giphy": "Mostra menu GIPHY",
"grantModerator": "Concedi permessi da relatore",
"grantModerator": "Concedi permessi di organizzatore",
"hangup": "Lascia la riunione",
"heading": "Barra degli strumenti",
"help": "Aiuto",
@@ -1380,20 +1346,6 @@
"videounmute": "Accendi videocamera"
},
"addPeople": "Aggiungi partecipanti alla chiamata",
"advancedAudioSettings": {
"aec": {
"label": "Cancellazione dell'eco"
},
"agc": {
"label": "Controllo del guadagno automatico"
},
"ns": {
"label": "Cancellazione del rumore"
},
"stereo": {
"label": "Stereo"
}
},
"audioOnlyOff": "Disabilita modalità larghezza di banda limitata",
"audioOnlyOn": "Abilita modalità larghezza di banda limitata",
"audioRoute": "Scegli il dispositivo audio",
@@ -1460,12 +1412,11 @@
"profile": "Modifica profilo",
"raiseHand": "Alza la mano",
"raiseYourHand": "Alza la mano",
"reactionBoo": "Invia Buu",
"reactionClap": "Invia Applauso",
"reactionHeart": "Invia Cuore",
"reactionLaugh": "Invia Risata",
"reactionLike": "Invia Mi piace",
"reactionLove": "Invia Love",
"reactionBoo": "Invia buu",
"reactionClap": "Invia applauso",
"reactionHeart": "Invia cuore",
"reactionLaugh": "Invia risata",
"reactionLike": "Invia mi piace",
"reactionSilence": "Invia senza parole",
"reactionSurprised": "Invia a bocca aperta",
"reactions": "Reazioni",
@@ -1551,17 +1502,15 @@
"connectionInfo": "Informazioni connessione",
"demote": "Fai diventare spettatore",
"domute": "Disattiva microfono",
"domuteDesktop": "Interrompi la condivisione dello schermo",
"domuteDesktopOfOthers": "Interrompi la condivisione dello schermo agli altri",
"domuteOthers": "Disattiva microfono a tutti gli altri",
"domuteVideo": "Disattiva videocamera",
"domuteVideoOfOthers": "Disattiva videocamera a tutti gli altri",
"flip": "Specchia",
"grantModerator": "Concedi permessi da relatore",
"grantModerator": "Concedi permessi da organizzatore",
"hideSelfView": "Nascondi la tua immagine",
"kick": "Espelli",
"mirrorVideo": "Specchia il tuo video",
"moderator": "Relatore",
"moderator": "Organizzatore",
"mute": "Il partecipante ha il microfono spento",
"muted": "Microfono spento",
"pinToStage": "Metti in primo piano",
@@ -1608,7 +1557,7 @@
"description": "Adesso sei uno spettatore in questa riunione.",
"raiseHand": "Alza la mano",
"title": "Ingresso nella riunione in corso",
"wishToSpeak": "Se vuoi parlare, si prega di alzare la mano sotto e aspettare l'autorizzazione del relatore."
"wishToSpeak": "Se vuoi parlare, si prega di alzare la mano sotto e aspettare l'autorizzazione dell'organizzatore."
},
"labelTooltip": "Numero di spettatori: {{count}}",
"notification": {
@@ -1669,7 +1618,7 @@
"roomnameHint": "Inserisci il nome o l'URL della riunione a cui vuoi accedere. Puoi anche inventarti un nome, assicurati solo che le persone con cui vuoi collegarti lo conoscano, così che possano inserire lo stesso nome.",
"sendFeedback": "Invia feedback",
"settings": "Impostazioni",
"startMeeting": "Avvia riunione",
"startMeeting": "Inizia riunione",
"terms": "Termini di utilizzo",
"title": "Il sistema di videoconferenza sicuro, funzionale e completamente gratuito.",
"upcomingMeetings": "Prossime riunioni"

View File

@@ -109,12 +109,9 @@
}
},
"chat": {
"disabled": "Tērzēšanas ziņojumu sūtīšana ir atspējota.",
"enter": "Ienākt istabā",
"error": "Kļūda: Jūsu ziņa netika nosūtīta. Cēlonis: {{error}}",
"everyone": "Visi",
"fieldPlaceHolder": "Rakstiet ziņu šeit",
"guestsChatIndicator": "(viesis)",
"lobbyChatMessageTo": "Vestibila tērzēšanas ziņa adresātam {{recipient}}",
"message": "Ziņa",
"messageAccessibleTitle": "{{user}} saka:",
@@ -127,8 +124,7 @@
"title": "Ierakstiet vārdu, lai izmantotu tērzēšanā",
"titleWithCC": "Ievadiet segvārdu, lai izmantotu tērzēšanā un slēptos subtitros",
"titleWithPolls": "Ierakstiet segvārdu, lai izmantotu tērzēšanā un aptaujās",
"titleWithPollsAndCC": "Ievadiet segvārdu, lai izmantotu tērzēšanā, aptaujās un slēptos subtitros",
"titleWithPollsAndCCAndFileSharing": "Ievadiet segvārdu, lai izmantotu tērzēšanā, aptaujās, slēptos subtitros un failos"
"titleWithPollsAndCC": "Ievadiet segvārdu, lai izmantotu tērzēšanā, aptaujās un slēptos subtitros"
},
"noMessagesMessage": "Sapulcē pagaidām nav nevienas ziņas. Uzsāciet saraksti!",
"privateNotice": "Privāta ziņa adresātam {{recipient}}",
@@ -138,14 +134,12 @@
"tabs": {
"chat": "Tērzēšana",
"closedCaptions": "Slēptie subtitri",
"fileSharing": "Faili",
"polls": "Aptaujas"
},
"title": "Tērzēšana",
"titleWithCC": "Tērzēšana un Slēptie subtitri",
"titleWithFeatures": "Tērzēšana un",
"titleWithFileSharing": "Faili",
"titleWithCC": "Tērzēšana un slēptie subtitri",
"titleWithPolls": "Tērzēšana un Aptaujas",
"titleWithPollsAndCC": "Tērzēšana, Aptaujas un Slēptie subtitri",
"you": "jūs"
},
"chromeExtensionBanner": {
@@ -302,12 +296,6 @@
"alreadySharedVideoTitle": "Atļauts tikai viens kopīgots videoklips",
"applicationWindow": "Lietotnes logs",
"authenticationRequired": "Nepieciešama autentifikācija",
"cameraCaptureDialog": {
"description": "Uzņemt un nosūtīt attēlu, izmantojot mobilā tālruņa kameru",
"ok": "Atvērt kameru",
"reject": "Ne tagad",
"title": "Uzņemt attēlu"
},
"cameraConstraintFailedError": "Kamera neatbilst noteiktajām prasībām.",
"cameraNotFoundError": "Kamera nav atrasta.",
"cameraNotSendingData": "Nevar piekļūt jūsu kamerai. Lūdzu, pārbaudiet, vai šo ierīci neizmanto cita programma, iestatījumu izvēlnē atlasiet citu ierīci vai mēģiniet atkārtoti ielādēt programmu.",
@@ -383,34 +371,22 @@
"micTimeoutError": "Nevarēja palaist audio avotu. Iestājās noildze!",
"micUnknownError": "Nevar izmantot mikrofonu nezināma iemesla dēļ.",
"moderationAudioLabel": "Atļaut dalībniekiem ieslēgt savu mikrofonu",
"moderationDesktopLabel": "Atļaut lietotājiem, kas nav moderatori, kopīgot savu ekrānu",
"moderationVideoLabel": "Atļaut dalībniekiem ieslēgt savu kameru",
"muteEveryoneDialog": "Dalībnieki paši var ieslēgt savu mikrofonu.",
"muteEveryoneDialogModerationOn": "Dalībnieki var nosūtīt pieprasījumu ieslēgt savu mikrofonu.",
"muteEveryoneElseDialog": "Kad skaņa būs izslēgta, jūs nevarēsiet to ieslēgt atpakaļ, taču dalībnieki to varēs izdarīt paši.",
"muteEveryoneElseTitle": "Vai izslēgt skaņu visiem, izņemot {{whom}}?",
"muteEveryoneElsesDesktopDialog": "Kad kopīgošana būs apturēta, jūs vairs nevarēsiet to ieslēgt atpakaļ, bet viņi to varēs izdarīt jebkurā laikā.",
"muteEveryoneElsesDesktopTitle": "Apturēt ekrāna kopīgošanu visiem, izņemot {{kam}}?",
"muteEveryoneElsesVideoDialog": "Kad video būs izslēgts, jūs nevarēsiet to ieslēgt atpakaļ, taču dalībnieki to varēs izdarīt paši.",
"muteEveryoneElsesVideoTitle": "Vai izslēgt video visiem, izņemot {{whom}}?",
"muteEveryoneSelf": "jūs",
"muteEveryoneStartMuted": "No šī brīža visi jauni dalībnieki pieslēdzas ar izslēgt skaņu",
"muteEveryoneTitle": "Vai izslēgt skaņu visiem?",
"muteEveryonesDesktopDialog": "Dalībnieki var kopīgot savu ekrānu jebkurā laikā.",
"muteEveryonesDesktopDialogModerationOn": "Dalībnieki jebkurā laikā var nosūtīt pieprasījumu kopīgot savu ekrānu.",
"muteEveryonesDesktopTitle": "Vai pārtraukt ekrāna kopīgošanu visiem?",
"muteEveryonesVideoDialog": "Dalībnieki var ieslēgt savu video.",
"muteEveryonesVideoDialogModerationOn": "Dalībnieki var nosūtīt pieprasījumu ieslēgt viņu video.",
"muteEveryonesVideoDialogOk": "Atspējot",
"muteEveryonesVideoTitle": "Vai apturēt ikviena video?",
"muteParticipantBody": "Jūs nevariet viņiem ieslēgt skaņu, bet viņi paši to var izdarīt jebkurā laikā.",
"muteParticipantButton": "Izslēgt skaņu",
"muteParticipantsDesktopBody": "Jūs nevarēsiet sākt viņu ekrāna kopīgošanu, bet viņi to varēs izdarīt jebkurā laikā.",
"muteParticipantsDesktopBodyModerationOn": "Jūs nevarēsiet sākt viņu ekrāna kopīgošanu, un arī viņi to nevarēs izdarīt.",
"muteParticipantsDesktopButton": "Pārtraukt ekrāna kopīgošanu",
"muteParticipantsDesktopDialog": "Vai tiešām vēlaties izslēgt šī dalībnieka ekrāna kopīgošanu? Jūs vairs nevarēsiet ieslēgt to atpakaļ, bet viņš to varēs izdarīt jebkurā laikā.",
"muteParticipantsDesktopDialogModerationOn": "Vai tiešām vēlaties izslēgt šī dalībnieka ekrāna kopīgošanu? Jūs vairs nevarēsiet ieslēgt to atpakaļ, un arī viņš to nevarēs izdarīt.",
"muteParticipantsDesktopTitle": "Atspējot ekrāna kopīgošanu šim dalībniekam?",
"muteParticipantsVideoBody": "Jūs nevarēsiet kameru ieslēgt atpakaļ, taču viņi paši to varēs izdarīt jebkurā laikā.",
"muteParticipantsVideoBodyModerationOn": "Ne Jūs, ne dalībnieki nevarēsiet ieslēgt kameru atpakaļ.",
"muteParticipantsVideoButton": "Pārtraukt video",
@@ -563,23 +539,6 @@
"veryBad": "Ļoti Slikta",
"veryGood": "Ļoti Laba"
},
"fileSharing": {
"downloadFailedDescription": "Lūdzu, mēģiniet vēlreiz.",
"downloadFailedTitle": "Lejuplādes kļūda",
"downloadFile": "Lejuplādēt",
"downloadStarted": "Sākta faila lejuplāde",
"dragAndDrop": "Velciet un palaidiet failus šeit, vai jebkurā ekrāna vietā",
"fileAlreadyUploaded": "Fails jau ir augšuplādēts šajā sanāksmē.",
"fileTooLargeDescription": "Lūdzu, pārliecinieties, vai faila lielums nepārsniedz {{ maxFileSize }}.",
"fileTooLargeTitle": "Izvēlētais fails ir pārāk liels",
"fileUploadProgress": "Faila augšuplādes gaita",
"fileUploadedSuccessfully": "Fails veiksmīgi augšuplādēts",
"removeFile": "Noņemt",
"removeFileSuccess": "Fails veiksmīgi noņemts",
"uploadFailedDescription": "Lūdzu, mēģiniet vēlreiz.",
"uploadFailedTitle": "Augšuplādes kļūda",
"uploadFile": "Kopīgot failu"
},
"filmstrip": {
"accessibilityLabel": {
"heading": "Video sīktēli"
@@ -791,9 +750,8 @@
"me": "es",
"notify": {
"OldElectronAPPTitle": "Drošības ievainojamība!",
"allowAll": "Atļaut visu",
"allowAudio": "Atļaut audio",
"allowDesktop": "Atļaut ekrāna kopīgošanu",
"allowBoth": "Abus",
"allowVideo": "Atļaut video",
"allowedUnmute": "Varat ieslēgt mikrofona skaņu, ieslēgt kameru vai kopīgot ekrānu.",
"audioUnmuteBlockedDescription": "Mikrofona ieslēgšanas darbība ir īslaicīgi bloķēta sistēmas ierobežojumu dēļ.",
@@ -807,7 +765,6 @@
"dataChannelClosedDescription": "Savienojuma kanāls nedarbojas, tāpēc video kvalitāte var būt ierobežota līdz zemākajam iestatījumam.",
"dataChannelClosedDescriptionWithAudio": "Savienojuma kanāls nedarbojas, tāpēc var rasties audio un video traucējumi.",
"dataChannelClosedWithAudio": "Audio un video kvalitāte var būt traucēta",
"desktopMutedRemotelyTitle": "",
"disabledIframe": "Iegulšana ir paredzēta tikai demonstrācijas nolūkiem, tāpēc šis zvans tiks atvienots pēc {{timeout}} minūtēm.",
"disabledIframeSecondaryNative": "Domēna {{domain}} iegulšana ir paredzēta tikai demonstrācijas nolūkiem, tāpēc šis zvans tiks pārtraukts pēc {{timeout}} minūtēm.",
"disabledIframeSecondaryWeb": "Domēna {{domain}} iegulšana ir paredzēta tikai demonstrācijas nolūkiem, tāpēc šis zvans tiks pārtraukts pēc {{timeout}} minūtēm. Lūdzu, produkcijas videi izmantojiet <a href='{{jaasDomain}}' rel='noopener noreferrer' target='_blank'>Jitsi as a Service</a>!",
@@ -888,7 +845,6 @@
"suggestRecordingDescription": "Vai vēlaties sākt ierakstīšanu?",
"suggestRecordingTitle": "Ierakstīt sanāksmi",
"unmute": "Ieslēgt mikrofonu",
"unmuteScreen": "",
"unmuteVideo": "Ieslēgt video",
"videoMutedRemotelyDescription": "Jūs vienmēr varat to atkal ieslēgt.",
"videoMutedRemotelyTitle": "{{participantDisplayName}} izslēdza jūsu video",
@@ -908,14 +864,11 @@
"admit": "Apstiprināt",
"admitAll": "Apstiprināt visus",
"allow": "Atļaut dalībniekiem:",
"allowDesktop": "Atļaut ekrāna kopīgošanu",
"allowVideo": "Atļaut video",
"askDesktop": "Lūgt kopīgot ekrānu",
"askUnmute": "Lūgt ieslēgt skaņu",
"audioModeration": "Ieslēgt savu skaņu",
"blockEveryoneMicCamera": "Bloķēt visiem mikrofonu un kameru",
"breakoutRooms": "Grupu istabas",
"desktopModeration": "Sākt ekrāna kopīgošanu",
"goLive": "Sākt",
"invite": "Uzaicināt",
"lowerAllHands": "Nolaist visas paceltās rokas",
@@ -927,8 +880,6 @@
"muteAll": "Apklusināt visus",
"muteEveryoneElse": "Apklusināt pārējos",
"reject": "Noraidīt",
"stopDesktop": "Pārtraukt ekrāna kopīgošanu",
"stopEveryonesDesktop": "Pārtraukt visiem ekrāna kopīgošanu",
"stopEveryonesVideo": "Izslēgt visiem video",
"stopVideo": "Izslēgt video",
"unblockEveryoneMicCamera": "Atbloķēt visiem mikrofonu un kameru",
@@ -938,11 +889,9 @@
"headings": {
"lobby": "Vestibils ({{count}})",
"participantsList": "Sapulces dalībnieki ({{count}})",
"viewerRequests": "Apmeklētāju pieprasījumi {{count}}",
"visitorInQueue": " (gaida {{count}})",
"visitorRequests": " (pieprasījumi {{count}})",
"visitors": "Apmeklētāji {{count}}",
"visitorsList": "Apmeklētāji ({{count}})",
"visitors": "Apmeklētāji ({{count}})",
"waitingLobby": "Gaida vestibilā ({{count}})"
},
"search": "Meklēt dalībniekus",
@@ -1535,8 +1484,6 @@
"connectionInfo": "Informācija par savienojumu",
"demote": "Pārveidot par apmeklētāju",
"domute": "Izlsēgt skaņu",
"domuteDesktop": "Pārtraukt ekrāna kopīgošanu",
"domuteDesktopOfOthers": "Pārtraukt ekrāna kopīgošanu visiem pārējiem",
"domuteOthers": "Izslēgt skaņu visiem pārējiem",
"domuteVideo": "Izslēgt kameru",
"domuteVideoOfOthers": "Izslēgt video visiem pārējiem",

View File

@@ -109,10 +109,8 @@
}
},
"chat": {
"disabled": "O envio de mensagens de chat está desativado.",
"enter": "Entrar na sala",
"error": "Erro: a sua mensagem não foi enviada. Motivo: {{error}}",
"everyone": "Todos",
"fieldPlaceHolder": "Aa",
"lobbyChatMessageTo": "Mensagem de chat na sala de espera para {{recipient}}",
"message": "Mensagem",
@@ -124,10 +122,7 @@
"nickname": {
"popover": "Escolha um apelido",
"title": "Introduza um apelido para usar o chat",
"titleWithCC": "Insira um apelido para usar o chat e as legendas ocultas",
"titleWithPolls": "Digite um apelido para usar o chat e as sondagens",
"titleWithPollsAndCC": "Insira um apelido para utilizar o chat, as sondagens e as legendas ocultas",
"titleWithPollsAndCCAndFileSharing": "Insira um apelido para utilizar o chat, as sondagens, as legendas e os ficheiros"
"titleWithPolls": "Introduza um apelido para usar o chat e as sondagens"
},
"noMessagesMessage": "Ainda não há mensagens na reunião. Comece aqui uma conversa!",
"privateNotice": "Mensagem privada para {{recipient}}",
@@ -136,15 +131,10 @@
"systemDisplayName": "Sistema",
"tabs": {
"chat": "Chat",
"closedCaptions": "LO",
"fileSharing": "Ficheiros",
"polls": "Sondagens"
},
"title": "Chat",
"titleWithCC": "LO",
"titleWithFeatures": "Chat e",
"titleWithFileSharing": "Ficheiros",
"titleWithPolls": "Sondagens",
"titleWithPolls": "Chat e Sondagens",
"you": "você"
},
"chromeExtensionBanner": {
@@ -154,10 +144,6 @@
"dontShowAgain": "Não me mostre isto outra vez",
"installExtensionText": "Instalar a extensão para a integração Google Calendar e Office 365"
},
"closedCaptionsTab": {
"emptyState": "O conteúdo das legendas ocultas estará disponível assim que um moderador iniciar a sessão.",
"startClosedCaptionsButton": "Iniciar legendas ocultas"
},
"connectingOverlay": {
"joiningRoom": "A ligá-lo à reunião…"
},
@@ -277,8 +263,6 @@
"Remove": "Remover",
"Share": "Partilhar",
"Submit": "Submeter",
"Understand": "Entendo, mantenha-me em silêncio por enquanto.",
"UnderstandAndUnmute": "Entendo, por favor, desative o silêncio.",
"WaitForHostMsg": "A conferência ainda não começou porque ainda não chegaram moderadores. Se quiser ser um moderador, inicie a sessão. Caso contrário, aguarde.",
"WaitForHostNoAuthMsg": "A conferência ainda não começou porque ainda não chegaram os moderadores. Por favor, aguarde.",
"WaitingForHostButton": "Esperar pelo moderador",
@@ -301,12 +285,6 @@
"alreadySharedVideoTitle": "Só é permitido um vídeo partilhado de cada vez",
"applicationWindow": "Janela de aplicação",
"authenticationRequired": "Autenticação necessária",
"cameraCaptureDialog": {
"description": "Tire e envie uma foto usando a câmara do seu telemóvel",
"ok": "Ligar a câmara",
"reject": "Agora não",
"title": "Tire uma foto"
},
"cameraConstraintFailedError": "A sua câmara não satisfaz algumas das restrições exigidas.",
"cameraNotFoundError": "A câmara não foi encontrada.",
"cameraNotSendingData": "Não podemos aceder à sua câmara. Verifique se outra aplicação está a utilizar este dispositivo, seleccione outro dispositivo do menu de definições ou tente recarregar a aplicação.",
@@ -321,7 +299,6 @@
"conferenceReloadMsg": "Estamos a tentar resolver isto. Reconexão em {{seconds}} seg…",
"conferenceReloadTitle": "Infelizmente, algo correu mal.",
"confirm": "Confirme",
"confirmBack": "Voltar",
"confirmNo": "Não",
"confirmYes": "Sim",
"connectError": "Oops! Algo correu mal e não conseguimos estabelecer uma ligação com a conferência.",
@@ -330,8 +307,8 @@
"contactSupport": "Contacte o suporte",
"copied": "Copiado",
"copy": "Cópia",
"demoteParticipantDialog": "Tem a certeza de que deseja mover este participante para espectador?",
"demoteParticipantTitle": "Mover para espectador",
"demoteParticipantDialog": "Tem a certeza de que pretende passar este participante para visitante?",
"demoteParticipantTitle": "Passar a visitante",
"dismiss": "Dispensar",
"displayNameRequired": "Olá! Qual é o seu nome?",
"done": "Feito",
@@ -357,9 +334,7 @@
"kickParticipantButton": "Expulsar",
"kickParticipantDialog": "Tem a certeza que quer expulsar este participante?",
"kickParticipantTitle": "Expulsar este participante?",
"kickSystemTitle": "Ai! Foste expulso da reunião.",
"kickTitle": "Ai! {{participantDisplayName}} expulsou-o da reunião",
"learnMore": "saiba mais",
"linkMeeting": "Link da reunião",
"linkMeetingTitle": "Link da reunião à Força de Vendas",
"liveStreaming": "Transmissão em direto",
@@ -381,35 +356,23 @@
"micPermissionDeniedError": "Não concedeu autorização para utilizar o seu microfone. Ainda pode participar na conferência, mas outros não o ouvirão. Use o botão da câmara na barra de endereço para corrigir isto.",
"micTimeoutError": "Não foi possível iniciar a fonte de áudio. Tempo limite expirado!",
"micUnknownError": "Não pode usar microfone por uma razão desconhecida.",
"moderationAudioLabel": "Permitir aos não moderadores ligar o som",
"moderationDesktopLabel": "Permitir que não moderadores partilhem o seu ecrã",
"moderationVideoLabel": "Permitir que não moderadores iniciem os seus vídeos",
"moderationAudioLabel": "Permitir aos participantes ligar o som",
"moderationVideoLabel": "Permitir aos participantes ligar a câmara",
"muteEveryoneDialog": "Os participantes podem ligar o som a qualquer momento.",
"muteEveryoneDialogModerationOn": "Os participantes podem enviar um pedido para falar a qualquer momento.",
"muteEveryoneElseDialog": "Uma vez silenciados, não poderá reativá-los, mas eles podem ligar o microfone a qualquer momento.",
"muteEveryoneElseTitle": "Silenciar todos excepto {{whom}}?",
"muteEveryoneElsesDesktopDialog": "Depois que o compartilhamento for interrompido, não será possível reiniciá-lo, mas eles poderão fazê-lo a qualquer momento.",
"muteEveryoneElsesDesktopTitle": "SInterromper a partilha de ecrã de todos, exceto {{whom}}?",
"muteEveryoneElsesVideoDialog": "Quando a câmara for desligada, não poderá voltar a ligá-la, mas eles podem voltar a ligá-la em qualquer momento.",
"muteEveryoneElsesVideoTitle": "Parar o vídeo de todos excepto {{whom}}?",
"muteEveryoneSelf": "você mesmo",
"muteEveryoneStartMuted": "A partir de agora, toda a gente começa a ficar calada",
"muteEveryoneTitle": "Silenciar toda a gente?",
"muteEveryonesDesktopDialog": "Os participantes podem partilhar o seu ecrã a qualquer momento.",
"muteEveryonesDesktopDialogModerationOn": "Os participantes podem enviar um pedido para partilhar o seu ecrã a qualquer momento.",
"muteEveryonesDesktopTitle": "Interromper a partilha de ecrã de todos?",
"muteEveryonesVideoDialog": "Os participantes podem ligar a sua câmara a qualquer momento.",
"muteEveryonesVideoDialogModerationOn": "Os participantes podem enviar um pedido para ligar a sua câmara a qualquer momento.",
"muteEveryonesVideoDialogOk": "Desativar",
"muteEveryonesVideoTitle": "Desligar a câmara de todos?",
"muteParticipantBody": "Não poderá reativá-los, mas eles podem reativar-se a qualquer momento.",
"muteParticipantButton": "Silenciar",
"muteParticipantsDesktopBody": "Não poderá iniciar a partilha de ecrã deles, mas eles podem fazê-lo a qualquer momento.",
"muteParticipantsDesktopBodyModerationOn": "Não será possível iniciar a partilha de ecrã nem para si nem para eles.",
"muteParticipantsDesktopButton": "Parar a partilha de ecrã",
"muteParticipantsDesktopDialog": "Tem a certeza de que deseja desativar a partilha de ecrã deste participante? Não será possível reiniciá-la, mas ele poderá fazê-lo a qualquer momento.",
"muteParticipantsDesktopDialogModerationOn": "Tem a certeza de que deseja desativar a partilha de ecrã deste participante? Não será possível reativar o ecrã, nem para si nem para ele.",
"muteParticipantsDesktopTitle": "Desativar a partilha de ecrã deste participante?",
"muteParticipantsVideoBody": "Não poderá voltar a ligar a câmara, mas eles podem voltar a ligá-la a qualquer momento.",
"muteParticipantsVideoBodyModerationOn": "Não será capaz de voltar a ligar a câmara e eles também não.",
"muteParticipantsVideoButton": "Parar vídeo",
@@ -429,10 +392,6 @@
"recentlyUsedObjects": "Os seus objetos recentemente utilizados",
"recording": "A gravar",
"recordingDisabledBecauseOfActiveLiveStreamingTooltip": "Não possível enquanto a transmissão em direto estiver activa",
"recordingInProgressDescription": "Esta reunião está a ser gravada e analisada pela IA{{learnMore}}. O seu áudio e vídeo foram silenciados. Se optar por ativar o som, concorda em ser gravado.",
"recordingInProgressDescriptionFirstHalf": "Esta reunião está a ser gravada e analisada por IA.",
"recordingInProgressDescriptionSecondHalf": ". Your audio and video have been muted. If you choose to unmute, you consent to being recorded.",
"recordingInProgressTitle": "Gravação em andamento",
"rejoinNow": "Reingressar agora",
"remoteControlAllowedMessage": "{{user}} aceitou o seu pedido de controlo remoto!",
"remoteControlDeniedMessage": "{{user}} rejeitou o seu pedido de controlo remoto!",
@@ -480,10 +439,7 @@
"shareScreenWarningD2": "é necessário parar a partilha de áudio, iniciar a partilha de ecrã e verificar a opção \"partilhar áudio\".",
"shareScreenWarningH1": "Se quiser partilhar apenas o seu ecrã:",
"shareScreenWarningTitle": "Tem de parar a partilha de áudio antes de partilhar o seu ecrã",
"shareVideoConfirmPlay": "Está prestes a abrir um site externo. Deseja continuar?",
"shareVideoConfirmPlayTitle": "{{name}} partilhou um vídeo consigo.",
"shareVideoLinkError": "Oops, este vídeo não pode ser reproduzido.",
"shareVideoLinkStopped": "O vídeo de {{name}} foi interrompido.",
"shareVideoLinkError": "Por favor, forneça um link correcto do vídeo.",
"shareVideoTitle": "Partilhar vídeo",
"shareYourScreen": "Partilhe o seu ecrã",
"shareYourScreenDisabled": "Partilha de ecrã desactivada.",
@@ -562,21 +518,6 @@
"veryBad": "Muito má",
"veryGood": "Muito boa"
},
"fileSharing": {
"downloadFailedDescription": "Por favor, tente novamente.",
"downloadFailedTitle": "Falha no descarregar",
"downloadFile": "Descarregar",
"dragAndDrop": "Arraste e solte os ficheiros aqui ou em qualquer lugar do ecrã",
"fileAlreadyUploaded": "O ficheiro já foi carregado para esta reunião.",
"fileTooLargeDescription": "Certifique-se de que o ficheiro não exceda {{ maxFileSize }}.",
"fileTooLargeTitle": "O ficheiro selecionado é muito grande",
"fileUploadProgress": "Progresso do envio do ficheiro",
"fileUploadedSuccessfully": "Ficheiro carregado com sucesso",
"removeFile": "Remover",
"uploadFailedDescription": "Por favor, tente novamente.",
"uploadFailedTitle": "Falha ao carregar",
"uploadFile": "Partilhar ficheiro"
},
"filmstrip": {
"accessibilityLabel": {
"heading": "Miniaturas de vídeo"
@@ -697,7 +638,6 @@
"on": "Iniciada a transmissão em direto",
"onBy": "{{name}} iniciou a transmissão em direto",
"pending": "Início da transmissão em direto…",
"policyError": "Tentou iniciar uma transmissão ao vivo muito rapidamente. Por favor, tente novamente mais tarde!",
"serviceName": "Serviço de Transmissão em Direto",
"sessionAlreadyActive": "Esta sessão já está a ser gravada ou transmitida em direto.",
"signIn": "Iniciar sessão com o Google",
@@ -788,10 +728,7 @@
"me": "eu",
"notify": {
"OldElectronAPPTitle": "Vulnerabilidade de segurança!",
"allowAll": "Permitir tudo",
"allowAudio": "Permitir áudio",
"allowDesktop": "Permitir partilha de ecrã",
"allowVideo": "Permitir vídeo",
"allowAction": "Permitir",
"allowedUnmute": "Pode ligar o seu microfone, ligar a sua câmara ou partilhar o seu ecrã.",
"audioUnmuteBlockedDescription": "A operação de ligar o microfone foi temporariamente bloqueada devido aos limites do sistema.",
"audioUnmuteBlockedTitle": "Ligar microfone bloqueado!",
@@ -799,15 +736,12 @@
"connectedOneMember": "{{name}} entrou na reunião",
"connectedThreePlusMembers": "{{name}} e muitos outros entraram na reunião",
"connectedTwoMembers": "{{first}} e {{second}} entraram na reunião",
"connectionFailed": "Falha na ligação. Por favor, tente novamente mais tarde!",
"dataChannelClosed": "A qualidade do vídeo pode ser afetada",
"dataChannelClosedDescription": "O canal de ponte está em baixo e, por isso, a qualidade de vídeo pode estar limitada à sua definição mais baixa.",
"dataChannelClosedDescriptionWithAudio": "O canal de ponte está em baixo, pelo que podem ocorrer interrupções no áudio e no vídeo.",
"dataChannelClosedWithAudio": "A qualidade do áudio e do vídeo pode ser afetada",
"desktopMutedRemotelyTitle": "A partilha do seu ecrã foi interrompida por {{participantDisplayName}}",
"disabledIframe": "A incorporação destina-se apenas a fins de demonstração, pelo que esta chamada será desligada em {{timeout}} minutos.",
"disabledIframeSecondaryNative": "A incorporação de {{domain}} destina-se apenas a fins de demonstração, pelo que esta chamada será desligada em {{timeout}} minutos.",
"disabledIframeSecondaryWeb": "A incorporação de {{domain}} destina-se apenas a fins de demonstração, pelo que esta chamada será desligada em {{timeout}} minutos. Utilize <a href='{{jaasDomain}}' rel='noopener noreferrer' target='_blank'>Jitsi as a Service</a> para incorporação em produção!",
"disabledIframeSecondary": "A incorporação de {{domain}} destina-se apenas a fins de demonstração, pelo que esta chamada será desligada em {{timeout}} minutos. Por favor, use <a href='{{jaasDomain}}' rel='noopener noreferrer' target='_blank'>Jitsi as a Service</a> para incorporação em produção!",
"disconnected": "desconectado",
"displayNotifications": "Mostrar notificações para",
"dontRemindMe": "Não me lembre",
@@ -815,10 +749,7 @@
"focusFail": "{{component}} não disponĩvel - tente em {{ms}} seg.",
"gifsMenu": "GIPHY",
"groupTitle": "Notificações",
"hostAskedUnmute": "O moderador gostaria que participasse.",
"invalidTenant": "Tenant inválido",
"invalidTenantHyphenDescription": "O tenant que está a utilizar é inválido (começa ou termina com '-').",
"invalidTenantLengthDescription": "O tenant que está a utilizar é demasiado longo.",
"hostAskedUnmute": "O moderador gostaria que você falasse",
"invitedOneMember": "{{displayName}} foi convidado",
"invitedThreePlusMembers": "{{name}} e {{count}} outros foram convidados",
"invitedTwoMembers": "{{first}} e {{second}} foram convidados",
@@ -856,9 +787,9 @@
"newDeviceAudioTitle": "Novo dispositivo de áudio detetado",
"newDeviceCameraTitle": "Nova câmara detetada",
"nextToSpeak": "É o próximo na fila para falar",
"noiseSuppressionDesktopAudioDescription": "A supressão de ruído extra não pode ser ativada enquanto estiver a partilhar o áudio do ambiente de trabalho. Desative-a e tente novamente.",
"noiseSuppressionFailedTitle": "Falha ao iniciar a supressão de ruído extra",
"noiseSuppressionStereoDescription": "Atualmente, a supressão extra de ruído não é suportada com áudio estéreo.",
"noiseSuppressionDesktopAudioDescription": "A supressão de ruído não pode ser ativada enquanto se partilha o áudio do ambiente de trabalho, por favor desative-o e tente novamente.",
"noiseSuppressionFailedTitle": "Falha ao iniciar a supressão de ruído",
"noiseSuppressionStereoDescription": "A supressão do ruído de áudio estéreo não é atualmente suportada.",
"oldElectronClientDescription1": "Parece estar a utilizar uma versão antiga do cliente Jitsi Meet que tem vulnerabilidades de segurança conhecidas. Por favor, certifique-se de que actualiza a nossa ",
"oldElectronClientDescription2": "compilação mais recente",
"oldElectronClientDescription3": " agora!",
@@ -867,7 +798,7 @@
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) removido por outro participante",
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) definido por outro participante",
"raiseHandAction": "Levantar a mão",
"raisedHand": "Gostaria de participar.",
"raisedHand": "Gostaria de falar.",
"raisedHands": "{{participantName}} e mais {{raisedHands}} pessoas",
"reactionSounds": "Desactivar sons",
"reactionSoundsForAll": "Desativar sons para todos",
@@ -885,17 +816,15 @@
"suggestRecordingDescription": "Gostaria de iniciar uma gravação?",
"suggestRecordingTitle": "Gravar esta reunião",
"unmute": "Ligar microfone",
"unmuteScreen": "Iniciar partilha de ecrã",
"unmuteVideo": "Ligar câmara",
"videoMutedRemotelyDescription": "Pode sempre ligá-la novamente.",
"videoMutedRemotelyTitle": "A sua câmara foi desligada pelo {{participantDisplayName}}.",
"videoUnmuteBlockedDescription": "A operação de ligar a câmara e partilhar o ambiente de trabalho foi temporariamente bloqueada devido aos limites do sistema.",
"videoUnmuteBlockedTitle": "Está bloqueado ligar a câmara e partilhar o ambiente de trabalho!",
"viewLobby": "Ver sala de espera",
"viewParticipants": "Ver participantes",
"viewVisitors": "Visualizar espectadores",
"viewVisitors": "Ver visitantes",
"waitingParticipants": "{{waitingParticipants}} pessoas",
"waitingVisitors": "Espectadores em fila de espera: {{waitingVisitors}}",
"waitingVisitors": "Visitantes em fila de espera: {{waitingVisitors}}",
"waitingVisitorsTitle": "A reunião ainda não está em direto!",
"whiteboardLimitDescription": "Guarde o seu progresso, pois o limite de utilizadores será atingido em breve e o quadro branco será encerrado.",
"whiteboardLimitTitle": "Utilização do quadro branco"
@@ -904,17 +833,14 @@
"actions": {
"admit": "Aceitar",
"admitAll": "Aceitar todos",
"allow": "Permitir que os não moderadores:",
"allowDesktop": "Permitir partilha de ecrã",
"allow": "Permitir aos participantes:",
"allowVideo": "Permitir vídeo",
"askDesktop": "Pedir para partilhar o ecrã",
"askUnmute": "Pedir para ligar o som",
"audioModeration": "Ligar o microfone deles",
"blockEveryoneMicCamera": "Bloquear o microfone e a câmara de todos",
"breakoutRooms": "Salas simultâneas",
"desktopModeration": "Iniciar partilha de ecrã",
"goLive": "Aceder ao vivo",
"invite": "Convide alguém",
"invite": "Convidar alguém",
"lowerAllHands": "Baixar todas as mãos",
"lowerHand": "Baixar a mão",
"moreModerationActions": "Mais opções de moderação",
@@ -924,8 +850,6 @@
"muteAll": "Silenciar todos",
"muteEveryoneElse": "Silenciar todos os outros",
"reject": "Rejeitar",
"stopDesktop": "Parar a partilha de ecrã",
"stopEveryonesDesktop": "Interromper a partilha de ecrã de todos",
"stopEveryonesVideo": "Desligar a câmara de todos",
"stopVideo": "Desligar a câmara",
"unblockEveryoneMicCamera": "Desbloquear o microfone e a câmara de todos",
@@ -935,15 +859,12 @@
"headings": {
"lobby": "Sala de espera ({{count}})",
"participantsList": "Participantes da reunião ({{count}})",
"viewerRequests": "Pedidos dos espectadores {{count}}",
"visitorInQueue": " (à espera {{count}})",
"visitorRequests": " (pedidos {{count}})",
"visitors": "Espectadores ({{count}})",
"visitorsList": "Espectadores ({{count}})",
"visitors": "Visitantes ({{count}})",
"waitingLobby": "Aguardam na sala de espera ({{count}})"
},
"search": "Pesquisar participantes",
"searchDescription": "Comece a digitar para filtrar os participantes",
"title": "Participantes"
},
"passwordDigitsOnly": "Até {{number}} dígitos",
@@ -980,7 +901,7 @@
},
"results": {
"changeVote": "Mudar o voto",
"empty": "Ainda não há sondagens na reunião.",
"empty": "Ainda não há sondagens na reunião. Comece aqui uma sondagem!",
"hideDetailedResults": "Ocultar detalhes",
"showDetailedResults": "Mostrar detalhes",
"vote": "Voto"
@@ -998,11 +919,9 @@
"configuringDevices": "A configurar os dispositivos…",
"connectedWithAudioQ": "Está ligado com áudio?",
"connection": {
"failed": "Falha no teste de ligação!",
"good": "A sua ligação à Internet parece boa!",
"nonOptimal": "A sua ligação à Internet não é óptima",
"poor": "Tem uma ligação à Internet fraca",
"running": "A realizar teste de ligação..."
"poor": "Tem uma ligação à Internet"
},
"connectionDetails": {
"audioClipping": "Prevemos que o seu áudio tenha cortes.",
@@ -1011,7 +930,6 @@
"goodQuality": "Fantástico! A qualidade dos seus meios de comunicação vai ser óptima.",
"noMediaConnectivity": "Não foi possível encontrar uma forma de estabelecer a conectividade dos meios de comunicação para este teste. Isto é tipicamente causado por uma firewall ou NAT.",
"noVideo": "Prevemos que o seu vídeo seja terrível.",
"testFailed": "O teste de ligação encontrou problemas inesperados, mas isso pode não afetar a sua experiência.",
"undetectable": "Se mesmo assim não conseguir fazer chamadas no browser, recomendamos que se certifique de que os seus altifalantes, microfone e câmara estão devidamente configurados, que concedeu ao seu browser direitos de utilização do seu microfone e câmara, e que a versão do seu browser está actualizada. Se mesmo assim tiver problemas em telefonar, deverá contactar o criador da aplicação web.",
"veryPoorConnection": "Prevemos que a qualidade da sua chamada seja realmente terrível.",
"videoFreezing": "Prevemos que o seu vídeo congele, fique preto, e seja pixelizado.",
@@ -1040,7 +958,7 @@
"joinWithoutAudio": "Entrar sem áudio",
"keyboardShortcuts": "Ativar os atalhos de teclado",
"linkCopied": "Link copiado para a área de transferência",
"lookGood": "Os seus dispositivos estão a funcionar corretamente",
"lookGood": "Tudo está a funcionar corretamente",
"or": "ou",
"premeeting": "Pré-reunião",
"proceedAnyway": "Continuar na mesma",
@@ -1126,7 +1044,6 @@
"onBy": "{{name}} iniciou a gravação",
"onlyRecordSelf": "Gravar apenas as minhas transmissões áudio e vídeo",
"pending": "Preparando para gravar a reunião…",
"policyError": "Tentou iniciar uma gravação muito rapidamente. Por favor, tente novamente mais tarde!",
"recordAudioAndVideo": "Gravar áudio e vídeo",
"recordTranscription": "Gravar transcrições",
"saveLocalRecording": "Guardar ficheiro de gravação localmente (Beta)",
@@ -1170,13 +1087,11 @@
"signedIn": "Atualmente a aceder a eventos de calendário por {{email}}. Clique no botão Desconectar abaixo para parar de aceder a eventos de calendário.",
"title": "Calendário"
},
"chatWithPermissions": "O chat requer permissão",
"desktopShareFramerate": "Taxa de fotogramas para partilha do ambiente de trabalho",
"desktopShareHighFpsWarning": "Uma taxa de fotogramas mais elevada para a partilha do ambiente de trabalho pode afectar a sua largura de banda. É necessário reiniciar a partilha de ecrã para que as novas definições entrem em vigor.",
"desktopShareWarning": "É necessário reiniciar a partilha do ecrã para que as novas definições entrem em vigor.",
"devices": "Dispositivos",
"followMe": "Todos me seguem",
"followMeRecorder": "O gravador segue-me",
"framesPerSecond": "fotogramas-por-segundo",
"incomingMessage": "Receber uma mensagem",
"language": "Idioma",
@@ -1200,7 +1115,6 @@
"selectMic": "Microfone",
"selfView": "Autovisualização",
"shortcuts": "Atalhos",
"showSubtitlesOnStage": "Mostrar legendas",
"speakers": "Altifalantes",
"startAudioMuted": "Todos começam com microfone desligado",
"startReactionsMuted": "Todos começam com os sons de reação desativados",
@@ -1254,13 +1168,11 @@
"fearful": "Temeroso",
"happy": "Feliz",
"hours": "{{count}}h",
"labelTooltip": "Número de participantes: {{count}}",
"minutes": "{{count}}m",
"name": "Nome",
"neutral": "Neutro",
"sad": "Triste",
"search": "Pesquisar",
"searchDescription": "Comece a digitar para filtrar os participantes",
"searchHint": "Pesquisar participantes",
"seconds": "{{count}}s",
"speakerStats": "Estatísticas dos Participantes",
@@ -1297,7 +1209,6 @@
"closeChat": "Fechar chat",
"closeMoreActions": "Fechar menu de mais ações",
"closeParticipantsPane": "Fechar painel de participantes",
"closedCaptions": "Legendas ocultas",
"collapse": "Colapsar",
"document": "Mudar para documento partilhado",
"documentClose": "Fechar documento partilhado",
@@ -1327,7 +1238,6 @@
"lobbyButton": "Ativar/desativar sala de espera",
"localRecording": "Mudar os controlos locais de gravação",
"lockRoom": "Mudar palavra-chave de reunião",
"love": "Coração",
"lowerHand": "Baixar a mão",
"moreActions": "Mais ações",
"moreActionsMenu": "Menu de mais ações",
@@ -1338,14 +1248,13 @@
"muteEveryoneElsesVideo": "Parar o vídeo de todos os outros",
"muteEveryonesVideo": "Parar o vídeo de todos",
"muteGUMPending": "A ligar o seu microfone",
"noiseSuppression": "Supressão extra de ruído (BETA)",
"noiseSuppression": "Supressão de ruído",
"openChat": "Abrir chat",
"participants": "Abrir painel de participantes. {{participantsCount}} participantes",
"participants": "Abrir painel de participantes",
"pip": "Mudar para o modo Picture-in-Picture",
"privateMessage": "Enviar mensagem privada",
"profile": "Editar o seu perfil",
"raiseHand": "Levantar a mão",
"react": "Reações às mensagens",
"reactions": "Reações",
"reactionsMenu": "Menu de reações",
"recording": "Mudar gravação",
@@ -1388,15 +1297,14 @@
"closeChat": "Fechar chat",
"closeParticipantsPane": "Fechar painel de participantes",
"closeReactionsMenu": "Fechar menu de reações",
"closedCaptions": "Legendas ocultas",
"disableNoiseSuppression": "Desativar supressão de ruído extra (BETA)",
"disableNoiseSuppression": "Desativar a supressão de ruído",
"disableReactionSounds": "Pode desactivar os sons de reacção para esta reunião",
"documentClose": "Fechar documento partilhado",
"documentOpen": "Abrir documento partilhado",
"download": "Descarregar as nossas aplicações",
"e2ee": "Criptografia ponta a ponta",
"embedMeeting": "Incorporar reunião",
"enableNoiseSuppression": "Ativar supressão extra de ruído (BETA)",
"enableNoiseSuppression": "Ativar a supressão de ruído",
"endConference": "Terminar reunião para todos",
"enterFullScreen": "Ver em ecrã completo",
"enterTileView": "Ver em quadrícula",
@@ -1418,7 +1326,6 @@
"lobbyButtonEnable": "Ativar sala de espera",
"login": "Iniciar sessão",
"logout": "Terminar sessão",
"love": "Coração",
"lowerYourHand": "Baixar a mão",
"moreActions": "Mais ações",
"moreOptions": "Mais opções",
@@ -1431,7 +1338,7 @@
"noAudioSignalDialInDesc": "Também pode marcar usando:",
"noAudioSignalDialInLinkDesc": "Números de marcação",
"noAudioSignalTitle": "Não há nenhuma entrada vinda do seu microfone!",
"noiseSuppression": "Supressão extra de ruído (BETA)",
"noiseSuppression": "Supressão de ruído",
"noisyAudioInputDesc": "Parece que o seu microfone está a fazer barulho, por favor considere silenciar ou mudar de dispositivo.",
"noisyAudioInputTitle": "Seu microfone parece estar barulhento!",
"openChat": "Abrir chat",
@@ -1444,7 +1351,6 @@
"raiseYourHand": "Levantar a mão",
"reactionBoo": "Enviar reação de vaia",
"reactionClap": "Enviar reação de aplausos",
"reactionHeart": "Enviar reação com coração",
"reactionLaugh": "Enviar reação de risos",
"reactionLike": "Enviar reação de aprovado",
"reactionSilence": "Enviar reação de silêncio",
@@ -1478,19 +1384,15 @@
"transcribing": {
"ccButtonTooltip": "Iniciar/parar legendas",
"expandedLabel": "Transcrição ativada",
"failed": "Falha na transcrição",
"labelTooltip": "Esta reunião está a ser transcrita.",
"labelTooltipExtra": "Além disso, uma transcrição estará disponível posteriormente.",
"openClosedCaptions": "Abrir legendas ocultas",
"original": "Original",
"failedToStart": "Transcrição falhou ao iniciar",
"labelToolTip": "A reunião esta sendo transcrita",
"sourceLanguageDesc": "Atualmente a língua da reunião está definida para <b>{{sourceLanguage}}</b>. <br/> Pode alterá-la a partir ",
"sourceLanguageHere": "daqui",
"start": "Exibir legendas",
"stop": "Não exibir legendas",
"subtitles": "Legendas",
"subtitlesOff": "Desligado",
"tr": "TR",
"translateTo": "Traduzir para"
"tr": "TR"
},
"unpinParticipant": "{{participantName}} - Desafixar",
"userMedia": {
@@ -1522,7 +1424,7 @@
"ldTooltip": "Ver vídeo em baixa definição",
"lowDefinition": "Baixa definição (LD)",
"performanceSettings": "Definições de desempenho",
"recording": "Esta reunião está a ser gravada.",
"recording": "Gravação em curso",
"sd": "SD",
"sdTooltip": "Ver vídeo em definição padrão",
"standardDefinition": "Definição padrão",
@@ -1530,10 +1432,8 @@
},
"videothumbnail": {
"connectionInfo": "Informações sobre a ligação",
"demote": "Passar a espectador",
"demote": "Passar a visitante",
"domute": "Sem som",
"domuteDesktop": "Parar a partilha de ecrã",
"domuteDesktopOfOthers": "Interromper a partilha de ecrã para todos os outros",
"domuteOthers": "Silenciar todos os outros",
"domuteVideo": "Desativar a câmara",
"domuteVideoOfOthers": "Desactivar a câmara de todos os outros",
@@ -1584,21 +1484,21 @@
"webAssemblyWarningDescription": "WebAssembly desactivado ou não suportado por este navegador"
},
"visitors": {
"chatIndicator": "(espectador)",
"chatIndicator": "(visitante)",
"joinMeeting": {
"description": "Atualmente, é um espectador nesta conferência.",
"description": "Atualmente, é um observador nesta conferência.",
"raiseHand": "Levantar a mão",
"title": "Participar na reunião",
"wishToSpeak": "Se deseja intervir, levante a mão e aguarde a aprovação do moderador."
},
"labelTooltip": "Número de espectadores: {{count}}",
"labelTooltip": "Número de visitantes: {{count}}",
"notification": {
"demoteDescription": "Enviado aqui pelo {{actor}}, levante a mão para participar",
"noMainParticipantsDescription": "Um participante precisa de iniciar a reunião. Tente novamente daqui a pouco.",
"noMainParticipantsTitle": "Esta reunião ainda não começou.",
"noVisitorLobby": "Não é possível aderir enquanto houver uma sala de espera activada para a reunião.",
"notAllowedPromotion": "É necessário que um participante autorize primeiro o seu pedido.",
"title": "É um espectador na reunião"
"title": "É um visitante na reunião"
},
"waitingMessage": "Participará na reunião assim que esta estiver em direto!"
},

File diff suppressed because it is too large Load Diff

View File

@@ -331,11 +331,11 @@
"internalError": "Ett fel uppstod. Fel: {{error}}",
"internalErrorTitle": "Internt fel",
"kickMessage": "Du kan kontakta {{participantDisplayName}} för mer information.",
"kickParticipantButton": "Ta bort från mötet",
"kickParticipantDialog": "Vill du ta bort denna deltagaren från mötet?",
"kickParticipantButton": "Sparka ut",
"kickParticipantDialog": "Vill du sparka ut den här deltagaren?",
"kickParticipantTitle": "Tysta deltagaren?",
"kickSystemTitle": "Du har blivit borttagen från mötet",
"kickTitle": "{{participantDisplayName}} tog bort dig från mötet",
"kickSystemTitle": "Aj! du blev utsparkad ur mötet",
"kickTitle": "Aj! {{participantDisplayName}} sparkade ut dig ur mötet",
"linkMeeting": "Länka möte",
"linkMeetingTitle": "Länka möte till Salesforce",
"liveStreaming": "Streama",
@@ -763,7 +763,7 @@
"invitedThreePlusMembers": "{{name}} och {{count}} andra har bjudits in",
"invitedTwoMembers": "{{first}} och {{second}} har bjudits in",
"joinMeeting": "Delta",
"kickParticipant": "{{kicked}} togs bort av {{kicker}}",
"kickParticipant": "{{kicked}} sparkades ut av {{kicker}}",
"leftOneMember": "{{name}} lämnade mötet",
"leftThreePlusMembers": "{{name}} och många andra lämnade mötet",
"leftTwoMembers": "{{first}} och {{second}} lämnade mötet",
@@ -1245,7 +1245,7 @@
"help": "Hjälp",
"hideWhiteboard": "Dölj whiteboard",
"invite": "Bjud in personer",
"kick": "Ta bort deltagare",
"kick": "Sparka ut deltagare",
"laugh": "Skratta",
"leaveConference": "Lämna mötet",
"like": "Tummen upp",
@@ -1459,7 +1459,7 @@
"flip": "Vänd",
"grantModerator": "Godkänn moderator",
"hideSelfView": "Dölj självvyn",
"kick": "Ta bort",
"kick": "Sparka ut",
"mirrorVideo": "Spegelvänd video",
"moderator": "Moderator",
"mute": "Deltagaren har avstängd mikrofon",

View File

@@ -112,9 +112,7 @@
"disabled": "Sending chat messages is disabled.",
"enter": "Enter room",
"error": "Error: your message was not sent. Reason: {{error}}",
"everyone": "Everyone",
"fieldPlaceHolder": "Aa",
"guestsChatIndicator": "(guest)",
"lobbyChatMessageTo": "Lobby chat message to {{recipient}}",
"message": "Message",
"messageAccessibleTitle": "{{user}} says:",
@@ -302,12 +300,6 @@
"alreadySharedVideoTitle": "Only one shared video is allowed at a time",
"applicationWindow": "Application window",
"authenticationRequired": "Authentication required",
"cameraCaptureDialog": {
"description": "Take and send a picture using your mobile camera",
"ok": "Open camera",
"reject": "Not now",
"title": "Take a picture"
},
"cameraConstraintFailedError": "Your camera does not satisfy some of the required constraints.",
"cameraNotFoundError": "Camera was not found.",
"cameraNotSendingData": "We are unable to access your camera. Please check if another application is using this device, select another device from the settings menu or try to reload the application.",
@@ -382,7 +374,7 @@
"micPermissionDeniedError": "You have not granted permission to use your microphone. You can still join the conference but others won't hear you. Use the camera button in the address bar to fix this.",
"micTimeoutError": "Could not start audio source. Timeout occurred!",
"micUnknownError": "Cannot use microphone for an unknown reason.",
"moderationAudioLabel": "Allow non-moderators to unmute themselves",
"moderationAudioLabel": "Allow attendees to unmute themselves",
"moderationDesktopLabel": "Allow non-moderators to share their screen",
"moderationVideoLabel": "Allow non-moderators to start their video",
"muteEveryoneDialog": "The participants can unmute themselves at any time.",
@@ -567,15 +559,11 @@
"downloadFailedDescription": "Please try again.",
"downloadFailedTitle": "Download failed",
"downloadFile": "Download",
"downloadStarted": "File download started",
"dragAndDrop": "Drag and drop files here or anywhere on screen",
"fileAlreadyUploaded": "File has already been uploaded to this meeting.",
"fileTooLargeDescription": "Please make sure the file does not exceed {{ maxFileSize }}.",
"fileTooLargeTitle": "The selected file is too large",
"fileUploadProgress": "File upload progress",
"fileUploadedSuccessfully": "File uploaded successfully",
"removeFile": "Remove",
"removeFileSuccess": "File removed successfully",
"uploadFailedDescription": "Please try again.",
"uploadFailedTitle": "Upload failed",
"uploadFile": "Share file"
@@ -865,7 +853,6 @@
"oldElectronClientDescription1": "You appear to be using an old version of the Jitsi Meet client which has known security vulnerabilities. Please make sure you update to our ",
"oldElectronClientDescription2": "latest build",
"oldElectronClientDescription3": " now!",
"openChat": "Open chat",
"participantWantsToJoin": "Wants to join the meeting",
"participantsWantToJoin": "Want to join the meeting",
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) removed by another participant",
@@ -1380,20 +1367,6 @@
"videounmute": "Start camera"
},
"addPeople": "Add people to your call",
"advancedAudioSettings": {
"aec": {
"label": "Acoustic echo cancellation"
},
"agc": {
"label": "Automatic gain control"
},
"ns": {
"label": "Noise suppression"
},
"stereo": {
"label": "Stereo"
}
},
"audioOnlyOff": "Disable low bandwidth mode",
"audioOnlyOn": "Enable low bandwidth mode",
"audioRoute": "Select the sound device",
@@ -1465,7 +1438,6 @@
"reactionHeart": "Send heart reaction",
"reactionLaugh": "Send laugh reaction",
"reactionLike": "Send thumbs up reaction",
"reactionLove": "Send love reaction",
"reactionSilence": "Send silence reaction",
"reactionSurprised": "Send surprised reaction",
"reactions": "Reactions",
@@ -1617,8 +1589,6 @@
"noMainParticipantsTitle": "This meeting hasn't started yet.",
"noVisitorLobby": "You cannot join while there is a lobby enabled for the meeting.",
"notAllowedPromotion": "A participant needs to allow your request first.",
"requestToJoin": "Hand Raised",
"requestToJoinDescription": "Your request was sent to the moderators. Hang tight!",
"title": "You are a viewer in the meeting"
},
"waitingMessage": "You'll join the meeting as soon as it is live!"

View File

@@ -30,7 +30,6 @@ import { overwriteConfig } from '../../react/features/base/config/actions';
import { getWhitelistedJSON } from '../../react/features/base/config/functions.any';
import { toggleDialog } from '../../react/features/base/dialog/actions';
import { isSupportedBrowser } from '../../react/features/base/environment/environment';
import { isMobileBrowser } from '../../react/features/base/environment/utils';
import { parseJWTFromURLParams } from '../../react/features/base/jwt/functions';
import JitsiMeetJS, { JitsiRecordingConstants } from '../../react/features/base/lib-jitsi-meet';
import { MEDIA_TYPE, VIDEO_TYPE } from '../../react/features/base/media/constants';
@@ -114,10 +113,7 @@ import { RECORDING_METADATA_ID, RECORDING_TYPES } from '../../react/features/rec
import { getActiveSession, supportsLocalRecording } from '../../react/features/recording/functions';
import { startAudioScreenShareFlow, startScreenShareFlow } from '../../react/features/screen-share/actions';
import { isScreenAudioSupported } from '../../react/features/screen-share/functions';
import {
openCameraCaptureDialog,
toggleScreenshotCaptureSummary
} from '../../react/features/screenshot-capture/actions';
import { toggleScreenshotCaptureSummary } from '../../react/features/screenshot-capture/actions';
import { isScreenshotCaptureEnabled } from '../../react/features/screenshot-capture/functions';
import SettingsDialog from '../../react/features/settings/components/web/SettingsDialog';
import { SETTINGS_TABS } from '../../react/features/settings/constants';
@@ -138,7 +134,7 @@ import {
ENDPOINT_TEXT_MESSAGE_NAME
} from './constants';
const logger = Logger.getLogger('api:core');
const logger = Logger.getLogger(__filename);
/**
* List of the available commands.
@@ -944,20 +940,6 @@ function initCommands() {
});
});
break;
case 'capture-camera-picture' : {
const { cameraFacingMode, descriptionText, titleText } = request;
if (!isMobileBrowser()) {
logger.error('This feature is only supported on mobile');
return;
}
APP.store.dispatch(openCameraCaptureDialog(callback, { cameraFacingMode,
descriptionText,
titleText }));
break;
}
case 'deployment-info':
callback(APP.store.getState()['features/base/config'].deploymentInfo);
break;

View File

@@ -820,27 +820,6 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
});
}
/**
* Captures a picture through OS camera.
*
* @param {string} cameraFacingMode - The OS camera facing mode (environment/user).
* @param {string} descriptionText - The OS camera facing mode (environment/user).
* @param {string} titleText - The OS camera facing mode (environment/user).
* @returns {Promise<string>} - Resolves with a base64 encoded image data of the screenshot.
*/
captureCameraPicture(
cameraFacingMode,
descriptionText,
titleText
) {
return this._transport.sendRequest({
name: 'capture-camera-picture',
cameraFacingMode,
descriptionText,
titleText
});
}
/**
* Removes the listeners and removes the Jitsi Meet frame.
*

View File

@@ -1,6 +1,6 @@
import Logger from '@jitsi/logger';
const logger = Logger.getLogger('api:external');
const logger = Logger.getLogger(__filename);
/**
* Returns Promise that resolves with result an list of available devices.

View File

@@ -28,7 +28,7 @@ import EtherpadManager from './etherpad/Etherpad';
import UIUtil from './util/UIUtil';
import VideoLayout from './videolayout/VideoLayout';
const logger = Logger.getLogger('ui:core');
const logger = Logger.getLogger(__filename);
let etherpadManager;

View File

@@ -45,7 +45,7 @@ import AudioLevels from '../audio_levels/AudioLevels';
import { VIDEO_CONTAINER_TYPE, VideoContainer } from './VideoContainer';
const logger = Logger.getLogger('ui:videolayout');
const logger = Logger.getLogger(__filename);
const DESKTOP_CONTAINER_TYPE = 'desktop';

View File

@@ -24,7 +24,7 @@ export const VIDEO_CONTAINER_TYPE = 'camera';
// Corresponds to animation duration from the animatedFadeIn and animatedFadeOut CSS classes.
const FADE_DURATION_MS = 300;
const logger = Logger.getLogger('ui:VideoContainer');
const logger = Logger.getLogger(__filename);
/**
* List of container events that we are going to process for the large video.

View File

@@ -16,7 +16,7 @@ import {
import LargeVideoManager from './LargeVideoManager';
import { VIDEO_CONTAINER_TYPE } from './VideoContainer';
const logger = Logger.getLogger('ui:VideoLayout');
const logger = Logger.getLogger(__filename);
let largeVideo;
const VideoLayout = {

View File

@@ -1,4 +1,4 @@
const logger = require('@jitsi/logger').getLogger('app:utils');
const logger = require('@jitsi/logger').getLogger(__filename);
/**
* Manages a queue of functions where the current function in progress will

746
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -23,10 +23,10 @@
"@emotion/styled": "11.10.6",
"@giphy/js-fetch-api": "4.9.3",
"@giphy/react-components": "6.9.4",
"@giphy/react-native-sdk": "4.1.0",
"@giphy/react-native-sdk": "3.3.1",
"@jitsi/excalidraw": "https://github.com/jitsi/excalidraw/releases/download/v0.0.19/jitsi-excalidraw-0.0.19.tgz",
"@jitsi/js-utils": "2.2.1",
"@jitsi/logger": "2.1.1",
"@jitsi/logger": "2.0.2",
"@jitsi/rnnoise-wasm": "0.2.1",
"@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",
@@ -57,10 +57,8 @@
"clipboard-copy": "4.0.1",
"clsx": "1.1.1",
"dayjs": "1.11.13",
"dompurify": "3.2.6",
"dropbox": "10.7.0",
"focus-visible": "5.1.0",
"glob": "11.0.3",
"grapheme-splitter": "1.0.4",
"i18n-iso-countries": "6.8.0",
"i18next": "17.0.6",
@@ -72,7 +70,7 @@
"js-md5": "0.6.1",
"js-sha512": "0.8.0",
"jwt-decode": "2.2.0",
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v2089.0.0+75c1c6ff/lib-jitsi-meet.tgz",
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v2030.0.0+b225c920/lib-jitsi-meet.tgz",
"lodash-es": "4.17.21",
"null-loader": "4.0.1",
"optional-require": "1.0.3",
@@ -89,16 +87,16 @@
"react-native-background-timer": "https://github.com/jitsi/react-native-background-timer.git#d180dfaa4486ae3ee17d01242db92cb3195f4718",
"react-native-calendar-events": "https://github.com/jitsi/react-native-calendar-events.git#47f068dedfed7c0f72042e093f688eb11624eb7b",
"react-native-default-preference": "https://github.com/jitsi/react-native-default-preference.git#c9bf63bdc058e3fa2aa0b87b1ee1af240f44ed02",
"react-native-device-info": "12.1.0",
"react-native-device-info": "10.9.0",
"react-native-dialog": "https://github.com/jitsi/react-native-dialog/releases/download/v9.2.2-jitsi.1/react-native-dialog-9.2.2.tgz",
"react-native-gesture-handler": "2.24.0",
"react-native-get-random-values": "1.11.0",
"react-native-immersive-mode": "https://github.com/jitsi/react-native-immersive-mode.git#38cc9001db24618bc0c61800f81e889bcfb6ff2c",
"react-native-orientation-locker": "https://github.com/jitsi/react-native-orientation-locker.git#fe095651d819cf134624f786b61fc8667862178a",
"react-native-pager-view": "6.8.1",
"react-native-orientation-locker": "1.6.0",
"react-native-pager-view": "6.4.1",
"react-native-paper": "5.10.3",
"react-native-performance": "5.1.2",
"react-native-safe-area-context": "5.5.2",
"react-native-safe-area-context": "5.4.0",
"react-native-screens": "4.11.1",
"react-native-sound": "https://github.com/jitsi/react-native-sound.git#ea13c97b5c2a4ff5e0d9bacbd9ff5e4457fe2c3c",
"react-native-splash-view": "0.0.18",
@@ -110,11 +108,10 @@
"react-native-watch-connectivity": "1.1.0",
"react-native-webrtc": "124.0.4",
"react-native-webview": "13.13.5",
"react-native-worklets-core": "https://github.com/jitsi/react-native-worklets-core.git#8c5dfab2a5907305da8971696a781b60f0f9cb18",
"react-native-youtube-iframe": "2.3.0",
"react-redux": "7.2.9",
"react-textarea-autosize": "8.3.0",
"react-virtualized-auto-sizer": "1.0.26",
"react-virtualized-auto-sizer": "^1.0.26",
"react-window": "1.8.6",
"react-youtube": "10.1.0",
"redux": "4.0.4",
@@ -132,8 +129,6 @@
},
"devDependencies": {
"@babel/core": "7.25.9",
"@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6",
"@babel/plugin-proposal-optional-chaining": "7.21.0",
"@babel/plugin-transform-private-methods": "7.25.9",
"@babel/preset-env": "7.25.9",
"@babel/preset-react": "7.25.9",

View File

@@ -0,0 +1,14 @@
diff --git a/node_modules/@giphy/js-analytics/dist/send-pingback.js b/node_modules/@giphy/js-analytics/dist/send-pingback.js
index 989f0ff..52471cb 100644
--- a/node_modules/@giphy/js-analytics/dist/send-pingback.js
+++ b/node_modules/@giphy/js-analytics/dist/send-pingback.js
@@ -10,6 +10,9 @@ var global_1 = __importDefault(require("./global"));
var environment = (global_1.default === null || global_1.default === void 0 ? void 0 : global_1.default.GIPHY_PINGBACK_URL) || 'https://pingback.giphy.com';
var pingBackUrl = "".concat(environment, "/v2/pingback?apikey=l0HlIwPWyBBUDAUgM");
var sendPingback = function (events) {
+ // Disabled.
+ return Promise.resolve();
+
var headers = (0, js_util_1.getGiphySDKRequestHeaders)();
/* istanbul ignore next */
headers === null || headers === void 0 ? void 0 : headers.set('Content-Type', 'application/json');

View File

@@ -70,7 +70,6 @@ cd ios && pod install && cd ..
## Android
- In your build.gradle have at least `minSdkVersion = 26`
- In your build.gradle have `gradlePluginVersion = "8.4.2"` or higher
- In `android/app/src/debug/AndroidManifest.xml` and `android/app/src/main/AndroidManifest.xml`, under the `</application>` tag, include
```xml
<uses-permission android:name="android.permission.RECORD_AUDIO" />

View File

@@ -7,6 +7,7 @@ buildscript {
dependencies {
classpath "com.android.tools.build:gradle:$rootProject.ext.gradlePluginVersion"
}
namespace 'org.jitsi.meet.reactnativesdk'
}
def isNewArchitectureEnabled() {
@@ -28,7 +29,6 @@ def getExtOrIntegerDefault(name) {
}
android {
namespace 'org.jitsi.meet.sdk'
compileSdkVersion getExtOrIntegerDefault('compileSdkVersion')
defaultConfig {
@@ -124,11 +124,12 @@ repositories {
dependencies {
// noinspection GradleDynamicVersion
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+"
implementation 'com.squareup.duktape:duktape-android:1.3.0'
implementation 'com.dropbox.core:dropbox-core-sdk:4.0.1'
implementation 'com.jakewharton.timber:timber:4.7.1'
// From node_modules
// From node_modules
}
if (isNewArchitectureEnabled()) {

View File

@@ -1,3 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.jitsi.meet.sdk">
</manifest>

View File

@@ -22,6 +22,7 @@ public class JitsiMeetReactNativePackage implements ReactPackage {
new AppInfoModule(reactContext),
new AudioModeModule(reactContext),
new JMOngoingConferenceModule(reactContext),
new JavaScriptSandboxModule(reactContext),
new LocaleDetector(reactContext),
new LogBridgeModule(reactContext),
new PictureInPictureModule(reactContext),

View File

@@ -85,12 +85,7 @@
"react-native-video": "0.0.0",
"react-native-watch-connectivity": "0.0.0",
"react-native-webrtc": "0.0.0",
"react-native-webview": "0.0.0",
"react-native-worklets-core": "0.0.0"
},
"devDependencies": {
"@babel/plugin-proposal-nullish-coalescing-operator": "0.0.0",
"@babel/plugin-proposal-optional-chaining": "0.0.0"
"react-native-webview": "0.0.0"
},
"scripts": {
"postinstall": "node sdk_instructions.js",

View File

@@ -100,6 +100,10 @@ fs.copyFileSync(
`${iosSrcPath}/InfoPlistUtil.h`,
`${iosDestPath}/InfoPlistUtil.h`
);
fs.copyFileSync(
`${iosSrcPath}/JavaScriptSandbox.m`,
`${iosDestPath}/JavaScriptSandbox.m`
);
fs.copyFileSync(
`${iosSrcPath}/JitsiAudioSession.m`,
`${iosDestPath}/JitsiAudioSession.m`
@@ -180,6 +184,10 @@ fs.copyFileSync(
`${androidSourcePath}/ConnectionService.java`,
`${androidTargetPath}/ConnectionService.java`
);
fs.copyFileSync(
`${androidSourcePath}/JavaScriptSandboxModule.java`,
`${androidTargetPath}/JavaScriptSandboxModule.java`
);
fs.copyFileSync(
`${androidSourcePath}/LocaleDetector.java`,
`${androidTargetPath}/LocaleDetector.java`

View File

@@ -60,12 +60,12 @@ This is now set on your end.`
);
}
}
packageJSON.devDependencies = packageJSON.devDependencies || {};
for (const key in RNSDKpackageJSON.devDependencies) {
if (!packageJSON.devDependencies.hasOwnProperty(key)) {
packageJSON.devDependencies[key] = RNSDKpackageJSON.devDependencies[key];
packageJSON.overrides = packageJSON.overrides || {};
for (const key in RNSDKpackageJSON.overrides) {
if (!packageJSON.overrides.hasOwnProperty(key)) {
packageJSON.overrides[key] = RNSDKpackageJSON.overrides[key];
updated = true;
}
}
@@ -91,14 +91,6 @@ This is now set on your end.`
return item;
}, {});
packageJSON.devDependencies = Object.keys(packageJSON.devDependencies)
.sort()
.reduce((item, itemKey) => {
item[itemKey] = packageJSON.devDependencies[itemKey];
return item;
}, {});
fs.writeFileSync(pathToPackageJSON, JSON.stringify(packageJSON, null, 2));

View File

@@ -26,13 +26,6 @@ function mergeDependencyVersions() {
SDKPackageJSON.peerDependencies[key] = packageJSON.dependencies[key];
}
}
// Updates SDK dev dependencies(used by react-native-worklets-core lib. babel plugin)
for (const key in packageJSON.devDependencies) {
if (SDKPackageJSON.devDependencies.hasOwnProperty(key)) {
SDKPackageJSON.devDependencies[key] = packageJSON.devDependencies[key];
}
}
// Set RN peer dependency.
const rnVersion = semver.parse(packageJSON.dependencies['react-native']);

View File

@@ -35,12 +35,3 @@ export function fixDeviceID(amplitude: Types.BrowserClient) {
}
}
}
/**
* Returns the amplitude shared deviceId.
*
* @returns {string} - The amplitude deviceId.
*/
export function getDeviceID() {
return jitsiLocalStorage.getItem(DEVICE_ID_KEY);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -2,7 +2,7 @@ import React, { useCallback } from 'react';
import { makeStyles } from 'tss-react/mui';
import Icon from '../../../icons/components/Icon';
import { pixelsToRem } from '../../../ui/functions.any';
import { withPixelLineHeight } from '../../../styles/functions.web';
import { isIcon } from '../../functions';
import { IAvatarProps } from '../../types';
import { PRESENCE_AVAILABLE_COLOR, PRESENCE_AWAY_COLOR, PRESENCE_BUSY_COLOR, PRESENCE_IDLE_COLOR } from '../styles';
@@ -50,8 +50,9 @@ const useStyles = makeStyles()(theme => {
avatar: {
backgroundColor: '#AAA',
borderRadius: '50%',
fontWeight: '600',
color: theme.palette?.text01 || '#fff',
...(theme.typography?.heading1 ?? {}),
...withPixelLineHeight(theme.typography?.heading1 ?? {}),
fontSize: 'inherit',
objectFit: 'cover',
textAlign: 'center',
@@ -136,7 +137,7 @@ const StatelessAvatar = ({
const _getAvatarStyle = (backgroundColor?: string) => {
return {
background: backgroundColor || undefined,
fontSize: size ? pixelsToRem(size * 0.4) : '180%',
fontSize: size ? size * 0.4 : '180%',
height: size || '100%',
width: size || '100%'
};

View File

@@ -4,12 +4,13 @@ import { makeStyles } from 'tss-react/mui';
import Icon from '../icons/components/Icon';
import { IconCheck, IconCopy } from '../icons/svg';
import { withPixelLineHeight } from '../styles/functions.web';
import { copyText } from '../util/copyText.web';
const useStyles = makeStyles()(theme => {
return {
copyButton: {
...theme.typography.bodyShortBold,
...withPixelLineHeight(theme.typography.bodyShortBold),
borderRadius: theme.shape.borderRadius,
display: 'flex',
justifyContent: 'flex-start',

View File

@@ -83,8 +83,7 @@ import {
getConferenceState,
getCurrentConference,
getVisitorOptions,
sendLocalParticipant,
updateTrackMuteState
sendLocalParticipant
} from './functions';
import logger from './logger';
import { IConferenceMetadata, IJitsiConference } from './reducer';
@@ -187,15 +186,6 @@ function _addConferenceListeners(conference: IJitsiConference, dispatch: IStore[
(disableVideoMuteChange: boolean) => {
dispatch(setVideoUnmutePermissions(disableVideoMuteChange));
});
conference.on(
JitsiConferenceEvents.START_MUTED_POLICY_CHANGED,
({ audio, video }: { audio: boolean; video: boolean; }) => {
dispatch(onStartMutedPolicyChanged(audio, video));
updateTrackMuteState(state, dispatch, true);
updateTrackMuteState(state, dispatch, false);
}
);
// Dispatches into features/base/tracks follow:
@@ -1023,8 +1013,6 @@ export function setStartMutedPolicy(
audio: startAudioMuted,
video: startVideoMuted
});
dispatch(onStartMutedPolicyChanged(startAudioMuted, startVideoMuted));
};
}

View File

@@ -40,8 +40,3 @@ export const CONFERENCE_LEAVE_REASONS = {
SWITCH_ROOM: 'switch_room',
UNRECOVERABLE_ERROR: 'unrecoverable_error'
};
/**
* The ID of the notification that is shown when the user is muted by focus.
*/
export const START_MUTED_NOTIFICATION_ID = 'start-muted';

View File

@@ -3,13 +3,9 @@ import { upperFirst, words } from 'lodash-es';
import { getName } from '../../app/functions';
import { IReduxState, IStore } from '../../app/types';
import { showNotification } from '../../notifications/actions';
import { NOTIFICATION_TIMEOUT_TYPE } from '../../notifications/constants';
import { determineTranscriptionLanguage } from '../../transcribing/functions';
import { IStateful } from '../app/types';
import { JitsiTrackErrors } from '../lib-jitsi-meet';
import { setAudioMuted, setVideoMuted } from '../media/actions';
import { VIDEO_MUTISM_AUTHORITY } from '../media/constants';
import {
participantJoined,
participantLeft
@@ -26,8 +22,7 @@ import { setObfuscatedRoom } from './actions';
import {
AVATAR_URL_COMMAND,
EMAIL_COMMAND,
JITSI_CONFERENCE_URL_KEY,
START_MUTED_NOTIFICATION_ID
JITSI_CONFERENCE_URL_KEY
} from './constants';
import logger from './logger';
import { IJitsiConference } from './reducer';
@@ -579,42 +574,3 @@ function safeStartCase(s = '') {
(result, word, index) => result + (index ? ' ' : '') + upperFirst(word)
, '');
}
/**
* Updates the mute state of the track based on the start muted policy.
*
* @param {Object|Function} stateful - Either the whole Redux state object or the Redux store's {@code getState} method.
* @param {Function} dispatch - Redux dispatch function.
* @param {boolean} isAudio - Whether the track is audio or video.
* @returns {void}
*/
export function updateTrackMuteState(stateful: IStateful, dispatch: IStore['dispatch'], isAudio: boolean) {
const state = toState(stateful);
const mutedPolicyKey = isAudio ? 'startAudioMutedPolicy' : 'startVideoMutedPolicy';
const mutedPolicyValue = state['features/base/conference'][mutedPolicyKey];
// Currently, the policy only supports force muting others, not unmuting them.
if (!mutedPolicyValue) {
return;
}
let muteStateUpdated = false;
const { muted } = isAudio ? state['features/base/media'].audio : state['features/base/media'].video;
if (isAudio && !Boolean(muted)) {
dispatch(setAudioMuted(mutedPolicyValue, true));
muteStateUpdated = true;
} else if (!isAudio && !Boolean(muted)) {
// TODO: Add a new authority for video mutism for the moderator case.
dispatch(setVideoMuted(mutedPolicyValue, VIDEO_MUTISM_AUTHORITY.USER, true));
muteStateUpdated = true;
}
if (muteStateUpdated) {
dispatch(showNotification({
titleKey: 'notify.mutedTitle',
descriptionKey: 'notify.muted',
uid: START_MUTED_NOTIFICATION_ID // use the same id, to make sure we show one notification
}, NOTIFICATION_TIMEOUT_TYPE.SHORT));
}
}

View File

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

View File

@@ -72,6 +72,7 @@ import {
} from './functions';
import logger from './logger';
import { IConferenceMetadata } from './reducer';
import './subscriber';
/**
* Handler for before unload event.

View File

@@ -0,0 +1,61 @@
import { IStore } from '../../app/types';
import { showNotification } from '../../notifications/actions';
import { NOTIFICATION_TIMEOUT_TYPE } from '../../notifications/constants';
import { setAudioMuted, setVideoMuted } from '../media/actions';
import { VIDEO_MUTISM_AUTHORITY } from '../media/constants';
import StateListenerRegistry from '../redux/StateListenerRegistry';
let hasShownNotification = false;
/**
* Handles changes in the start muted policy for audio and video tracks in the meta data set for the conference.
*/
StateListenerRegistry.register(
/* selector */ state => state['features/base/conference'].startAudioMutedPolicy,
/* listener */ (startAudioMutedPolicy, store) => {
_updateTrackMuteState(store, true);
});
StateListenerRegistry.register(
/* selector */ state => state['features/base/conference'].startVideoMutedPolicy,
/* listener */(startVideoMutedPolicy, store) => {
_updateTrackMuteState(store, false);
});
/**
* Updates the mute state of the track based on the start muted policy.
*
* @param {IStore} store - The redux store.
* @param {boolean} isAudio - Whether the track is audio or video.
* @returns {void}
*/
function _updateTrackMuteState(store: IStore, isAudio: boolean) {
const { dispatch, getState } = store;
const mutedPolicyKey = isAudio ? 'startAudioMutedPolicy' : 'startVideoMutedPolicy';
const mutedPolicyValue = getState()['features/base/conference'][mutedPolicyKey];
// Currently, the policy only supports force muting others, not unmuting them.
if (!mutedPolicyValue) {
return;
}
let muteStateUpdated = false;
const { muted } = isAudio ? getState()['features/base/media'].audio : getState()['features/base/media'].video;
if (isAudio && !Boolean(muted)) {
dispatch(setAudioMuted(mutedPolicyValue, true));
muteStateUpdated = true;
} else if (!isAudio && !Boolean(muted)) {
// TODO: Add a new authority for video mutism for the moderator case.
dispatch(setVideoMuted(mutedPolicyValue, VIDEO_MUTISM_AUTHORITY.USER, true));
muteStateUpdated = true;
}
if (!hasShownNotification && muteStateUpdated) {
hasShownNotification = true;
dispatch(showNotification({
titleKey: 'notify.mutedTitle',
descriptionKey: 'notify.muted'
}, NOTIFICATION_TIMEOUT_TYPE.SHORT));
}
}

View File

@@ -1,6 +1,5 @@
import { ToolbarButton } from '../../toolbox/types';
import { ILoggingConfig } from '../logging/types';
import { IAudioSettings } from '../settings/reducer';
import { DesktopSharingSourceType } from '../tracks/types';
type ButtonsWithNotifyClick = 'camera' |
@@ -192,7 +191,6 @@ export interface IConfig {
appId?: string;
audioLevelsInterval?: number;
audioQuality?: {
enableAdvancedAudioSettings?: boolean;
opusMaxAverageBitrate?: number | null;
stereo?: boolean;
};
@@ -239,7 +237,6 @@ export interface IConfig {
inactiveDisabled?: boolean;
};
constraints?: {
audio?: IAudioSettings;
video?: {
height?: {
ideal?: number;
@@ -524,6 +521,7 @@ export interface IConfig {
preCallTestEnabled?: boolean;
preCallTestICEUrl?: string;
};
prejoinPageEnabled?: boolean;
raisedHands?: {
disableLowerHandByModerator?: boolean;
disableLowerHandNotification?: boolean;
@@ -555,7 +553,7 @@ export interface IConfig {
disableDemote?: boolean;
disableGrantModerator?: boolean;
disableKick?: boolean;
disablePrivateChat?: 'all' | 'allow-moderator-chat' | 'disable-visitor-chat';
disablePrivateChat?: 'all' | 'allow-moderator-chat';
disabled?: boolean;
};
replaceParticipant?: string;

View File

@@ -202,6 +202,7 @@ export default [
'prejoinConfig.enabled',
'prejoinConfig.hideDisplayName',
'prejoinConfig.hideExtraJoinButtons',
'prejoinPageEnabled',
'raisedHands',
'recordingService',
'requireDisplayName',

View File

@@ -6,9 +6,7 @@ import { safeJsonParse } from '@jitsi/js-utils/json';
import { isEmpty, mergeWith, pick } from 'lodash-es';
import { IReduxState } from '../../app/types';
import { browser } from '../lib-jitsi-meet';
import { getLocalParticipant } from '../participants/functions';
import { isEmbedded } from '../util/embedUtils';
import { parseURLParams } from '../util/parseURLParams';
import { IConfig } from './configType';
@@ -257,17 +255,6 @@ export function isDisplayNameVisible(state: IReduxState): boolean {
return !state['features/base/config'].hideDisplayName;
}
/**
* Selector for determining if the advanced audio settings are enabled.
*
* @param {Object} state - The state of the app.
* @returns {boolean}
*/
export function isAdvancedAudioSettingsEnabled(state: IReduxState): boolean {
return !browser.isWebKitBased() && Boolean(state['features/base/config']?.audioQuality?.enableAdvancedAudioSettings);
}
/**
* Restores a Jitsi Meet config.js from {@code localStorage} if it was
* previously downloaded from a specific {@code baseURL} and stored with
@@ -348,7 +335,7 @@ export function setConfigFromURLParams(
overrideConfigJSON(config, interfaceConfig, json);
// Print warning about deprecated URL params
// Print warning about depricated URL params
if ('interfaceConfig.SUPPORT_URL' in params) {
logger.warn('Using SUPPORT_URL interfaceConfig URL overwrite is deprecated.'
+ ' Please use supportUrl from advanced branding!');
@@ -384,13 +371,6 @@ export function setConfigFromURLParams(
logger.warn('Using liveStreaming config URL overwrite and/or LIVE_STREAMING_HELP_LINK interfaceConfig URL'
+ ' overwrite is deprecated. Please use liveStreaming from advanced branding!');
}
// When not in an iframe, start without media if the pre-join page is not enabled.
if (!isEmbedded()
&& 'config.prejoinConfig.enabled' in params && config.prejoinConfig?.enabled === false) {
logger.warn('Using prejoinConfig.enabled config URL overwrite implies starting without media.');
config.disableInitialGUM = true;
}
}
/* eslint-enable max-params */

View File

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

View File

@@ -405,6 +405,13 @@ function _translateLegacyConfig(oldValue: IConfig) {
newValue.welcomePage.disabled = !oldValue.enableWelcomePage;
}
newValue.prejoinConfig = oldValue.prejoinConfig || {};
if (oldValue.hasOwnProperty('prejoinPageEnabled')
&& !newValue.prejoinConfig.hasOwnProperty('enabled')
) {
newValue.prejoinConfig.enabled = oldValue.prejoinPageEnabled;
}
newValue.disabledSounds = newValue.disabledSounds || [];
if (oldValue.disableJoinLeaveSounds) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -2,6 +2,7 @@ import React, { useCallback } from 'react';
import { makeStyles } from 'tss-react/mui';
import Icon from '../../../icons/components/Icon';
import { withPixelLineHeight } from '../../../styles/functions.web';
import { COLORS } from '../../constants';
interface IProps {
@@ -54,7 +55,7 @@ interface IProps {
const useStyles = makeStyles()(theme => {
return {
label: {
...theme.typography.labelRegular,
...withPixelLineHeight(theme.typography.labelRegular),
alignItems: 'center',
background: theme.palette.ui04,
borderRadius: '4px',

View File

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

View File

@@ -1,7 +1,6 @@
// @ts-ignore
import { safeJsonParse } from '@jitsi/js-utils/json';
// @ts-ignore
import { Worklets } from 'react-native-worklets-core';
import { NativeModules } from 'react-native';
import { loadScript } from '../util/loadScript.native';
@@ -9,12 +8,7 @@ import logger from './logger';
export * from './functions.any';
/**
* Worklet context usefull for running small tasks off the JS thread.
*/
export const workletContext = Worklets.createContext('ConfigParser');
const { JavaScriptSandbox } = NativeModules;
/**
* Loads config.js from a specific remote server.
@@ -24,46 +18,14 @@ export const workletContext = Worklets.createContext('ConfigParser');
*/
export async function loadConfig(url: string): Promise<Object> {
try {
const configTxt = await loadScript(url, 10 * 1000, true);
const configTxt = await loadScript(url, 10 * 1000 /* Timeout in ms */, true /* skipeval */);
const configJson = await JavaScriptSandbox.evaluate(`${configTxt}\nJSON.stringify(config);`);
const config = safeJsonParse(configJson);
const parseConfigAsync = workletContext.createRunAsync(function parseConfig(configText: string): string {
'worklet';
try {
// Used IIFE wrapper to capture config object from config.js
const configObj = eval(
'(function(){\n'
+ configText
+ '\n; return (typeof config !== "undefined" ? config : globalThis.config); })()'
);
if (configObj == void 0) {
return 'Worklet_Error: config is undefined after eval()';
}
if (typeof configObj !== 'object') {
return 'Worklet_Error: config is not an object';
}
return JSON.stringify(configObj);
} catch (err) {
return 'Worklet_Error:' + ((err as Error)?.message ?? String(err));
}
});
const workletConfig = await parseConfigAsync(configTxt);
if (typeof workletConfig !== 'string') {
throw new Error('Worklet error: workletConfig is not a string');
if (typeof config !== 'object') {
throw new Error('config is not an object');
}
if (workletConfig.startsWith('Worklet_Error:')) {
const msg = workletConfig.slice('Worklet_Error:'.length);
throw new Error(`Worklet error: ${msg}`);
}
const config = safeJsonParse(workletConfig);
logger.info(`Config loaded from ${url}`);
return config;

View File

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

View File

@@ -17,8 +17,8 @@ const DEFAULT_LOGGING_CONFIG: ILoggingConfig = {
loggers: {
// The following are too verbose in their logging with the
// {@link #defaultLogLevel}:
'rtc:TraceablePeerConnection': 'info',
'xmpp:strophe.util': 'log'
'modules/RTC/TraceablePeerConnection': 'info',
'modules/xmpp/strophe.util': 'log'
}
};
@@ -41,10 +41,10 @@ const DEFAULT_STATE = {
// Reduce default verbosity on mobile, it kills performance.
if (navigator.product === 'ReactNative') {
const RN_LOGGERS: { [key: string]: LogLevel; } = {
'sdp:SDPUtils': 'info',
'xmpp:ChatRoom': 'warn',
'xmpp:JingleSessionPC': 'info',
'xmpp:strophe.jingle': 'info'
'modules/sdp/SDPUtil': 'info',
'modules/xmpp/ChatRoom': 'warn',
'modules/xmpp/JingleSessionPC': 'info',
'modules/xmpp/strophe.jingle': 'info'
};
DEFAULT_STATE.config.loggers = {

View File

@@ -3,7 +3,7 @@
*
* @enum {string}
*/
export const CAMERA_FACING_MODE: Record<string, string> = {
export const CAMERA_FACING_MODE = {
ENVIRONMENT: 'environment',
USER: 'user'
};

View File

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

View File

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

View File

@@ -2,12 +2,10 @@
import { getGravatarURL } from '@jitsi/js-utils/avatar';
import { IReduxState, IStore } from '../../app/types';
import { isVisitorChatParticipant } from '../../chat/functions';
import { isStageFilmstripAvailable } from '../../filmstrip/functions';
import { isAddPeopleEnabled, isDialOutEnabled } from '../../invite/functions';
import { toggleShareDialog } from '../../share-room/actions';
import { iAmVisitor } from '../../visitors/functions';
import { IVisitorChatParticipant } from '../../visitors/types';
import { IStateful } from '../app/types';
import { GRAVATAR_BASE_URL } from '../avatar/constants';
import { isCORSAvatarURL } from '../avatar/functions';
@@ -829,28 +827,18 @@ export const setShareDialogVisiblity = (addPeopleFeatureEnabled: boolean, dispat
/**
* Checks if private chat is enabled for the given participant.
*
* @param {IParticipant|IVisitorChatParticipant|undefined} participant - The participant to check.
* @param {IParticipant|undefined} participant - The participant to check.
* @param {IReduxState} state - The Redux state.
* @returns {boolean} - True if private chat is enabled, false otherwise.
*/
export function isPrivateChatEnabled(participant: IParticipant | IVisitorChatParticipant | undefined, state: IReduxState) {
export function isPrivateChatEnabled(participant: IParticipant | undefined, state: IReduxState) {
const { remoteVideoMenu = {} } = state['features/base/config'];
const { disablePrivateChat } = remoteVideoMenu;
if ((!isVisitorChatParticipant(participant) && participant?.local) || disablePrivateChat === 'all') {
if (participant?.local || state['features/visitors'].iAmVisitor || disablePrivateChat === 'all') {
return false;
}
if (disablePrivateChat === 'disable-visitor-chat') {
// Block if the participant we're trying to message is a visitor
// OR if the local user is a visitor
if (isVisitorChatParticipant(participant) || iAmVisitor(state)) {
return false;
}
return true; // should allow private chat for other participants
}
if (disablePrivateChat === 'allow-moderator-chat') {
return isLocalParticipantModerator(state) || isParticipantModerator(participant);
}

View File

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

View File

@@ -24,14 +24,12 @@ import { hideNotification, showNotification } from '../../notifications/actions'
import {
LOCAL_RECORDING_NOTIFICATION_ID,
NOTIFICATION_TIMEOUT_TYPE,
RAISE_HAND_NOTIFICATION_ID,
VISITOR_ASKED_TO_JOIN_NOTIFICATION_ID
RAISE_HAND_NOTIFICATION_ID
} from '../../notifications/constants';
import { open as openParticipantsPane } from '../../participants-pane/actions';
import { CALLING, INVITED } from '../../presence-status/constants';
import { RAISE_HAND_SOUND_ID } from '../../reactions/constants';
import { RECORDING_OFF_SOUND_ID, RECORDING_ON_SOUND_ID } from '../../recording/constants';
import { iAmVisitor } from '../../visitors/functions';
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app/actionTypes';
import { CONFERENCE_JOINED, CONFERENCE_WILL_JOIN } from '../conference/actionTypes';
import { forEachConference, getCurrentConference } from '../conference/functions';
@@ -169,10 +167,7 @@ MiddlewareRegistry.register(store => next => action => {
case LOCAL_PARTICIPANT_RAISE_HAND: {
const { raisedHandTimestamp } = action;
const localParticipant = getLocalParticipant(store.getState());
const localId = localParticipant?.id;
const _iAmVisitor = iAmVisitor(store.getState());
const isHandRaised = hasRaisedHand(localParticipant);
const localId = getLocalParticipant(store.getState())?.id;
store.dispatch(participantUpdated({
// XXX Only the local participant is allowed to update without
@@ -191,18 +186,6 @@ MiddlewareRegistry.register(store => next => action => {
raisedHandTimestamp
}));
if (_iAmVisitor) {
const notifyAction = isHandRaised
? hideNotification(VISITOR_ASKED_TO_JOIN_NOTIFICATION_ID)
: showNotification({
titleKey: 'visitors.notification.requestToJoin',
descriptionKey: 'visitors.notification.requestToJoinDescription',
uid: VISITOR_ASKED_TO_JOIN_NOTIFICATION_ID
}, NOTIFICATION_TIMEOUT_TYPE.STICKY);
store.dispatch(notifyAction);
}
if (typeof APP !== 'undefined') {
APP.API.notifyRaiseHandUpdated(localId, raisedHandTimestamp);
}

View File

@@ -3,6 +3,7 @@ import { makeStyles } from 'tss-react/mui';
import Icon from '../../../icons/components/Icon';
import { IconArrowDown } from '../../../icons/svg';
import { withPixelLineHeight } from '../../../styles/functions.web';
interface IProps {
@@ -81,7 +82,7 @@ interface IProps {
const useStyles = makeStyles()(theme => {
return {
actionButton: {
...theme.typography.bodyLongBold,
...withPixelLineHeight(theme.typography.bodyLongBold),
borderRadius: theme.shape.borderRadius,
boxSizing: 'border-box',
color: theme.palette.text01,
@@ -114,7 +115,7 @@ const useStyles = makeStyles()(theme => {
'&.text': {
width: 'auto',
fontSize: '0.875rem',
fontSize: '13px',
margin: '0',
padding: '0'
},
@@ -134,7 +135,7 @@ const useStyles = makeStyles()(theme => {
[theme.breakpoints.down(400)]: {
fontSize: '1rem',
fontSize: 16,
marginBottom: 8,
padding: '11px 16px'
}

View File

@@ -5,6 +5,7 @@ import { makeStyles } from 'tss-react/mui';
import Icon from '../../../icons/components/Icon';
import { IconArrowDown, IconCloseCircle, IconWifi1Bar, IconWifi2Bars, IconWifi3Bars } from '../../../icons/svg';
import { withPixelLineHeight } from '../../../styles/functions.web';
import { PREJOIN_DEFAULT_CONTENT_WIDTH } from '../../../ui/components/variables';
import Spinner from '../../../ui/components/web/Spinner';
import { runPreCallTest } from '../../actions.web';
@@ -15,7 +16,7 @@ const useStyles = makeStyles()(theme => {
return {
connectionStatus: {
color: '#fff',
...theme.typography.bodyShortRegular,
...withPixelLineHeight(theme.typography.bodyShortRegular),
position: 'absolute',
width: '100%',

View File

@@ -10,6 +10,7 @@ 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 { withPixelLineHeight } from '../../../styles/functions.web';
import Tooltip from '../../../tooltip/components/Tooltip';
import { isPreCallTestEnabled } from '../../functions';
@@ -151,7 +152,7 @@ const useStyles = makeStyles()(theme => {
width: '100%'
},
title: {
...theme.typography.heading4,
...withPixelLineHeight(theme.typography.heading4),
color: `${theme.palette.text01}!important`,
marginBottom: theme.spacing(3),
textAlign: 'center',
@@ -167,7 +168,7 @@ const useStyles = makeStyles()(theme => {
},
roomName: {
...theme.typography.heading5,
...withPixelLineHeight(theme.typography.heading5),
color: theme.palette.text01,
display: 'inline-block',
overflow: 'hidden',

View File

@@ -2,6 +2,8 @@ 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: {
@@ -9,7 +11,7 @@ const useStyles = makeStyles()(theme => {
color: theme.palette.text03,
display: 'flex',
justifyContent: 'center',
...theme.typography.bodyShortRegular,
...withPixelLineHeight(theme.typography.bodyShortRegular),
marginBottom: theme.spacing(3),
marginTop: theme.spacing(2),
paddingLeft: theme.spacing(3),

View File

@@ -4,6 +4,7 @@ import { useDispatch, useSelector } from 'react-redux';
import { makeStyles } from 'tss-react/mui';
import { IReduxState } from '../../../../app/types';
import { withPixelLineHeight } from '../../../styles/functions.web';
import Checkbox from '../../../ui/components/web/Checkbox';
import getUnsafeRoomText from '../../../util/getUnsafeRoomText.web';
import { setUnsafeRoomConsent } from '../../actions.web';
@@ -13,7 +14,7 @@ const useStyles = makeStyles()(theme => {
warning: {
backgroundColor: theme.palette.warning01,
color: theme.palette.text04,
...theme.typography.bodyShortRegular,
...withPixelLineHeight(theme.typography.bodyShortRegular),
padding: theme.spacing(3),
borderRadius: theme.shape.borderRadius,
marginBottom: theme.spacing(3)

View File

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

View File

@@ -6,7 +6,6 @@ import { translate } from '../../../i18n/functions';
import Icon from '../../../icons/components/Icon';
import Tooltip from '../../../tooltip/components/Tooltip';
import { TOOLTIP_POSITION } from '../../../ui/constants.any';
import { pixelsToRem } from '../../../ui/functions.any';
/**
* The type of the React {@code Component} props of {@link BaseIndicator}.
@@ -41,7 +40,7 @@ interface IProps extends WithTranslation {
/**
* The font size for the icon.
*/
iconSize: number;
iconSize: string | number;
/**
* The ID attribute to set on the root element of the component.
@@ -89,10 +88,10 @@ const BaseIndicator = ({
tooltipPosition = 'top'
}: IProps) => {
const { classes: styles } = useStyles();
const style: { fontSize?: string; } = {};
const style: { fontSize?: string | number; } = {};
if (iconSize) {
style.fontSize = pixelsToRem(iconSize);
style.fontSize = iconSize;
}
return (

View File

@@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
import { makeStyles } from 'tss-react/mui';
import { withPixelLineHeight } from '../../../styles/functions.web';
import Button from '../../../ui/components/web/Button';
import { getSupportUrl } from '../../functions';
@@ -14,7 +15,7 @@ const useStyles = makeStyles()(theme => {
borderRadius: `${Number(theme.shape.borderRadius)}px`,
boxShadow: '0px 1px 2px rgba(41, 41, 41, 0.25)',
color: theme.palette.text01,
...theme.typography.bodyShortRegular,
...withPixelLineHeight(theme.typography.bodyShortRegular),
padding: `${theme.spacing(3)} 10`,
'& .retry-button': {
margin: '16px auto 0 auto'

View File

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

View File

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

View File

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

View File

@@ -51,15 +51,8 @@ const DEFAULT_STATE: ISettingsState = {
userSelectedMicDeviceLabel: undefined
};
export interface IAudioSettings {
autoGainControl?: boolean;
channelCount?: 1 | 2;
echoCancellation?: boolean;
noiseSuppression?: boolean;
}
export interface ISettingsState {
audioOutputDeviceId?: string;
audioSettings?: IAudioSettings;
audioSettingsVisible?: boolean;
avatarURL?: string;
cameraDeviceId?: string | boolean;
@@ -73,7 +66,6 @@ export interface ISettingsState {
localFlipX?: boolean;
maxStageParticipants?: number;
micDeviceId?: string | boolean;
previewAudioTrack?: any | null;
serverURL?: string;
showSubtitlesOnStage?: boolean;
soundsIncomingMessage?: boolean;

View File

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

View File

@@ -22,3 +22,17 @@ export function getFixedPlatformStyle(style?: StyleType | StyleType[]) {
return style;
}
/**
* Sets the line height of a CSS Object group in pixels.
* By default lineHeight is unitless in CSS, but not in RN.
*
* @param {Object} base - The base object containing the `lineHeight` property.
* @returns {Object}
*/
export function withPixelLineHeight(base: any) {
return {
...base,
lineHeight: `${base.lineHeight}px`
};
}

View File

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

View File

@@ -6,6 +6,7 @@ import { makeStyles } from 'tss-react/mui';
import { IReduxState } from '../../../app/types';
import { isMobileBrowser } from '../../environment/utils';
import Popover from '../../popover/components/Popover.web';
import { withPixelLineHeight } from '../../styles/functions.web';
import { TOOLTIP_POSITION } from '../../ui/constants.any';
import { hideTooltip, showTooltip } from '../actions';
@@ -25,7 +26,7 @@ const useStyles = makeStyles()(theme => {
backgroundColor: theme.palette.uiBackground,
borderRadius: '3px',
padding: theme.spacing(2),
...theme.typography.labelRegular,
...withPixelLineHeight(theme.typography.labelRegular),
color: theme.palette.text01,
position: 'relative',

View File

@@ -164,7 +164,6 @@ export function createLocalTracksA(options: ITrackOptions = {}) {
= createLocalTracksF(
{
cameraDeviceId: options.cameraDeviceId,
constraints: options?.constraints,
devices: [ device ],
facingMode:
options.facingMode || getCameraFacingMode(state),

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