Compare commits

...

67 Commits

Author SHA1 Message Date
Boris Grozev
b22f1965aa doc: Remove obsolete reference to browserify. 2017-01-25 15:48:32 -06:00
Samuel Liard
df6f920b44 Force jquery-ui version to fix pb with beta version we can get with npm
Use Maven in place of ant
Add --host parameter for jicofo
Add build for jitsi Meet

Revert "Force jquery-ui version to fix pb with beta version we can get with npm"

This reverts commit 35a8641e62.
2017-01-25 15:47:23 -06:00
Дамян Минков
f13b2462c8 Merge pull request #1257 from saghul/ds-options-cleanup
cleanup: Remove default Chrome extension ID
2017-01-23 17:04:59 -06:00
Paweł Domas
c0e80c14f8 Merge pull request #1192 from jitsi/remotecontrol
Implement remote control support
2017-01-23 17:00:11 -06:00
hristoterezov
2b1176df53 style(remotecontrol): getRequestedParticipant method comments 2017-01-23 16:06:51 -06:00
hristoterezov
05bfbf5620 fix(remotecontrol): Execute Reciever.enable only when the value is changed 2017-01-23 15:29:25 -06:00
hristoterezov
4af706bd83 style(keycode): Comment 2017-01-23 15:29:25 -06:00
hristoterezov
b62e4d5ee9 fix(remotecontrol): Log level 2017-01-23 15:29:25 -06:00
hristoterezov
bd98d661d3 ref(remotecontrol): Moves hangup logic to remote control module 2017-01-23 15:29:25 -06:00
hristoterezov
1f7c5529e9 fix(remotecontrol): Pin the controlled participant only on remote control permissions granted 2017-01-23 15:29:25 -06:00
hristoterezov
0453346cf4 ref(remotecontrol): Pass the largeVideoWrapper as parameter to remote control module 2017-01-23 15:29:25 -06:00
hristoterezov
15090243d0 fix(API): JS errors caused by remote control merge 2017-01-23 15:29:25 -06:00
hristoterezov
b22e3ee253 style(remotecontrol): Fix JSDoc for RemoteControlEvent 2017-01-23 15:29:25 -06:00
hristoterezov
e693554961 fix(remotecontrol): Logging 2017-01-23 15:29:25 -06:00
hristoterezov
0efca9a9a8 fix(remotecontrol): Fixing issues after peer review. 2017-01-23 15:29:25 -06:00
hristoterezov
5d22061c0a fix(remotecontrol): Handle on-stage participant changes 2017-01-23 15:29:25 -06:00
hristoterezov
84be7fd739 fix(remotecontrol): import of remote control 2017-01-23 15:29:25 -06:00
hristoterezov
5d269ad0aa fix(remotecontrol): Disable the keyboard shortcuts during remote control 2017-01-23 15:29:25 -06:00
hristoterezov
a4d5c41b3a feat(remotecontrol): UI for requesting permissions 2017-01-23 15:29:25 -06:00
hristoterezov
846fb9abb0 feat(remotecontrol): Implement requesting remote control permissions 2017-01-23 15:29:25 -06:00
hristoterezov
0f33e59e4d feat(remotecontrol): announce remotecontrol support 2017-01-23 15:29:25 -06:00
hristoterezov
896650d005 feat(remotecontrol): Implement basic remote control support 2017-01-23 15:29:25 -06:00
Saúl Ibarra Corretgé
6d6b5a7917 cleanup: Remove default Chrome extension ID
It makes for a bad first-time experience for users, since the desktop sharing
button will be visible, but it will never work.

Also get rid of the now deprecated `desktopSharingChromeMethod` option.
2017-01-23 15:21:28 -06:00
Любомир Маринов
db5010be9d Merge pull request #1261 from jitsi/clean-css-module-update
Stick to clean-css version 3.x.
2017-01-23 15:18:18 -06:00
damencho
be8860080c Fixes build.
Starting version 4.x clean-css is split into two packages and we should depend on clean-css-cli for versions 4 and above. Tested it and we have currently some problem with it like fonts and images got referenced under css folder. So sticking version to 3.x for now.
2017-01-23 14:35:26 -06:00
Lyubomir Marinov
42f124b0f6 Fix typo 2017-01-23 13:01:12 -06:00
Lyubomir Marinov
7249ababb7 Provide microphone and camera usage descriptions
iTunes Connect/TestFlight requires these now and is not satisfied with
empty values anymore.
2017-01-23 12:11:48 -06:00
Lyubomir Marinov
079be92468 Revert "[RN][iOS] Make universal builds"
This reverts commit b96ca538e4. While iPad
support is nice to have, we are not ready for a publish in App Store.
During the upload to iTunes Connect, a verification of the .ipa fails
because:

- app icons for iPad are missing:
  - 76x76 pixels in .png format for iOS versions >= 7.0,
  - 167x167 pixels in .png format for iOS versions supporting iPad Pro,
  - 152x152 pixels in .png format for iOS versions >= 7.0,
- orientations required for iPad Mutitasking are missing:
  - UIInterfaceOrientationPortraitUpsideDown.
2017-01-23 11:26:15 -06:00
Lyubomir Marinov
dda2a2feba Automatic Xcode project file fixes 2017-01-22 16:02:57 -06:00
Lyubomir Marinov
ae726cfdc0 react-native 0.40.0 2017-01-22 12:32:08 -06:00
Saúl Ibarra Corretgé
1a04e5a9af [RN] Use a translucent status bar on Android 2017-01-21 15:42:13 -06:00
Lyubomir Marinov
cac68dbaba [RN] Increment short app version from 1.1 to 1.2
Now that Apple have approved build 1.1.185 for release in the App Store,
the short app version needs to be incremented; otherwise, no new builds
can be uploaded to TestFlight and, respectively, for release in the App
Store.
2017-01-20 15:01:01 -06:00
Lyubomir Marinov
3c04634609 Simplify
Simplify the source code (with the idea that source code which does not
exist does not have to be maintained).

Additionally, apply modifications to have the source code comply with the coding
style.

Overall, prepare saghul:audio-mode for merge into jitsi:master.
2017-01-20 14:06:15 -06:00
Saúl Ibarra Corretgé
6c12681b9c [RN][iOS] Default to speaker for video conferences 2017-01-20 14:06:15 -06:00
Saúl Ibarra Corretgé
b1b5f3e6f0 Add CONFERENCE_WILL_JOIN action
It's fired before creating the conference with lib-jitsi-meet.
2017-01-20 14:06:15 -06:00
bbaldino
5baa167a08 Sdp overhaul (#1234)
* M1: device change now uses new flow.  fundamentally "works" but may be corner cases/side effects to other flows. haven't touched ffox yet

* M2: change toggle screenshare flows to use the new video replacement chain

* remove the old 'useVideoStream' and replace it with the new one

* use the new (and renamed back from the shim) 'dispose' method

* tweaks to work with the sdp overhaul changes in lib-jitsi-meet

* change the order in which we call dispose (to handle dispose being reverted back to how it is currently on master)

* move useAudioStream over to new flow

* restore useVideoStream doc

* handle rename JitsiConference::replaceStream -> JitsiConference::replaceTrack

* fix useAudioStream and useVideoStream to return a promise again
2017-01-19 12:46:10 -06:00
ibauersachs
343d17d19a Commit from translate.jitsi.org by user ibauersachs.: 99 of 298 strings translated (18 fuzzy). 2017-01-18 23:58:43 +00:00
ibauersachs
0370cc47fc Commit from translate.jitsi.org by user ibauersachs.: 140 of 298 strings translated (15 fuzzy). 2017-01-18 23:58:36 +00:00
ibauersachs
083fc955dc Commit from translate.jitsi.org by user ibauersachs.: 237 of 298 strings translated (17 fuzzy). 2017-01-18 23:58:30 +00:00
ibauersachs
a6e268f784 Commit from translate.jitsi.org by user ibauersachs.: 128 of 298 strings translated (14 fuzzy). 2017-01-18 23:58:23 +00:00
ibauersachs
7e0a9bc37c Commit from translate.jitsi.org by user ibauersachs.: 138 of 298 strings translated (14 fuzzy). 2017-01-18 23:58:16 +00:00
ibauersachs
f25bc818d7 Commit from translate.jitsi.org by user ibauersachs.: 298 of 298 strings translated (0 fuzzy). 2017-01-18 23:58:05 +00:00
ibauersachs
9beae22803 Commit from translate.jitsi.org by user ibauersachs.: 237 of 298 strings translated (17 fuzzy). 2017-01-18 23:57:58 +00:00
ibauersachs
920b0af269 Commit from translate.jitsi.org by user ibauersachs.: 298 of 298 strings translated (0 fuzzy). 2017-01-18 23:57:51 +00:00
ibauersachs
6c674bef2a Commit from translate.jitsi.org by user ibauersachs.: 129 of 298 strings translated (14 fuzzy). 2017-01-18 23:57:44 +00:00
ibauersachs
e74fbbb38b Commit from translate.jitsi.org by user ibauersachs.: 298 of 298 strings translated (0 fuzzy). 2017-01-18 23:57:29 +00:00
ibauersachs
fb3f916802 Commit from translate.jitsi.org by user ibauersachs.: 237 of 298 strings translated (17 fuzzy). 2017-01-18 23:57:21 +00:00
ibauersachs
c80d47d3dd Commit from translate.jitsi.org by user ibauersachs.: 192 of 298 strings translated (21 fuzzy). 2017-01-18 23:57:14 +00:00
ibauersachs
693ee1dcf8 Commit from translate.jitsi.org by user ibauersachs.: 237 of 298 strings translated (17 fuzzy). 2017-01-18 23:57:06 +00:00
Дамян Минков
640c0faff1 Merge pull request #1253 from jitsi/api_participant_count
Iframe API - participant count
2017-01-18 14:52:59 -06:00
hristoterezov
207ac47aa7 fix(iframe_api): s/getNumberOfParticipant/getNumberOfParticipants 2017-01-18 14:24:41 -06:00
hristoterezov
8844f83a59 feat(iframe_api): Add api.html to doc for example and testing purpose 2017-01-18 14:24:40 -06:00
hristoterezov
4a5a1cd5f4 fix(iframe_api): Remove enable/disable events 2017-01-18 14:24:21 -06:00
hristoterezov
09d63d38ab fix(iframe_api): prevents multiple execution of listeners per event 2017-01-18 13:24:30 -06:00
hristoterezov
6bf0f9b2ec feat(iframe_api): get number of participants 2017-01-18 13:20:32 -06:00
Lyubomir Marinov
f6fdd3ce70 Don't show watermarks in film strip-only mode even for guests 2017-01-17 21:54:17 -06:00
Lyubomir Marinov
d1f6679f2d [RN] Remove Crashlytics 2017-01-17 21:54:17 -06:00
Lyubomir Marinov
b8a6eb4768 Fix the checkbox to disable the Welcome page
Recently, we reimplemented the Welcome page in React. Unfortunately, we
broke the checkbox that enables/disables the Welcome page and it would
allow checking but wouldn't allow unchecking.
2017-01-17 16:20:43 -06:00
Lyubomir Marinov
6efad1348a Fix the display of watermarks in film strip-only mode
Recently, we reimplemented the watermarks in React. Unfortunately, we
didn't take into account film strip-only mode.

Additionally, we duplicated watermark-related source code on the Welcome
and Conference pages.
2017-01-17 16:20:13 -06:00
Lyubomir Marinov
eaed9db1e7 Name folders consistently 2017-01-17 08:53:23 -06:00
Lyubomir Marinov
4f8b7a934c Comply w/ coding style 2017-01-17 08:32:20 -06:00
Lyubomir Marinov
71c04936af Merge branch 'actions-rename' of https://github.com/saghul/jitsi-meet into saghul-actions-rename 2017-01-17 08:18:52 -06:00
Любомир Маринов
41da758946 Merge pull request #1242 from saghul/ipad
Enable universal builds
2017-01-16 19:56:29 -06:00
Saúl Ibarra Corretgé
acbfe5cb09 [RN] Keep device screen on while in a conference 2017-01-16 19:12:43 -06:00
Saúl Ibarra Corretgé
b96ca538e4 [RN][iOS] Make universal builds 2017-01-12 16:24:01 -06:00
Saúl Ibarra Corretgé
3266ace916 [RN][iOS] Set deployment target to 9.0
According to Apple iOS devices with versions < 9.0 are 6%.
https://developer.apple.com/support/app-store/
2017-01-12 16:20:03 -06:00
Saúl Ibarra Corretgé
e71e6c5b79 Name Redux actions consistently
Redux actions which represent "commands" should be imperative, and those
representing events should use the past tense.
2017-01-11 13:11:11 -06:00
110 changed files with 3257 additions and 1208 deletions

1
.gitattributes vendored
View File

@@ -1,2 +1,3 @@
*.bundle.js -text -diff
*.pbxproj -text
lib-jitsi-meet.js -text -diff

18
.gitignore vendored
View File

@@ -36,12 +36,13 @@ DerivedData
*.xcuserstate
project.xcworkspace
# Android/IJ
# Android/IntelliJ
#
*.iml
build/
.idea
.gradle
local.properties
*.iml
# node.js
#
@@ -53,4 +54,15 @@ npm-debug.log
buck-out/
\.buckd/
android/app/libs
android/keystores/debug.keystore
*.keystore
# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use
# fastlane to re-generate the screenshots whenever they are needed. For more
# information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
#
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots

4
ConferenceEvents.js Normal file
View File

@@ -0,0 +1,4 @@
/**
* Notifies interested parties that hangup procedure will start.
*/
export const BEFORE_HANGUP = "conference.before_hangup";

View File

@@ -1,15 +1,4 @@
buildscript {
repositories {
maven { url 'https://maven.fabric.io/public' }
}
dependencies {
classpath 'io.fabric.tools:gradle:1.+'
}
}
apply plugin: 'com.android.application'
apply plugin: 'io.fabric'
import com.android.build.OutputFile
@@ -102,7 +91,7 @@ android {
minSdkVersion 16
targetSdkVersion 22
versionCode Integer.parseInt("${version}")
versionName "1.1.${version}"
versionName "1.2.${version}"
ndk {
abiFilters 'armeabi-v7a', 'x86'
}
@@ -149,18 +138,13 @@ if (project.hasProperty('JITSI_SIGNING')
apply from: project.property('JITSI_SIGNING');
}
repositories {
maven { url 'https://maven.fabric.io/public' }
}
dependencies {
compile project(':react-native-keep-awake')
compile project(':react-native-vector-icons')
compile project(':react-native-webrtc')
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.facebook.react:react-native:+'
compile('com.crashlytics.sdk.android:crashlytics:2.6.5@aar') {
transitive = true
}
compile 'com.facebook.react:react-native:+' // From node_modules
}
apply from: '../../node_modules/react-native-vector-icons/fonts.gradle'
@@ -168,6 +152,6 @@ apply from: '../../node_modules/react-native-vector-icons/fonts.gradle'
// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
from configurations.compile
into 'libs'
from configurations.compile
into 'libs'
}

View File

@@ -43,8 +43,5 @@
</activity>
<activity
android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<meta-data
android:name="io.fabric.ApiKey"
android:value="a8ae24a58302ba79da1d312138e941f6b86e3242" />
</application>
</manifest>

View File

@@ -2,12 +2,10 @@ package org.jitsi.meet;
import android.app.Application;
import com.crashlytics.android.Crashlytics;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import io.fabric.sdk.android.Fabric;
import com.facebook.soloader.SoLoader;
import java.util.Arrays;
import java.util.List;
@@ -28,6 +26,7 @@ public class MainApplication extends Application implements ReactApplication {
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new com.corbt.keepawake.KCKeepAwakePackage(),
new com.facebook.react.shell.MainReactPackage(),
new com.oblador.vectoricons.VectorIconsPackage(),
new com.oney.WebRTCModule.WebRTCModulePackage()
@@ -50,11 +49,13 @@ public class MainApplication extends Application implements ReactApplication {
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
if (!getReactNativeHost()
.getReactInstanceManager()
.getDevSupportManager()
.getDevSupportEnabled()) {
Fabric.with(this, new Crashlytics());
// TODO Auto-generated method stub
}
}
}

View File

@@ -3,6 +3,7 @@
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="android:windowTranslucentStatus">true</item>
</style>
</resources>

View File

@@ -1,6 +1,8 @@
rootProject.name = 'jitsi-meet-react'
include ':app'
include ':react-native-keep-awake'
project(':react-native-keep-awake').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-keep-awake/android')
include ':react-native-vector-icons'
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')
include ':react-native-webrtc'

4
app.js
View File

@@ -22,6 +22,7 @@ import conference from './conference';
import API from './modules/API/API';
import translation from "./modules/translation/translation";
import remoteControl from "./modules/remotecontrol/RemoteControl";
const APP = {
// Used by do_external_connect.js if we receive the attach data after
@@ -59,7 +60,8 @@ const APP = {
*/
ConferenceUrl : null,
connection: null,
API
API,
remoteControl
};
// TODO The execution of the mobile app starts from react/index.native.js.

View File

@@ -14,9 +14,12 @@ import {reportError} from './modules/util/helpers';
import UIEvents from './service/UI/UIEvents';
import UIUtil from './modules/UI/util/UIUtil';
import * as JitsiMeetConferenceEvents from './ConferenceEvents';
import analytics from './modules/analytics/analytics';
import EventEmitter from "events";
const ConnectionEvents = JitsiMeetJS.events.connection;
const ConnectionErrors = JitsiMeetJS.errors.connection;
@@ -28,6 +31,8 @@ const TrackErrors = JitsiMeetJS.errors.track;
const ConnectionQualityEvents = JitsiMeetJS.events.connectionQuality;
const eventEmitter = new EventEmitter();
let room, connection, localAudio, localVideo;
/**
@@ -485,10 +490,11 @@ export default {
}).then(([tracks, con]) => {
logger.log('initialized with %s local tracks', tracks.length);
APP.connection = connection = con;
this._bindConnectionFailedHandler(con);
this._createRoom(tracks);
this.isDesktopSharingEnabled =
JitsiMeetJS.isDesktopSharingEnabled();
APP.remoteControl.init();
this._bindConnectionFailedHandler(con);
this._createRoom(tracks);
if (UIUtil.isButtonEnabled('contacts')
&& !interfaceConfig.filmStripOnly) {
@@ -901,43 +907,40 @@ export default {
return options;
},
/**
* Start using provided video stream.
* Stops previous video stream.
* @param {JitsiLocalTrack} [stream] new stream to use or null
* @returns {Promise}
*/
useVideoStream (stream) {
let promise = Promise.resolve();
if (localVideo) {
// this calls room.removeTrack internally
// so we don't need to remove it manually
promise = localVideo.dispose();
}
localVideo = stream;
return promise.then(function () {
if (stream) {
return room.addTrack(stream);
}
}).then(() => {
if (stream) {
this.videoMuted = stream.isMuted();
this.isSharingScreen = stream.videoType === 'desktop';
/**
* Start using provided video stream.
* Stops previous video stream.
* @param {JitsiLocalTrack} [stream] new stream to use or null
* @returns {Promise}
*/
useVideoStream (newStream) {
return room.replaceTrack(localVideo, newStream)
.then(() => {
// We call dispose after doing the replace because
// dispose will try and do a new o/a after the
// track removes itself. Doing it after means
// the JitsiLocalTrack::conference member is already
// cleared, so it won't try and do the o/a
if (localVideo) {
localVideo.dispose();
}
localVideo = newStream;
if (newStream) {
this.videoMuted = newStream.isMuted();
this.isSharingScreen = newStream.videoType === 'desktop';
APP.UI.addLocalStream(stream);
APP.UI.addLocalStream(newStream);
stream.videoType === 'camera'
&& APP.UI.setCameraButtonEnabled(true);
} else {
this.videoMuted = false;
this.isSharingScreen = false;
}
APP.UI.setVideoMuted(this.getMyUserId(), this.videoMuted);
APP.UI.updateDesktopSharingButtons();
});
newStream.videoType === 'camera'
&& APP.UI.setCameraButtonEnabled(true);
} else {
this.videoMuted = false;
this.isSharingScreen = false;
}
APP.UI.setVideoMuted(this.getMyUserId(), this.videoMuted);
APP.UI.updateDesktopSharingButtons();
});
},
/**
@@ -946,31 +949,27 @@ export default {
* @param {JitsiLocalTrack} [stream] new stream to use or null
* @returns {Promise}
*/
useAudioStream (stream) {
let promise = Promise.resolve();
if (localAudio) {
// this calls room.removeTrack internally
// so we don't need to remove it manually
promise = localAudio.dispose();
}
localAudio = stream;
return promise.then(function () {
if (stream) {
return room.addTrack(stream);
}
}).then(() => {
if (stream) {
this.audioMuted = stream.isMuted();
APP.UI.addLocalStream(stream);
} else {
this.audioMuted = false;
}
APP.UI.setMicrophoneButtonEnabled(true);
APP.UI.setAudioMuted(this.getMyUserId(), this.audioMuted);
});
useAudioStream (newStream) {
return room.replaceTrack(localAudio, newStream)
.then(() => {
// We call dispose after doing the replace because
// dispose will try and do a new o/a after the
// track removes itself. Doing it after means
// the JitsiLocalTrack::conference member is already
// cleared, so it won't try and do the o/a
if (localAudio) {
localAudio.dispose();
}
localAudio = newStream;
if (newStream) {
this.audioMuted = newStream.isMuted();
APP.UI.addLocalStream(newStream);
} else {
this.audioMuted = false;
}
APP.UI.setMicrophoneButtonEnabled(true);
APP.UI.setAudioMuted(this.getMyUserId(), this.audioMuted);
});
},
videoSwitchInProgress: false,
@@ -988,7 +987,7 @@ export default {
let externalInstallation = false;
if (shareScreen) {
createLocalTracks({
this.screenSharingPromise = createLocalTracks({
devices: ['desktop'],
desktopSharingExtensionExternalInstallation: {
interval: 500,
@@ -1077,7 +1076,10 @@ export default {
dialogTitleKey, dialogTxt, false);
});
} else {
createLocalTracks({ devices: ['video'] }).then(
APP.remoteControl.receiver.stop();
this.screenSharingPromise = createLocalTracks(
{ devices: ['video'] })
.then(
([stream]) => this.useVideoStream(stream)
).then(() => {
this.videoSwitchInProgress = false;
@@ -1109,6 +1111,8 @@ export default {
}
);
room.on(ConferenceEvents.PARTCIPANT_FEATURES_CHANGED,
user => APP.UI.onUserFeaturesChanged(user));
room.on(ConferenceEvents.USER_JOINED, (id, user) => {
if (user.isHidden())
return;
@@ -1344,11 +1348,13 @@ export default {
this.deviceChangeListener);
// stop local video
if (localVideo)
if (localVideo) {
localVideo.dispose();
}
// stop local audio
if (localAudio)
if (localAudio) {
localAudio.dispose();
}
// show overlay
APP.UI.showSuspendedOverlay();
@@ -1605,12 +1611,23 @@ export default {
},
/**
* Adds any room listener.
* @param eventName one of the ConferenceEvents
* @param callBack the function to be called when the event occurs
* @param {string} eventName one of the ConferenceEvents
* @param {Function} listener the function to be called when the event
* occurs
*/
addConferenceListener(eventName, callBack) {
room.on(eventName, callBack);
addConferenceListener(eventName, listener) {
room.on(eventName, listener);
},
/**
* Removes any room listener.
* @param {string} eventName one of the ConferenceEvents
* @param {Function} listener the listener to be removed.
*/
removeConferenceListener(eventName, listener) {
room.off(eventName, listener);
},
/**
* Inits list of current devices and event listener for device change.
* @private
@@ -1768,6 +1785,7 @@ export default {
* requested
*/
hangup (requestFeedback = false) {
eventEmitter.emit(JitsiMeetConferenceEvents.BEFORE_HANGUP);
APP.UI.hideRingOverLay();
let requestFeedbackPromise = requestFeedback
? APP.UI.requestFeedbackOnHangup()
@@ -1818,5 +1836,36 @@ export default {
APP.settings.setAvatarUrl(url);
APP.UI.setUserAvatarUrl(room.myUserId(), url);
sendData(commands.AVATAR_URL, url);
},
/**
* Sends a message via the data channel.
* @param {string} to the id of the endpoint that should receive the
* message. If "" - the message will be sent to all participants.
* @param {object} payload the payload of the message.
* @throws NetworkError or InvalidStateError or Error if the operation
* fails.
*/
sendEndpointMessage (to, payload) {
room.sendEndpointMessage(to, payload);
},
/**
* Adds new listener.
* @param {String} eventName the name of the event
* @param {Function} listener the listener.
*/
addListener (eventName, listener) {
eventEmitter.addListener(eventName, listener);
},
/**
* Removes listener.
* @param {String} eventName the name of the event that triggers the
* listener
* @param {Function} listener the listener.
*/
removeListener (eventName, listener) {
eventEmitter.removeListener(eventName, listener);
}
};

View File

@@ -20,10 +20,10 @@ var config = { // eslint-disable-line no-unused-vars
//focusUserJid: 'focus@auth.jitsi-meet.example.com', // The real JID of focus participant - can be overridden here
//defaultSipNumber: '', // Default SIP number
// Desktop sharing method. Can be set to 'ext', 'webrtc' or false to disable.
desktopSharingChromeMethod: 'ext',
// The ID of the jidesha extension for Chrome.
desktopSharingChromeExtId: 'diibjkoicjeejcmhdnailmkgecihlobk',
desktopSharingChromeExtId: null,
// Whether desktop sharing should be disabled on Chrome.
desktopSharingChromeDisabled: true,
// The media sources to use when using screen sharing with the Chrome
// extension.
desktopSharingChromeSources: ['screen', 'window', 'tab'],

View File

@@ -92,7 +92,7 @@
0 0 3px $videoThumbnailSelected !important;
}
.remotevideomenu {
.remotevideomenu > .icon-menu {
display: none;
}
@@ -105,7 +105,7 @@
box-shadow: inset 0 0 3px $videoThumbnailHovered,
0 0 3px $videoThumbnailHovered;
.remotevideomenu {
.remotevideomenu > .icon-menu {
display: inline-block;
}
}
@@ -121,4 +121,4 @@
}
}
}
}
}

View File

@@ -6,7 +6,6 @@
padding: 0;
margin: 2px 0;
bottom: 0;
width: 100px;
height: auto;
&:first-child {
@@ -66,4 +65,9 @@
span.remotevideomenu:hover ul.popupmenu, ul.popupmenu:hover {
display:block !important;
}
}
.remote-control-spinner {
top: 6px;
left: 2px;
}

22
doc/api/api.html Normal file
View File

@@ -0,0 +1,22 @@
<html itemscope itemtype="http://schema.org/Product" prefix="og: http://ogp.me/ns#" xmlns="http://www.w3.org/1999/html">
<head>
<meta charset="utf-8">
<meta http-equiv="content-type" content="text/html;charset=utf-8">
</head>
<body>
<script src="https://meet.jit.si/external_api.js"></script>
<script>
var domain = "meet.jit.si";
var room = "JitsiMeetAPIExample";
var width = 700;
var height = 180;
var htmlElement = undefined;
var configOverwrite = {};
var interfaceConfigOverwrite = {
filmStripOnly: true
};
var api = new JitsiMeetExternalAPI(domain, room, width, height,
htmlElement, configOverwrite, interfaceConfigOverwrite);
</script>
</body>
</html>

View File

@@ -202,6 +202,11 @@ If you want to remove more than one event you can use ```removeEventListeners```
api.removeEventListeners(["incomingMessage", "outgoingMessageListener"]);
```
You can get the number of participants in the conference with the following code:
```
var numberOfParticipants = api.getNumberOfParticipants();
```
You can remove the embedded Jitsi Meet Conference with the following code:
```
api.dispose()

View File

@@ -131,9 +131,9 @@ Or autostart it by adding the line in `/etc/rc.local`:
## Install Jitsi Conference Focus (jicofo)
Install JDK and Ant if missing:
Install JDK and Maven if missing:
```
apt-get install default-jdk ant
apt-get install default-jdk maven
```
_NOTE: When installing on older Debian releases keep in mind that you need JDK >= 1.7._
@@ -145,12 +145,14 @@ git clone https://github.com/jitsi/jicofo.git
Build distribution package. Replace {os-name} with one of: 'lin', 'lin64', 'macosx', 'win', 'win64'.
```sh
cd jicofo
ant dist.{os-name}
mvn package -DskipTests -Dassembly.skipAssembly=false
```
Run jicofo:
```sh
cd dist/{os-name}'
./jicofo.sh --host=127.0.0.1 --domain=jitsi.example.com --secret=YOURSECRET2 --user_domain=auth.jitsi.example.com --user_name=focus --user_password=YOURSECRET3
=======
unzip target/jicofo-{os-name}-1.0-SNAPSHOT.zip
cd jicofo-{os-name}-1.0-SNAPSHOT'
./jicofo.sh --host=localhost --domain=jitsi.example.com --secret=YOURSECRET2 --user_domain=auth.jitsi.example.com --user_name=focus --user_password=YOURSECRET3
```
## Deploy Jitsi Meet
@@ -159,6 +161,8 @@ Checkout and configure Jitsi Meet:
cd /srv
git clone https://github.com/jitsi/jitsi-meet.git
mv jitsi-meet/ jitsi.example.com
npm install
make
```
Edit host names in `/srv/jitsi.example.com/config.js` (see also the example config file):
@@ -167,11 +171,11 @@ var config = {
hosts: {
domain: 'jitsi.example.com',
muc: 'conference.jitsi.example.com',
bridge: 'jitsi-videobridge.jitsi.example.com'
bridge: 'jitsi-videobridge.jitsi.example.com',
focus: 'focus.jitsi.example.com'
},
useNicks: false,
bosh: '//jitsi.example.com/http-bind', // FIXME: use xep-0156 for that
desktopSharing: 'false' // Desktop sharing method. Can be set to 'ext', 'webrtc' or false to disable.
//chromeExtensionId: 'diibjkoicjeejcmhdnailmkgecihlobk', // Id of desktop streamer Chrome extension
//minChromeExtVersion: '0.1' // Required version of Chrome extension
};

View File

@@ -1,12 +0,0 @@
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'jitsi-meet-react' do
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
# use_frameworks!
# Pods for jitsi-meet-react
pod 'Crashlytics'
pod 'Fabric'
end

View File

@@ -1,16 +0,0 @@
PODS:
- Crashlytics (3.8.3):
- Fabric (~> 1.6.3)
- Fabric (1.6.11)
DEPENDENCIES:
- Crashlytics
- Fabric
SPEC CHECKSUMS:
Crashlytics: 2b6dbe138a42395577cfa73dfa1aa7248cadf39e
Fabric: 5911403591946b8228ab1c51d98f1d7137e863c6
PODFILE CHECKSUM: 672d557f679f28c07b3364884b4580e605000f01
COCOAPODS: 1.1.1

View File

@@ -8,8 +8,6 @@
*/
#import "AppDelegate.h"
#import <Crashlytics/Crashlytics.h>
#import <Fabric/Fabric.h>
#import "RCTAssert.h"
#import "RCTBundleURLProvider.h"
#import "RCTLinkingManager.h"
@@ -55,8 +53,6 @@ continueUserActivity:(NSUserActivity *)userActivity
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#if !DEBUG
[Fabric with:@[[Crashlytics class]]];
// In the Release configuration, React Native will (intentionally) raise an
// unhandled NSException for an unhandled JavaScript error. This will
// effectively kill the application. In accord with the Web, do not kill the

134
ios/app/AudioMode.m Normal file
View File

@@ -0,0 +1,134 @@
#import "RCTBridgeModule.h"
#import "RCTLog.h"
#import <AVFoundation/AVFoundation.h>
@interface AudioMode : NSObject<RCTBridgeModule>
@end
@implementation AudioMode {
NSString *_category;
NSString *_mode;
}
RCT_EXPORT_MODULE();
typedef enum {
kAudioModeDefault,
kAudioModeAudioCall,
kAudioModeVideoCall
} JitsiMeetAudioMode;
- (NSDictionary *)constantsToExport {
return @{
@"AUDIO_CALL" : [NSNumber numberWithInt: kAudioModeAudioCall],
@"DEFAULT" : [NSNumber numberWithInt: kAudioModeDefault],
@"VIDEO_CALL" : [NSNumber numberWithInt: kAudioModeVideoCall]
};
};
- (instancetype)init {
self = [super init];
if (self) {
_category = nil;
_mode = nil;
}
return self;
}
- (dispatch_queue_t)methodQueue {
// Make sure all our methods run in the main thread. The route change
// notification runs there so this will make sure it will only be fired
// after our changes have been applied (when we cause them, that is).
return dispatch_get_main_queue();
}
- (void)routeChanged:(NSNotification*)notification {
NSInteger reason
= [[notification.userInfo
valueForKey:AVAudioSessionRouteChangeReasonKey]
integerValue];
switch (reason) {
case AVAudioSessionRouteChangeReasonCategoryChange:
// The category has changed. Check if it's the one we want and adjust as
// needed.
[self setCategory:_category mode:_mode error:nil];
break;
default:
// Do nothing.
break;
}
}
- (BOOL)setCategory:(NSString *)category
mode:(NSString *)mode
error:(NSError * _Nullable *)outError {
AVAudioSession *session = [AVAudioSession sharedInstance];
if (session.category != category
&& ![session setCategory:category error:outError]) {
RCTLogError(@"Failed to (re)apply specified AVAudioSession category!");
return NO;
}
if (session.mode != mode && ![session setMode:mode error:outError]) {
RCTLogError(@"Failed to (re)apply specified AVAudioSession mode!");
return NO;
}
return YES;
}
RCT_EXPORT_METHOD(setMode:(int)mode
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {
NSString *avCategory;
NSString *avMode;
NSError *error;
switch (mode) {
case kAudioModeAudioCall:
avCategory = AVAudioSessionCategoryPlayAndRecord;
avMode = AVAudioSessionModeVoiceChat;
break;
case kAudioModeDefault:
avCategory = AVAudioSessionCategorySoloAmbient;
avMode = AVAudioSessionModeDefault;
break;
case kAudioModeVideoCall:
avCategory = AVAudioSessionCategoryPlayAndRecord;
avMode = AVAudioSessionModeVideoChat;
break;
default:
reject(@"setMode", @"Invalid mode", nil);
return;
}
if (![self setCategory:avCategory mode:avMode error:&error] || error) {
reject(@"setMode", error.localizedDescription, error);
return;
}
// Even though the specified category and mode were successfully set, the
// AVAudioSession is a singleton and other parts of the application such as
// WebRTC may undo the settings. Make sure that the settings are reapplied
// upon undoes.
if (!_category || !_mode) {
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(routeChanged:)
name:AVAudioSessionRouteChangeNotification
object:nil];
}
// Save the desired/specified category and mode so that they may be
// reapplied (upon undoes as described above).
_category = avCategory;
_mode = avMode;
resolve(nil);
}
@end

View File

@@ -17,25 +17,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.1</string>
<string>1.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>Fabric</key>
<dict>
<key>APIKey</key>
<string>a8ae24a58302ba79da1d312138e941f6b86e3242</string>
<key>Kits</key>
<array>
<dict>
<key>KitInfo</key>
<dict/>
<key>KitName</key>
<string>Crashlytics</string>
</dict>
</array>
</dict>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>
@@ -57,11 +43,11 @@
</dict>
</dict>
<key>NSCameraUsageDescription</key>
<string></string>
<string>Participate in conferences with video.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>NSMicrophoneUsageDescription</key>
<string></string>
<string>Participate in conferences with audio.</string>
<key>UIAppFonts</key>
<array>
<string>jitsi.ttf</string>

View File

@@ -1,4 +0,0 @@
#import "RCTBridgeModule.h"
@interface POSIX : NSObject<RCTBridgeModule>
@end

View File

@@ -1,10 +1,13 @@
#import "POSIX.h"
#import "RCTBridgeModule.h"
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
@interface POSIX : NSObject<RCTBridgeModule>
@end
@implementation POSIX
RCT_EXPORT_MODULE();

View File

@@ -13,6 +13,7 @@
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; };
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
0B42DFAE1E2FD90700111B12 /* AudioMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B42DFAD1E2FD90700111B12 /* AudioMode.m */; };
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; };
@@ -23,7 +24,9 @@
146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
2602576C1D0A7703001E3363 /* jitsi.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2602576B1D0A7703001E3363 /* jitsi.ttf */; };
3847F11906B4479A9162628F /* libRNVectorIcons.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 821D8ABD506944B4BDBB069B /* libRNVectorIcons.a */; };
5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; };
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
901FE90FA5744B5B94DCDC41 /* libKCKeepAwake.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0EA8C046B2BF46279796F07D /* libKCKeepAwake.a */; };
B30EF2311DC0ED7C00690F45 /* WebRTC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B30EF2301DC0ED7C00690F45 /* WebRTC.framework */; };
B30EF2331DC0EEA500690F45 /* WebRTC.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B30EF2301DC0ED7C00690F45 /* WebRTC.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B3A9D0251E0481E10009343D /* POSIX.m in Sources */ = {isa = PBXBuildFile; fileRef = B3A9D0241E0481E10009343D /* POSIX.m */; };
@@ -76,6 +79,13 @@
remoteGlobalIDString = 832C81801AAF6DEF007FA2F7;
remoteInfo = RCTVibration;
};
0B8752851E26E54A004C5CAB /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5B09C20C78C74A548AAAC1FA /* KCKeepAwake.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = KCKeepAwake;
};
139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
@@ -104,6 +114,62 @@
remoteGlobalIDString = 5DBEB1501B18CEA900B34395;
remoteInfo = RNVectorIcons;
};
3DAD3EA41DF850E9000B6D8A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3D3C059A1DE3340900C268FA;
remoteInfo = yoga;
};
3DAD3EA61DF850E9000B6D8A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3D3C06751DE3340C00C268FA;
remoteInfo = "yoga-tvOS";
};
3DAD3EA81DF850E9000B6D8A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3D3CD9251DE5FBEC00167DC4;
remoteInfo = cxxreact;
};
3DAD3EAA1DF850E9000B6D8A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3D3CD9321DE5FBEE00167DC4;
remoteInfo = "cxxreact-tvOS";
};
3DAD3EAC1DF850E9000B6D8A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3D3CD90B1DE5FBD600167DC4;
remoteInfo = jschelpers;
};
3DAD3EAE1DF850E9000B6D8A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3D3CD9181DE5FBD800167DC4;
remoteInfo = "jschelpers-tvOS";
};
5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RCTAnimation;
};
5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 2D2A28201D9B03D100D4039D;
remoteInfo = "RCTAnimation-tvOS";
};
78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
@@ -197,6 +263,8 @@
00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = "<group>"; };
00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = "<group>"; };
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = "<group>"; };
0B42DFAD1E2FD90700111B12 /* AudioMode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AudioMode.m; path = app/AudioMode.m; sourceTree = "<group>"; };
0EA8C046B2BF46279796F07D /* libKCKeepAwake.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libKCKeepAwake.a; sourceTree = "<group>"; };
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = "<group>"; };
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = "<group>"; };
13B07F961A680F5B00A75B9A /* jitsi-meet-react.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "jitsi-meet-react.app"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -209,11 +277,12 @@
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = "<group>"; };
22418656B14845609F953A42 /* RNVectorIcons.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNVectorIcons.xcodeproj; path = "../node_modules/react-native-vector-icons/RNVectorIcons.xcodeproj"; sourceTree = "<group>"; };
2602576B1D0A7703001E3363 /* jitsi.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = jitsi.ttf; path = ../android/app/src/main/assets/fonts/jitsi.ttf; sourceTree = "<group>"; };
5B09C20C78C74A548AAAC1FA /* KCKeepAwake.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = KCKeepAwake.xcodeproj; path = "../node_modules/react-native-keep-awake/ios/KCKeepAwake.xcodeproj"; sourceTree = "<group>"; };
5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = "<group>"; };
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; };
821D8ABD506944B4BDBB069B /* libRNVectorIcons.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNVectorIcons.a; sourceTree = "<group>"; };
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; };
B30EF2301DC0ED7C00690F45 /* WebRTC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebRTC.framework; path = "../node_modules/react-native-webrtc/ios/WebRTC.framework"; sourceTree = "<group>"; };
B3A9D0231E0481E10009343D /* POSIX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = POSIX.h; path = app/POSIX.h; sourceTree = "<group>"; };
B3A9D0241E0481E10009343D /* POSIX.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = POSIX.m; path = app/POSIX.m; sourceTree = "<group>"; };
B3B083EB1D4955FF0069CEE7 /* jitsi-meet-react.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "jitsi-meet-react.entitlements"; sourceTree = "<group>"; };
B96AF9B6FBC0453798399985 /* FontAwesome.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf"; sourceTree = "<group>"; };
@@ -248,6 +317,7 @@
BF96438E1C34FBE100B0BBDF /* VideoToolbox.framework in Frameworks */,
146834051AC3E58100842450 /* libReact.a in Frameworks */,
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,
5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */,
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */,
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */,
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */,
@@ -258,6 +328,7 @@
BFC745141CB829B300673F38 /* libRCTWebRTC.a in Frameworks */,
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,
3847F11906B4479A9162628F /* libRNVectorIcons.a in Frameworks */,
901FE90FA5744B5B94DCDC41 /* libKCKeepAwake.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -306,6 +377,14 @@
name = Products;
sourceTree = "<group>";
};
0B8752821E26E54A004C5CAB /* Products */ = {
isa = PBXGroup;
children = (
0B8752861E26E54A004C5CAB /* libKCKeepAwake.a */,
);
name = Products;
sourceTree = "<group>";
};
139105B71AF99BAD00B5F7CC /* Products */ = {
isa = PBXGroup;
children = (
@@ -329,12 +408,12 @@
children = (
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
13B07FB01A68108700A75B9A /* AppDelegate.m */,
0B42DFAD1E2FD90700111B12 /* AudioMode.m */,
13B07FB51A68108700A75B9A /* Images.xcassets */,
13B07FB61A68108700A75B9A /* Info.plist */,
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
008F07F21AC5B25A0029DE68 /* main.jsbundle */,
13B07FB71A68108700A75B9A /* main.m */,
B3A9D0231E0481E10009343D /* POSIX.h */,
B3A9D0241E0481E10009343D /* POSIX.m */,
);
name = app;
@@ -344,7 +423,13 @@
isa = PBXGroup;
children = (
146834041AC3E56700842450 /* libReact.a */,
B3BA19EF1DC6B37B00BCD481 /* libReact-tvOS.a */,
B3BA19EF1DC6B37B00BCD481 /* libReact.a */,
3DAD3EA51DF850E9000B6D8A /* libyoga.a */,
3DAD3EA71DF850E9000B6D8A /* libyoga.a */,
3DAD3EA91DF850E9000B6D8A /* libcxxreact.a */,
3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */,
3DAD3EAD1DF850E9000B6D8A /* libjschelpers.a */,
3DAD3EAF1DF850E9000B6D8A /* libjschelpers.a */,
);
name = Products;
sourceTree = "<group>";
@@ -357,6 +442,15 @@
name = Products;
sourceTree = "<group>";
};
5E91572E1DD0AC6500FF2AA8 /* Products */ = {
isa = PBXGroup;
children = (
5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */,
5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */,
);
name = Products;
sourceTree = "<group>";
};
6956B374CC3C453DB7B8E82D /* Resources */ = {
isa = PBXGroup;
children = (
@@ -378,10 +472,12 @@
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
isa = PBXGroup;
children = (
5B09C20C78C74A548AAAC1FA /* KCKeepAwake.xcodeproj */,
BF96438F1C34FBEB00B0BBDF /* libc.tbd */,
BF9643911C34FBF100B0BBDF /* libsqlite3.tbd */,
BF9643931C34FBF900B0BBDF /* libstdc++.tbd */,
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,
5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */,
00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */,
00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */,
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */,
@@ -463,7 +559,6 @@
13B07F8E1A680F5B00A75B9A /* Resources */,
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
B30EF2341DC0EEA500690F45 /* Embed Frameworks */,
B3DBBAC41DC6A3BE001DA4DD /* ShellScript */,
B35383AD1DDA0083008F406A /* ShellScript */,
);
buildRules = (
@@ -481,7 +576,7 @@
83CBB9F71A601CBA00E9B192 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0800;
LastUpgradeCheck = 0820;
ORGANIZATIONNAME = Facebook;
TargetAttributes = {
13B07F861A680F5B00A75B9A = {
@@ -506,10 +601,18 @@
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = 0B8752821E26E54A004C5CAB /* Products */;
ProjectRef = 5B09C20C78C74A548AAAC1FA /* KCKeepAwake.xcodeproj */;
},
{
ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */;
ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
},
{
ProductGroup = 5E91572E1DD0AC6500FF2AA8 /* Products */;
ProjectRef = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */;
},
{
ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */;
ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;
@@ -598,6 +701,13 @@
remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B8752861E26E54A004C5CAB /* libKCKeepAwake.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libKCKeepAwake.a;
remoteRef = 0B8752851E26E54A004C5CAB /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@@ -626,6 +736,62 @@
remoteRef = 26D58A061D0B42EE00FC396B /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
3DAD3EA51DF850E9000B6D8A /* libyoga.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libyoga.a;
remoteRef = 3DAD3EA41DF850E9000B6D8A /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
3DAD3EA71DF850E9000B6D8A /* libyoga.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libyoga.a;
remoteRef = 3DAD3EA61DF850E9000B6D8A /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
3DAD3EA91DF850E9000B6D8A /* libcxxreact.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libcxxreact.a;
remoteRef = 3DAD3EA81DF850E9000B6D8A /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libcxxreact.a;
remoteRef = 3DAD3EAA1DF850E9000B6D8A /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
3DAD3EAD1DF850E9000B6D8A /* libjschelpers.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libjschelpers.a;
remoteRef = 3DAD3EAC1DF850E9000B6D8A /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
3DAD3EAF1DF850E9000B6D8A /* libjschelpers.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libjschelpers.a;
remoteRef = 3DAD3EAE1DF850E9000B6D8A /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTAnimation.a;
remoteRef = 5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libRCTAnimation-tvOS.a";
remoteRef = 5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@@ -682,10 +848,10 @@
remoteRef = B3BA19EA1DC6B37B00BCD481 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
B3BA19EF1DC6B37B00BCD481 /* libReact-tvOS.a */ = {
B3BA19EF1DC6B37B00BCD481 /* libReact.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libReact-tvOS.a";
path = libReact.a;
remoteRef = B3BA19EE1DC6B37B00BCD481 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
@@ -740,19 +906,6 @@
shellPath = /bin/sh;
shellScript = "APP_PATH=\"${TARGET_BUILD_DIR}/${WRAPPER_NAME}\"\n\n# This script loops through the frameworks embedded in the application and\n# removes unused architectures.\nfind \"$APP_PATH\" -name '*.framework' -type d | while read -r FRAMEWORK\ndo\nFRAMEWORK_EXECUTABLE_NAME=$(defaults read \"$FRAMEWORK/Info.plist\" CFBundleExecutable)\nFRAMEWORK_EXECUTABLE_PATH=\"$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME\"\necho \"Executable is $FRAMEWORK_EXECUTABLE_PATH\"\n\nEXTRACTED_ARCHS=()\n\nfor ARCH in $ARCHS\ndo\necho \"Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME\"\nlipo -extract \"$ARCH\" \"$FRAMEWORK_EXECUTABLE_PATH\" -o \"$FRAMEWORK_EXECUTABLE_PATH-$ARCH\"\nEXTRACTED_ARCHS+=(\"$FRAMEWORK_EXECUTABLE_PATH-$ARCH\")\ndone\n\necho \"Merging extracted architectures: ${ARCHS}\"\nlipo -o \"$FRAMEWORK_EXECUTABLE_PATH-merged\" -create \"${EXTRACTED_ARCHS[@]}\"\nrm \"${EXTRACTED_ARCHS[@]}\"\n\necho \"Replacing original executable with thinned version\"\nrm \"$FRAMEWORK_EXECUTABLE_PATH\"\nmv \"$FRAMEWORK_EXECUTABLE_PATH-merged\" \"$FRAMEWORK_EXECUTABLE_PATH\"\n\ndone";
};
B3DBBAC41DC6A3BE001DA4DD /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Fabric/run\" a8ae24a58302ba79da1d312138e941f6b86e3242 256ed316263eb534e26a1ad5dcc42ca9c179af5937dd864c3e44cfefa2e8b54c";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -761,6 +914,7 @@
buildActionMask = 2147483647;
files = (
B3A9D0251E0481E10009343D /* POSIX.m in Sources */,
0B42DFAE1E2FD90700111B12 /* AudioMode.m in Sources */,
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
);
@@ -798,10 +952,11 @@
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../node_modules/react-native/React/**",
"$(SRCROOT)/../node_modules/react-native/Libraries/LinkingIOS/**",
"$(SRCROOT)/../node_modules/react-native-keep-awake/ios",
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
);
INFOPLIST_FILE = app/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
@@ -833,10 +988,11 @@
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../node_modules/react-native/React/**",
"$(SRCROOT)/../node_modules/react-native/Libraries/LinkingIOS/**",
"$(SRCROOT)/../node_modules/react-native-keep-awake/ios",
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
);
INFOPLIST_FILE = app/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
@@ -865,15 +1021,19 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
@@ -890,6 +1050,7 @@
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../node_modules/react-native/React/**",
"$(SRCROOT)/../node_modules/react-native-keep-awake/ios",
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
);
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
@@ -912,8 +1073,10 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@@ -921,6 +1084,7 @@
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
@@ -931,6 +1095,7 @@
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../node_modules/react-native/React/**",
"$(SRCROOT)/../node_modules/react-native-keep-awake/ios",
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
);
IPHONEOS_DEPLOYMENT_TARGET = 8.0;

View File

@@ -1,11 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0820"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
parallelizeBuildables = "NO"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "83CBBA2D1A601D0E00E9B192"
BuildableName = "libReact.a"
BlueprintName = "React"
ReferencedContainer = "container:../node_modules/react-native/React/React.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"

View File

@@ -4,7 +4,4 @@
<FileRef
location = "group:jitsi-meet-react.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -2,12 +2,14 @@
"en": "Английски",
"bg": "Български",
"de": "Немски",
"es": "",
"es": "Испански",
"fr": "Френски",
"hy": "",
"hy": "Арменски",
"it": "Италиански",
"oc": "",
"pl": "",
"ptBR": "",
"ru": "",
"sk": "Словашки",
"sl": "Словенски",
"sv": "Шведски",

View File

@@ -2,12 +2,14 @@
"en": "Inglés",
"bg": "Búlgaro",
"de": "Alemán",
"es": "",
"es": "Español",
"fr": "Francés",
"hy": "",
"hy": "Armenio",
"it": "Italiano",
"oc": "",
"ptBR": "",
"oc": "Occitano",
"pl": "Polaco",
"ptBR": "Portugués (Brasil)",
"ru": "Ruso",
"sk": "Eslovaco",
"sl": "Esloveno",
"sv": "Sueco",

View File

@@ -7,7 +7,9 @@
"hy": "Arménien",
"it": "Italien",
"oc": "Occitan",
"pl": "Polonais",
"ptBR": "Portugais (Brésil)",
"ru": "Russe",
"sk": "Slovaque",
"sl": "Slovène",
"sv": "Suédois",

View File

@@ -7,7 +7,9 @@
"hy": "",
"it": "Italiano",
"oc": "",
"pl": "",
"ptBR": "",
"ru": "",
"sk": "Slovacco",
"sl": "Sloveno",
"sv": "",

View File

@@ -7,7 +7,9 @@
"hy": "Ormiański",
"it": "Włoski",
"oc": "Prowansalski",
"pl": "Polski",
"ptBR": "portugalski (brazylijski)",
"ru": "Rosyjski",
"sk": "Słowacki",
"sl": "Słoweński",
"sv": "Szwedzki",

View File

@@ -7,7 +7,9 @@
"hy": "",
"it": "Taliančina",
"oc": "",
"pl": "",
"ptBR": "",
"ru": "",
"sk": "Slovenčina",
"sl": "Slovinčina",
"sv": "",

View File

@@ -7,7 +7,9 @@
"hy": "",
"it": "Italjanščina",
"oc": "",
"pl": "",
"ptBR": "",
"ru": "",
"sk": "",
"sl": "Slovenščina",
"sv": "",

View File

@@ -7,7 +7,9 @@
"hy": "",
"it": "Italienska",
"oc": "",
"pl": "",
"ptBR": "",
"ru": "",
"sk": "Slovakiska",
"sl": "Slovenska",
"sv": "",

View File

@@ -7,7 +7,9 @@
"hy": "",
"it": "",
"oc": "",
"pl": "",
"ptBR": "",
"ru": "",
"sk": "",
"sl": "",
"sv": "",

View File

@@ -1,17 +1,19 @@
{
"contactlist": "СПИСЪК С КОНТАКТИ",
"contactlist": "",
"addParticipants": "",
"roomLocked": "",
"roomUnlocked": "",
"passwordSetRemotely": "",
"connectionsettings": "Настройки на връзката",
"poweredby": "powered by",
"downloadlogs": "Изтегли логовете",
"feedback": "Кажете ни как върви",
"roomUrlDefaultMsg": "Конференцията се създава...",
"participant": "Участник",
"inviteUrlDefaultMsg": "Конференцията се създава...",
"me": "аз",
"speaker": "Говорител",
"raisedHand": "",
"defaultNickname": "Яна Розова",
"defaultLink": "например __url__",
"calling": "Обаждане към __name__ ...",
"callingName": "",
"userMedia": {
"react-nativeGrantPermissions": "",
"chromeGrantPermissions": "",
@@ -23,17 +25,18 @@
"nwjsGrantPermissions": ""
},
"keyboardShortcuts": {
"keyboardShortcuts": "Клавишни комбинации:",
"raiseHand": "Вдигни ръка.",
"pushToTalk": "Push to talk.",
"toggleScreensharing": "Смяна между камера и споделен екран.",
"toggleFilmstrip": "Показване/скриване на лентата с видеата.",
"toggleShortcuts": "Показване/скриване на това меню.",
"focusLocal": "Фокусиране върху нашето видео.",
"focusRemote": "Фокусиране върху видео на участник.",
"toggleChat": "Отваряне/скриване на чат панела.",
"mute": "Спиране/пускане на микрофона.",
"videoMute": "Спиране/пускане на нашето видео."
"keyboardShortcuts": "",
"raiseHand": "",
"pushToTalk": "",
"toggleScreensharing": "",
"toggleFilmstrip": "",
"toggleShortcuts": "",
"focusLocal": "",
"focusRemote": "",
"toggleChat": "",
"mute": "",
"fullScreen": "",
"videoMute": ""
},
"welcomepage": {
"go": "Влез",
@@ -72,33 +75,45 @@
"content": "Научете повече за своите потребители като интегрирате лесно Piwik, Google Analytics и други статистики за изполването."
}
},
"startupoverlay": {
"policyText": "",
"title": ""
},
"suspendedoverlay": {
"title": "",
"rejoinKeyTitle": ""
},
"toolbar": {
"mute": "Включи / Изключи микрофона",
"videomute": "Включи / Изключи камерата",
"videomute": "",
"authenticate": "Идентификация",
"lock": "Заключи / отключи стаята",
"invite": "Покани други",
"chat": "Отвори / затвори чат",
"etherpad": "Покажи споделения документ",
"lock": "",
"invite": "",
"chat": "",
"etherpad": "",
"sharedvideo": "Сподели YouTube видео",
"sharescreen": "Сподели екрана",
"fullscreen": "Влез / Излез от Пълен екран",
"sharescreen": "",
"fullscreen": "",
"sip": "Обади се на SIP номер",
"Settings": "Настройки",
"hangup": "Затвори",
"hangup": "",
"login": "Влез",
"logout": "Изход",
"dialpad": "Цифров панел",
"dialpad": "",
"sharedVideoMutedPopup": "Споделеното видео е заглуено,<br/>, за да можете да говорите.",
"micMutedPopup": "Микрофонът е заглушен, за да<br/>не пречи на YouTube видеото.",
"talkWhileMutedPopup": "",
"unableToUnmutePopup": "Не се говори по време на филм!",
"cameraDisabled": "Не е налична камера",
"micDisabled": "Не е наличен микрофон"
"micDisabled": "Не е наличен микрофон",
"filmstrip": "",
"profile": "",
"raiseHand": ""
},
"bottomtoolbar": {
"chat": "Отвори / затвори чат",
"filmstrip": "Покажи / скрий лентата с видеа",
"contactlist": "Отвори / затвори контакт листа"
"filmstrip": "",
"contactlist": ""
},
"chat": {
"nickname": {
@@ -108,23 +123,33 @@
"messagebox": "Въведете текст..."
},
"settings": {
"title": "НАСТРОЙКИ",
"title": "Настройки",
"update": "Актуализиране",
"name": "Име",
"startAudioMuted": "Започни без аудио",
"startVideoMuted": "Започни без видео",
"selectCamera": "Избери камера",
"selectMic": "Избери микрофон",
"selectAudioOutput": "Избери аудио изход",
"followMe": "Включи \"следвай ме\"",
"startAudioMuted": "",
"startVideoMuted": "",
"selectCamera": "",
"selectMic": "",
"selectAudioOutput": "",
"followMe": "",
"noDevice": "Няма",
"noPermission": "Не е разрешен достъп до устройството",
"avatarUrl": "Адрес на аватар"
"cameraAndMic": "",
"moderator": "",
"password": "",
"audioVideo": "",
"setPasswordLabel": ""
},
"profile": {
"title": "",
"setDisplayNameLabel": "",
"setEmailLabel": "",
"setEmailInput": ""
},
"videothumbnail": {
"editnickname": "Натиснете за да<br/>промените името",
"moderator": "Създателя на<br/>конференцията",
"videomute": "Учасника е спрял<br/>камерата си.",
"videomute": "",
"mute": "Учасника е с изключен микрофон",
"kick": "Изгони",
"muted": "Изключен микрофон",
@@ -132,6 +157,7 @@
"flip": "Огледално"
},
"connectionindicator": {
"header": "",
"bitrate": "Дебит:",
"packetloss": "Загуба на пакети:",
"resolution": "Резолюция:",
@@ -165,34 +191,49 @@
"raisedHand": ""
},
"dialog": {
"add": "",
"kickMessage": "Бяхте изгонен от срещата!",
"popupError": "Навигаторът ви блокира попъите. Молим ви да премахнете забраната и да опитате отново.",
"passwordErrorTitle": "",
"passwordError": "Стаята е защитена с парола. Само собственикът може да я променя или премахва.",
"passwordError2": "Стаята ви не е защитена с парола. Собственикът би могъл да добави парола.",
"connectError": "Опа! Нещо се обърка и не успяхме да се свържем с конференцията.",
"connectErrorWithMsg": "Опа! Нещо се обърка и не успяхме да се свържем с конференцията: __msg__",
"incorrectPassword": "",
"connecting": "Свързване",
"copy": "",
"error": "Грешка",
"roomLocked": "",
"addPassword": "",
"createPassword": "",
"detectext": "Възникна грешка при опит да бъде намерено разширението за споделяне на екран.",
"failtoinstall": "Неуспешна инсталация на разширението за споделяне на екрана.",
"failedpermissions": "Неуспешен опит за получаване на права за използване на микрофон и/или камера.",
"bridgeUnavailable": "Jitsi Videobridge не е наличен. Моля опитайте пак!",
"jicofoUnavailable": "Jitsi Videobridge не е наличен. Моля опитайте пак!",
"conferenceReloadTitle": "",
"conferenceReloadMsg": "",
"conferenceDisconnectTitle": "",
"conferenceDisconnectMsg": "",
"reconnectNow": "",
"conferenceReloadTimeLeft": "",
"maxUsersLimitReached": "Конференцията е пълна. Моля, опитайте по-късно!",
"lockTitle": "Неуспешно заключване",
"lockMessage": "Неуспешно заключване на конференцията.",
"warning": "Внимание",
"passwordNotSupported": "В момента не поддържаме стаи с пароли.",
"sorry": "Съжаляваме",
"internalError": "Вътрешна грешка [setRemoteDescription]",
"internalErrorTitle": "",
"internalError": "",
"unableToSwitch": "Неуспешен опит за смяна на видеото.",
"SLDFailure": "Опа! Нещо се обърка и не успяхме да спрем микрофона! (SLD Failure)",
"SRDFailure": "Опа! Нещо се обърка и не успяхме да спрем камерата! (SRD Failure)",
"oops": "Опа!",
"currentPassword": "",
"passwordLabel": "",
"defaultError": "Възникна грешка",
"passwordRequired": "Изисква се парола",
"Ok": "ОК",
"done": "",
"Remove": "DELETE DELETE DELETE DELETE DELETE DELETE DELETE DELETE DELETE DELETE ",
"removePassword": "",
"shareVideoTitle": "Сподели видео",
"shareVideoLinkError": "Моля въведете правилен Prezi линк.",
"removeSharedVideoTitle": "Край на споделянето на видео",
@@ -202,6 +243,7 @@
"WaitForHostMsg": "<b>__room__ </b> още не е започнал. Ако вие сте домакина моля идентифицирайте се. В противен случай ще изчакаме домакина.",
"IamHost": "Аз съм домакина",
"Cancel": "Отказ",
"Submit": "",
"retry": "Повторен опит",
"logoutTitle": "Изход",
"logoutQuestion": "Сигурни ли сте, че искате да излезете и да прекъснете конференцията?",
@@ -216,26 +258,29 @@
"sipMsg": "Въведете SIP номер",
"passwordCheck": "Сигурни ли сте, че искате да махнете паролата?",
"passwordMsg": "Въведете парола, за да заключите стаята",
"Invite": "Покани",
"shareLink": "Сподели този линк с всеки, който искаш да поканиш",
"shareLink": "",
"settings1": "Конфигурирай конференцията",
"settings2": "Участниците се присъединиха с изключен микрофон.",
"settings3": "Изисквай имена<br/><br/>Въведете парола за да заключите стаята:",
"yourPassword": "вашата парола",
"yourPassword": "",
"Back": "Назад",
"serviceUnavailable": "Услугата не е налична",
"gracefulShutdown": "Услугата временно не е достъпна поради профилактика. Моля опитайте по-късно.",
"Yes": "Да",
"reservationError": "Грешка в системата за резервации",
"reservationErrorMsg": "Грешка номер: __code__, съобщение: __msg__",
"password": "парола",
"password": "",
"userPassword": "потребителска парола",
"token": "код за достъп",
"tokenAuthFailed": "Неуспешна XMPP автентикация: невалиден тоукън",
"displayNameRequired": "Въведете името си:",
"tokenAuthFailedTitle": "",
"tokenAuthFailed": "",
"displayNameRequired": "",
"enterDisplayName": "Въведете името си:",
"extensionRequired": "Изисква се разширение: ",
"firefoxExtensionPrompt": "За да споделите екрана си, трябва да инсталирате Firefox разширение. <a href='__url__'>свалете го тук</a> и пробвайте пак!",
"feedbackQuestion": "Как мина разговора?",
"rateExperience": "",
"feedbackHelp": "",
"feedbackQuestion": "",
"thankYou": "Благодарим, че използвахте __appName__!",
"sorryFeedback": "Много съжаляваме! Бихте ли ни казали повече?",
"liveStreaming": "Пряко предаване",
@@ -246,6 +291,7 @@
"stopLiveStreaming": "Край на прякото предаване",
"stopRecording": "Край на записа",
"doNotShowWarningAgain": "Занапред не ме предупреждавай пак",
"doNotShowMessageAgain": "",
"permissionDenied": "Достъпът е отказан",
"screenSharingPermissionDeniedError": "Не сте дали права за споделяне на екран",
"micErrorPresent": "Грешка при достъп до микрофона",
@@ -253,12 +299,20 @@
"cameraUnsupportedResolutionError": "Камерата ви не поддържа тази резолюция",
"cameraUnknownError": "Невъзможен достъп до камерата по неясна причина.",
"cameraPermissionDeniedError": "",
"cameraNotFoundError": "Указаната камера не е намерена.",
"cameraNotFoundError": "",
"cameraConstraintFailedError": "Камерата ви не задоволява зададените условия.",
"micUnknownError": "Не възможен достъп до микрофона по неясна причина.",
"micPermissionDeniedError": "",
"micNotFoundError": "Микрофонът не задоволява зададените условия.",
"micConstraintFailedError": "Микрофонът не задоволява зададените условия."
"micNotFoundError": "",
"micConstraintFailedError": "Микрофонът не задоволява зададените условия.",
"micNotSendingData": "",
"cameraNotSendingData": "",
"goToStore": "",
"externalInstallationTitle": "",
"externalInstallationMsg": "",
"muteParticipantTitle": "",
"muteParticipantBody": "",
"muteParticipantButton": "Изключи микрофона"
},
"email": {
"sharedKey": [
@@ -302,7 +356,7 @@
"on": "Запис",
"off": "Записът спрян",
"failedToStart": "Неуспешен опит за записване",
"buttonTooltip": "Пускане / спиране на запис",
"buttonTooltip": "",
"error": "Грешка при опит за запис. Моля опитайте отново.",
"unavailable": "Записите са временно невъзможни. Моля опитайте по-късно."
},
@@ -312,7 +366,7 @@
"off": "Край на прякото предаване",
"unavailable": "Услугата за пряко предаване е временно недостъпна. Опитайте по-късно.",
"failedToStart": "Неуспешен опит за пряко предаване",
"buttonTooltip": "Начало / край на пряко предаване",
"buttonTooltip": "",
"streamIdRequired": "Моля попълнете името на потока, за да можем да започнем прякото предаване.",
"error": "Неуспешно пряко предаване. Опитайте пак.",
"busy": "Всички записвачки са временно заети. Опитайте отново по-късно."

View File

@@ -1,6 +1,6 @@
{
"contactlist": "Teilnehmer (__pcount__)",
"addParticipants": "",
"addParticipants": "Link teilen",
"roomLocked": "Teilnehmer müssen ein Passwort eingeben",
"roomUnlocked": "Jeder mit Zugriff auf den Link kann beitreten",
"passwordSetRemotely": "von einem anderen Teilnehmer gesetzt",

View File

@@ -1,59 +1,62 @@
{
"contactlist": "LISTA DE CONTACTOS",
"contactlist": "",
"addParticipants": "",
"roomLocked": "",
"roomUnlocked": "",
"passwordSetRemotely": "",
"connectionsettings": "Ajustes de la conexión",
"poweredby": "impulsado por",
"downloadlogs": "Descargar logs",
"poweredby": "potenciado por",
"feedback": "Danos tu opinión",
"roomUrlDefaultMsg": "Tu conferencia está siendo creada...",
"participant": "Participante",
"inviteUrlDefaultMsg": "Tu conferencia está siendo creada...",
"me": "yo",
"speaker": "Orador",
"raisedHand": "",
"raisedHand": "Desea hablar",
"defaultNickname": "ej. Juana Rosas",
"defaultLink": "ej. __url__",
"calling": "Llamando __nombre__ ...",
"callingName": "__name__",
"userMedia": {
"react-nativeGrantPermissions": "",
"chromeGrantPermissions": "",
"androidGrantPermissions": "",
"firefoxGrantPermissions": "",
"operaGrantPermissions": "",
"iexplorerGrantPermissions": "",
"safariGrantPermissions": "",
"nwjsGrantPermissions": ""
"react-nativeGrantPermissions": "Por favor, conceda permisos para utilizar su cámara y micrófono presionando el botón <b><i> Permitir </i></b>",
"chromeGrantPermissions": "Por favor, conceda permisos para utilizar su cámara y micrófono presionando el botón <b><i> Permitir </i></b>",
"androidGrantPermissions": "Por favor, conceda permisos para utilizar su cámara y micrófono presionando el botón <b><i> Permitir </i></b>",
"firefoxGrantPermissions": "Por favor, conceda permisos para utilizar su cámara y micrófono presionando el botón <b><i>Compartir Dispositivo seleccionado</i></b>",
"operaGrantPermissions": "Por favor, conceda permisos para utilizar su cámara y micrófono presionando el botón <b><i> Permitir </i></b>",
"iexplorerGrantPermissions": "Por favor, conceda permisos para utilizar su cámara y micrófono presionando el botón <b><i>OK</i></b>",
"safariGrantPermissions": "Por favor, conceda permisos para utilizar su cámara y micrófono presionando el botón <b><i>OK</i></b>",
"nwjsGrantPermissions": "Por favor, conceda permisos para utilizar su cámara y micrófono"
},
"keyboardShortcuts": {
"keyboardShortcuts": "Atajos de teclado:",
"raiseHand": "Levantar la mano.",
"pushToTalk": "Presione para hablar.",
"toggleScreensharing": "Cambiar entre cámara y compartir pantalla.",
"toggleFilmstrip": "Mostrar u ocultar película.",
"toggleShortcuts": "Muestra u oculta este menú de ayuda.",
"focusLocal": "Enfocar el video local.",
"focusRemote": "Enfocarse en uno de los videos remotos.",
"toggleChat": "Abrir o cerrar panel de charlas.",
"mute": "Activar o desactivar micrófono.",
"videoMute": "Detener o iniciar el video local."
"keyboardShortcuts": "",
"raiseHand": "",
"pushToTalk": "",
"toggleScreensharing": "",
"toggleFilmstrip": "",
"toggleShortcuts": "",
"focusLocal": "",
"focusRemote": "",
"toggleChat": "",
"mute": "",
"fullScreen": "",
"videoMute": ""
},
"welcomepage": {
"go": "IR",
"roomname": "Introduzca un nombre de sala:",
"roomname": "Introduzca un nombre de sala",
"disable": "No mostrar esta página otra vez",
"feature1": {
"title": "Sencillo de usar",
"content": "No se requiere descargar nada. __app__ funciona directamente con tu navegador. Solo comparte el URL de tu conferencia con otros para comenzar."
"content": "No se requiere descargar nada. __app__ funciona directamente con su navegador. Solo comparta el URL de su conferencia con otros para comenzar."
},
"feature2": {
"title": "Bajo Ancho de Banda",
"content": "Las Videoconferencias con múltiples participantes funcionan con tan solo 128 Kbps. Conferencias para compartir pantalla y audio son posibles con mucho menos."
"title": "Bajo consumo de Ancho de Banda",
"content": "Las Videoconferencias con múltiples participantes funcionan con tan solo 128 Kbps. Conferencias para compartir pantalla y solo audio son posibles con mucho menos."
},
"feature3": {
"title": "Código abierto",
"content": "__app__ está licenciado bajo la licencia Apache. Eres libre de descargar, usar, modificar, y compartirlo conforme a esta licencia libre."
"content": "__app__ está licenciado bajo la Licencia Apache. Eres libre de descargar, usar, modificar, y compartirlo de acuerdo a esta licencia."
},
"feature4": {
"title": "Usuarios ilimitados",
"content": "No hay restricciones artificiales en el número de usuarios o participantes de la conferencia. La capacidad del servidor y ancho de banda son los únicos factores limitantes."
"content": "No hay restricciones artificiales en el número de usuarios o participantes de la conferencia. La capacidad del servidor y del ancho de banda son los únicos factores limitantes."
},
"feature5": {
"title": "Compartir pantalla",
@@ -72,59 +75,81 @@
"content": "Aprenda de sus usuarios a través de una fácil integración con Piwik, Google Analytics, y otros sistemas de seguimiento y análisis de uso."
}
},
"startupoverlay": {
"policyText": "",
"title": ""
},
"suspendedoverlay": {
"title": "",
"rejoinKeyTitle": ""
},
"toolbar": {
"mute": "Activar / Desactivar Silencio",
"videomute": "Iniciar / detener cámara",
"videomute": "",
"authenticate": "Autenticar",
"lock": "Bloquear / desbloquear sala",
"invite": "Invitar a otros",
"chat": "Abrir / cerrar chat",
"etherpad": "Compartir documento",
"lock": "",
"invite": "",
"chat": "",
"etherpad": "",
"sharedvideo": "Compartir un vídeo de YouTube",
"sharescreen": "Compartir pantalla",
"fullscreen": "Entrar / Salir de Pantalla completa",
"sharescreen": "",
"fullscreen": "",
"sip": "Llamar a un número SIP",
"Settings": "Ajustes",
"hangup": "Colgar",
"hangup": "",
"login": "Inicio de sesión",
"logout": "Cerrar sesión",
"dialpad": "Mostrar teclado de llamada",
"dialpad": "",
"sharedVideoMutedPopup": "Su vídeo compartido ha sido silenciado<br/>para que pueda hablar con otros participantes.",
"micMutedPopup": "Su micrófono ha sido silenciado para que<br/>pueda disfrutar completamente de compartir su vídeo.",
"micMutedPopup": "Su micrófono ha sido silenciado para que<br/>pueda disfrutar completamente de su vídeo compartido.",
"talkWhileMutedPopup": "",
"unableToUnmutePopup": "No puede silenciar su micrófono mientras el vídeo compartido está activo.",
"cameraDisabled": "Cámara no disponible",
"micDisabled": "Micrófono no disponible"
"micDisabled": "Micrófono no disponible",
"filmstrip": "",
"profile": "",
"raiseHand": ""
},
"bottomtoolbar": {
"chat": "Abrir / cerrar chat",
"filmstrip": "Mostrar / ocultar film",
"contactlist": "Abrir / cerrar lista de contactos"
"chat": "Abrir / cerrar sala de charlas",
"filmstrip": "Mostrar / ocultar videos",
"contactlist": ""
},
"chat": {
"nickname": {
"title": "Indique un nombre en la caja inferior",
"popover": "Seleccione un nombre"
"title": "Introduzca un apodo en la caja inferior",
"popover": "Seleccione un apodo"
},
"messagebox": "Introduzca texto..."
},
"settings": {
"title": "CONFIGURAR",
"title": "Ajustes",
"update": "Actualizar",
"name": "Nombre",
"startAudioMuted": "Iniciar sin audio",
"startVideoMuted": "Iniciar sin vídeo",
"selectCamera": "Seleccionar cámara",
"selectMic": "Seleccionar micrófono",
"selectAudioOutput": "Selecciona salida de audio",
"followMe": "Habilitar sígueme",
"startAudioMuted": "Todos inician en silencio",
"startVideoMuted": "Todos inician ocultos",
"selectCamera": "Cámara",
"selectMic": "Micrófono",
"selectAudioOutput": "Salida de audio",
"followMe": "Todos me siguen",
"noDevice": "Ninguno",
"noPermission": "Permiso para usar el dispositivo no permitido",
"avatarUrl": "URL del Avatar"
"cameraAndMic": "Cámara y micrófono",
"moderator": "MODERADOR",
"password": "ESTABLECER CONTRASEÑA",
"audioVideo": "AUDIO Y VIDEO",
"setPasswordLabel": "Bloquear su cuarto con contraseña"
},
"profile": {
"title": "",
"setDisplayNameLabel": "Establecer nombre a mostrar",
"setEmailLabel": "Establecer su gravatar",
"setEmailInput": ""
},
"videothumbnail": {
"editnickname": "Click para editar tu <br/>nombre",
"editnickname": "Presione para editar tu <br/>nombre",
"moderator": "El propietario de<br/>esta conferencia",
"videomute": "Participante ha<br/>detenido la cámara.",
"videomute": "Participante a<br/>detenido la cámara",
"mute": "Participante está silenciado",
"kick": "Expulsar",
"muted": "Silenciado",
@@ -132,6 +157,7 @@
"flip": "Voltear"
},
"connectionindicator": {
"header": "",
"bitrate": "Tasa de bits:",
"packetloss": "Pérdida de paquetes:",
"resolution": "Resolución:",
@@ -148,63 +174,79 @@
"remoteaddress_plural": "Direcciones remotas:",
"transport": "Transporte:",
"bandwidth": "Ancho de banda estimado:",
"na": "Volver aquí para ver información de la conexión, una vez que se inicia la conferencia"
"na": "Una vez que se inicia la conferencia, volver aquí para ver información de la conexión"
},
"notify": {
"disconnected": "desconectado",
"moderator": Otorgados derechos de moderador! ",
"moderator": Se otorgaron privilegios de moderador!",
"connected": "conectado",
"somebody": "Alguien",
"me": "Yo",
"focus": "Foco de conferencia",
"focus": "Enfocar conferencia",
"focusFail": "__component__ no disponible - reintentar en __ms__ seg",
"grantedTo": Derechos de moderador otorgados a __to__!",
"grantedToUnknown": Derechos de moderador otorgados a $t(somebody)!",
"grantedTo": Se otorgaron privilegios de moderador a __to__!",
"grantedToUnknown": Se otorgaron privilegios de moderador a $t(somebody)!",
"muted": "Has iniciado la conversación silenciado.",
"mutedTitle": "¡Estás silenciado!",
"raisedHand": ""
"raisedHand": "Desearía hablar."
},
"dialog": {
"kickMessage": "¡Auch! ¡Haz sido expulsado de la reunión!",
"add": "",
"kickMessage": "¡Ouch! ¡Has sido expulsado de la reunión!",
"popupError": "Su navegador está bloqueando las ventanas emergentes de este sitio. Por favor, activa las ventanas emergentes en la configuración de seguridad del navegador y vuelva a intentarlo.",
"passwordErrorTitle": "",
"passwordError": "Esta conversación está protegida con una contraseña. Sólo el propietario de la conferencia puede establecer una contraseña.",
"passwordError2": "Esta conversación no está protegida con una contraseña. Sólo el propietario de la conferencia puede establecer una contraseña.",
"connectError": Uups! Algo salió mal y no pudimos conectarnos a la conferencia.",
"connectErrorWithMsg": Uups! Algo salió mal y no pudimos conectarnos a la conferencia: __msg__",
"connectError": Oops! Algo salio mal y no fue posible conectarnos a la conferencia.",
"connectErrorWithMsg": Oops! Algo salio mal y no fue posible conectarnos a la conferencia: __msg__",
"incorrectPassword": "",
"connecting": "Conectando",
"copy": "Copiar",
"error": "Error",
"detectext": "Error al tratar de detectar la extensión de compartir escritorio.",
"failtoinstall": "Fallo al instalar la extensión de compartir escritorio",
"failedpermissions": "Fallo al obtener permisos para utilizar el micrófono y/o cámara de tu equipo.",
"bridgeUnavailable": "Videobridge Jitsi no está actualmente disponible. ¡Por favor inténtelo más tarde!",
"jicofoUnavailable": "Jicofo no está disponible actualmente. ¡Por favor inténtelo más tarde!",
"maxUsersLimitReached": "El número máximo de participantes en la conferencia ha sido alcanzado. La conferencia está llena. ¡Por favor intente nuevamente más tarde!",
"lockTitle": "El número máximo de participantes en la conferencia ha sido alcanzado. La conferencia está llena. ¡Por favor intente nuevamente más tarde!",
"roomLocked": "",
"addPassword": "",
"createPassword": "",
"detectext": "Error al tratar de detectar la extensión para compartir escritorio.",
"failtoinstall": "Falla al instalar la extensión para compartir escritorio",
"failedpermissions": "Falla al obtener permisos para utilizar el micrófono y/o cámara de su equipo.",
"conferenceReloadTitle": "",
"conferenceReloadMsg": "",
"conferenceDisconnectTitle": "",
"conferenceDisconnectMsg": "",
"reconnectNow": "",
"conferenceReloadTimeLeft": "",
"maxUsersLimitReached": "La conferencia está llena. El número máximo de participantes de la conferencia se ha alcanzado. ¡Por favor intente más tarde!",
"lockTitle": "El bloqueo falló",
"lockMessage": "No se pudo bloquear la conferencia.",
"warning": "Advertencia",
"passwordNotSupported": "No se soportan contraseñas para la sala. ",
"sorry": "¡Perdón!",
"internalError": "Error interno de la aplicación [setRemoteDescription]",
"unableToSwitch": "No se puede activar transmisión de video",
"SLDFailure": Ups! Algo salió mal y no se logró silenciar! (Falla de SLD)",
"SRDFailure": Ups! ¡Algo salió mal y no se logró detener el video! (Falla SRD)",
"oops": Ups!",
"warning": "Aviso",
"passwordNotSupported": "No se soportan contraseñas para la sala.",
"internalErrorTitle": "Error interno",
"internalError": "¡Uups! Ocurrió algo incorrecto. Ocurrió el siguiente error: [setRemoteDescription]",
"unableToSwitch": "No se puede cambiar secuencia de video.",
"SLDFailure": Oops! Algo salio mal y no se logró silenciar! (Falla de SLD)",
"SRDFailure": Oops! ¡Algo salio mal y no se logró detener el video! (Falla de SRD)",
"oops": Oops!",
"currentPassword": "",
"passwordLabel": "",
"defaultError": "Hubo algún tipo de error",
"passwordRequired": "Se necesita contraseña",
"passwordRequired": "Se requiere una contraseña",
"Ok": "Aceptar",
"done": "",
"Remove": "Eliminar",
"removePassword": "",
"shareVideoTitle": "Compartir un vídeo",
"shareVideoLinkError": "Por favor introduzca un enlace correcto de Youtube.",
"removeSharedVideoTitle": "Eliminar video compartido",
"removeSharedVideoMsg": "¿Estas seguro que deseas eliminar tu vídeo compartido?",
"alreadySharedVideoMsg": "Otro participante esta ahora mismo compartiendo el vídeo. Esta conferencia permite sólo compartir un único vídeo a la vez.",
"WaitingForHost": "Esperando al anfitrión...",
"removeSharedVideoMsg": "¿Está seguro que desea eliminar su vídeo compartido?",
"alreadySharedVideoMsg": "Otro participante está compartiendo el vídeo en este momento. Esta conferencia permite sólo compartir un vídeo a la vez.",
"WaitingForHost": "Esperando al anfitrión ...",
"WaitForHostMsg": "La conferencia <b>__room__ </b> aún no inicia. Si usted es el anfitrión, por favor autentíquese. De lo contrario, por favor espere a que el anfitrión llegue.",
"IamHost": "Yo soy el anfitrión",
"Cancel": "Cancelar",
"Submit": "",
"retry": "Reintentar",
"logoutTitle": "Cerrar sesión",
"logoutQuestion": "¿Está seguro que quiere salir y detener la conferencia?",
"logoutQuestion": "¿Está seguro que desea salir y detener la conferencia?",
"sessTerminated": "Sesión finalizada",
"hungUp": "Colgaste",
"joinAgain": "Unirse de nuevo",
@@ -214,30 +256,33 @@
"recordingToken": "Introduzca el token de grabación",
"Dial": "Marcar",
"sipMsg": "Introduzca número SIP",
"passwordCheck": "¿Realmente quieres eliminar tu contraseña?",
"passwordMsg": "Indica una contraseña para bloquear tu sala",
"Invite": "Invitar",
"shareLink": "Comparte este enlace con las personas que deseas invitar",
"passwordCheck": "¿Realmente desea eliminar su contraseña?",
"passwordMsg": "Indique una contraseña para bloquear su sala",
"shareLink": "",
"settings1": "Configure su conferencia",
"settings2": "Los participantes se unieron silenciados",
"settings3": "Solicita nombres <br/> <br/>Establecer una contraseña para bloquear la sala:",
"yourPassword": "tu contraseña",
"Back": "Atrás",
"settings3": "Solicitar apodos<br/><br/>Establecer una contraseña para bloquear la sala:",
"yourPassword": "Introducir la nueva contraseña",
"Back": "Anterior",
"serviceUnavailable": "Servicio no disponible",
"gracefulShutdown": "Nuestro servicio está detenido por mantenimiento. Por favor, inténtelo de nuevo más tarde.",
"gracefulShutdown": "Nuestro servicio se encuentra en mantenimiento. Por favor, intente más tarde.",
"Yes": "Sí",
"reservationError": "Error de sistema de reservación",
"reservationError": "Error del sistema de reservación",
"reservationErrorMsg": "Código de error: __code__, message: __msg__",
"password": "contraseña",
"userPassword": "contraseña de usuario",
"password": "Introducir contraseña",
"userPassword": "contraseña del usuario",
"token": "token",
"tokenAuthFailed": "Error al autenticar con el servidor XMPP: token inválido",
"displayNameRequired": "Por favor escriba su nombre",
"extensionRequired": "Extensión requerida",
"firefoxExtensionPrompt": "Es necesario instalar una extensión para Firefox con el fin de utilizar la pantalla compartida. Por favor, inténtelo de nuevo después de que lo obtenga de aquí <a href='__url__'> </a>!",
"feedbackQuestion": "¿Como fue su llamada?",
"thankYou": "Gracias por usar __appName__!",
"sorryFeedback": " Sentimos escuchar eso. ¿Quieres decirnos algo más?",
"tokenAuthFailedTitle": "Problema de autenticación",
"tokenAuthFailed": "Lo siento, usted no tiene permiso para unirse a este llamada.",
"displayNameRequired": "",
"enterDisplayName": "Por favor escriba su nombre",
"extensionRequired": "Extensión requerida:",
"firefoxExtensionPrompt": "Necesita instalar una extensión para Firefox para poder utilizar la pantalla compartida. Por favor intente de nuevo, después de <a href='__url__'>obtenerla de aquí</a>!",
"rateExperience": "Por favor, califique la experiencia de su reunión.",
"feedbackHelp": "Su retroalimentación nos ayuda a mejorar nuestra experiencia de video.",
"feedbackQuestion": "¡Comente sobre su llamada!",
"thankYou": "¡Gracias por usar __appName__!",
"sorryFeedback": "Lamentamos escuchar eso. ¿Quiere decirnos algo más?",
"liveStreaming": "Emisión en Directo",
"streamKey": "Nombre/clave de emisión",
"startLiveStreaming": "Comenzar streaming en tiempo real",
@@ -246,52 +291,61 @@
"stopLiveStreaming": "Parar retransmisión en directo",
"stopRecording": "Parar grabación",
"doNotShowWarningAgain": "No volver a mostrar esta advertencia",
"doNotShowMessageAgain": "",
"permissionDenied": "Permiso Denegado",
"screenSharingPermissionDeniedError": "No ha otorgado permiso para compartir su pantalla.",
"micErrorPresent": "Hubo un error conectando su micrófono.",
"cameraErrorPresent": "Hubo un error conectando su cámara.",
"cameraUnsupportedResolutionError": "Su cámara no soporta la resolución de video.",
"cameraUnknownError": "No se puede usar su cámara por motivos desconocidos.",
"cameraPermissionDeniedError": "",
"cameraPermissionDeniedError": "No ha otorgado permisos para usar su cámara. Puede unirse a la conferencia, pero no lo podrán ver. Utilice el botón en la barra de dirección para solucionar esto.",
"cameraNotFoundError": "No se encontró la cámara.",
"cameraConstraintFailedError": "Su cámara no cumple los requerimientos.",
"micUnknownError": "No se puede usar su micrófono por motivos desconocidos.",
"micPermissionDeniedError": "",
"micPermissionDeniedError": "No ha otorgado permisos para usar su micrófono. Puede unirse a la conferencia, pero no lo podrán escuchar. Utilice el botón en la barra de dirección para solucionar esto.",
"micNotFoundError": "No se encontró el micrófono.",
"micConstraintFailedError": "Su micrófono no cumple los requerimientos."
"micConstraintFailedError": "Su micrófono no cumple los requerimientos.",
"micNotSendingData": "No fué posible acceder a su micrófono. Por favor, seleccione otro dispositivo del menú de configuración o intente reiniciando la aplicación.",
"cameraNotSendingData": "No fué posible acceder a su cámara. Por favor, revise si otra aplicación está usando el dispositivo, seleccione otro dispositivo del menú de configuración o intente reiniciando la aplicación.",
"goToStore": "Ir al webstore",
"externalInstallationTitle": "Extensión requerida",
"externalInstallationMsg": "Necesita instalar nuestra extensión para compartir escritorio.",
"muteParticipantTitle": "",
"muteParticipantBody": "",
"muteParticipantButton": "Silenciar"
},
"email": {
"sharedKey": [
"Esta conferencia está protegida con contraseña. Utiliza el siguiente pin cuando te unas: ",
"Esta conferencia está protegida con contraseña. Utiliza el siguiente pin cuando te unas:",
"",
"",
"__sharedKey__",
"",
""
],
"subject": "Invitación a a __appName__ (__conferenceName__)",
"subject": "Invitación a __appName__ (__conferenceName__)",
"body": [
"Ey allí, quiero invitarte a una a conferencia __appName__ que acabo de crear.",
"Hola, quiero invitarte a una a conferencia __appName__ que acabo de crear.",
"",
"",
"Por favor pica en la liga siguiente para unirte a la conferencia.",
"Por favor presiona el siguiente enlace para unirte a la conferencia.",
"",
"",
"__roomUrl__",
"",
"",
"__sharedKeyText__",
"Nota que __appName__ es soportada solo por __supportedBrowsers__, por lo que debes usar uno de esos navegadores.",
" Nota que __appName__ es soportada solo por __supportedBrowsers__, por lo que debes usar uno de esos navegadores.",
"",
"",
"Talk to you in a sec!"
"¡Hablamos en un segundo!"
],
"and": "y"
},
"connection": {
"ERROR": "Error",
"CONNECTING": "Conectando",
"RECONNECTING": "Ocurrió un problema en la red. Reconectando ...",
"RECONNECTING": "Ocurrió un problema en la red. Reconectando...",
"CONNFAIL": "Conexión fallida",
"AUTHENTICATING": "Autenticando",
"AUTHFAIL": "Falló la autenticación",
@@ -303,20 +357,20 @@
"recording": {
"pending": "La grabación esta esperando la entrada de un participante...",
"on": "Grabando",
"off": "Grabación parada",
"off": "Grabación detenida",
"failedToStart": "No se pudo iniciar la grabación",
"buttonTooltip": "Iniciar / parar grabación",
"buttonTooltip": "",
"error": "Falla de grabación. Vuelva a intentarlo.",
"unavailable": "El servicio de grabación no está disponible. Inténtelo más tarde."
},
"liveStreaming": {
"pending": "Iniciando Emisión en Directo",
"pending": "Iniciando Emisión en Directo...",
"on": "Emisión en Directo",
"off": "Emisión en Directo Detenida",
"unavailable": "El servicio de emisión en directo no está disponible actualmente. Por favor inténtelo de nuevo más tarde.",
"failedToStart": "La emisión en Directo falló al iniciar",
"buttonTooltip": "Iniciar / parar emisión en directo",
"streamIdRequired": "Por favor introduzca el id de emisión para poder lanzar la emisión en directo",
"buttonTooltip": "",
"streamIdRequired": "Por favor introduzca el identificador de emisión para poder iniciar la emisión en directo",
"error": "Falló el video en vivo. Por favor, vuelva a intentarlo.",
"busy": "Todos los grabadores están ocupados. Por favor intente más tarde."
}

View File

@@ -1,17 +1,19 @@
{
"contactlist": "Liste de contacts",
"contactlist": "",
"addParticipants": "",
"roomLocked": "",
"roomUnlocked": "",
"passwordSetRemotely": "",
"connectionsettings": "Paramètres de connexion",
"poweredby": "Produit par",
"downloadlogs": "Téléchargement des logs",
"feedback": "Donnez-nous votre avis",
"roomUrlDefaultMsg": "Votre conférence est en cours de création...",
"participant": "Participant",
"inviteUrlDefaultMsg": "Votre conférence est en cours de création...",
"me": "moi",
"speaker": "Haut-parleur",
"raisedHand": "Aimerais prendre la parole",
"defaultNickname": "ex. Jean Dupont",
"defaultLink": "ex. __url__",
"calling": "Appel __nom__ ...",
"callingName": "__name__",
"userMedia": {
"react-nativeGrantPermissions": "Merci d'autoriser le partage de votre camera et microphone en appuyant sur le bouton <b><i>Autoriser</i></b>",
"chromeGrantPermissions": "Merci d'autoriser le partage de votre camera et microphone en appuyant sur le bouton <b><i>Autoriser</i></b>",
@@ -23,17 +25,18 @@
"nwjsGrantPermissions": "Merci d'autoriser le partage de votre camera et microphone"
},
"keyboardShortcuts": {
"keyboardShortcuts": "Raccourcis clavier :",
"raiseHand": "Demander la parole.",
"pushToTalk": "Appuyer pour parler.",
"toggleScreensharing": "Basculer entre la caméra et le partage d'écran.",
"toggleFilmstrip": "Afficher ou masquer les vidéos miniatures.",
"toggleShortcuts": "Afficher ou masquer ce menu d'aide.",
"focusLocal": "Focus sur la vidéo locale.",
"focusRemote": "Focus sur l'une des vidéos distantes.",
"toggleChat": "Ouvrir ou fermer le panneau de conversation.",
"mute": "Activer ou désactiver le microphone.",
"videoMute": "Arrêter ou démarrer la vidéo locale."
"keyboardShortcuts": "",
"raiseHand": "",
"pushToTalk": "",
"toggleScreensharing": "",
"toggleFilmstrip": "",
"toggleShortcuts": "",
"focusLocal": "",
"focusRemote": "",
"toggleChat": "",
"mute": "",
"fullScreen": "",
"videoMute": ""
},
"welcomepage": {
"go": "Créer",
@@ -72,33 +75,45 @@
"content": "Apprenez plus au sujet de vos utilisateurs avec une intégration facile de Piwik, Google Analytics et d'autres systèmes de statistiques et supervision d'utilisation."
}
},
"startupoverlay": {
"policyText": "",
"title": ""
},
"suspendedoverlay": {
"title": "",
"rejoinKeyTitle": ""
},
"toolbar": {
"mute": "Muet / Actif",
"videomute": "Démarrer / Arrêter la caméra",
"videomute": "",
"authenticate": "Authentifiez-vous",
"lock": "Verrouiller / déverrouiller la salle",
"invite": "Inviter des participants",
"chat": "Ouvrir / fermer le chat",
"etherpad": "Document partagé",
"lock": "",
"invite": "",
"chat": "",
"etherpad": "",
"sharedvideo": "Partager une vidéo Youtube",
"sharescreen": "Partager mon écran",
"fullscreen": "Activer / Désactiver le plein écran",
"sharescreen": "",
"fullscreen": "",
"sip": "Appeler un numéro SIP",
"Settings": "Paramètres",
"hangup": "Raccrocher",
"hangup": "",
"login": "Connexion",
"logout": "Déconnexion",
"dialpad": "Afficher le clavier de numérotation",
"dialpad": "",
"sharedVideoMutedPopup": "Votre vidéo a été mise en muet<br/>pour que vous puissiez parler aux autres participants.",
"micMutedPopup": "Votre microphone a été désactivé afin que vous<br/>puissiez profiter pleinement de votre vidéo partagée.",
"talkWhileMutedPopup": "",
"unableToUnmutePopup": "Vous ne pouvez pas réactiver votre microphone pendant que la vidéo partagée est activée.",
"cameraDisabled": "La camera n'est pas disponible",
"micDisabled": "Le microphone n'est pas disponible"
"micDisabled": "Le microphone n'est pas disponible",
"filmstrip": "",
"profile": "",
"raiseHand": ""
},
"bottomtoolbar": {
"chat": "Ouvrir / fermer le chat",
"filmstrip": "Montrer / cacher ma vidéo miniature",
"contactlist": "Ouvrir / fermer ma liste de contacts"
"filmstrip": "Afficher / cacher les vidéos",
"contactlist": ""
},
"chat": {
"nickname": {
@@ -108,23 +123,33 @@
"messagebox": "Saisissez votre texte..."
},
"settings": {
"title": "PARAMÈTRES",
"title": "Paramètres",
"update": "Mise à jour",
"name": "Nom",
"startAudioMuted": "Démarrer sans son",
"startVideoMuted": "Démarrer sans vidéo",
"selectCamera": "Sélectionnez une caméra",
"selectMic": "Sélectionnez un microphone",
"selectAudioOutput": "Sélectionner la sortie audio",
"followMe": "Activer \"me suivre\"",
"startAudioMuted": "Tout le monde commence en muet",
"startVideoMuted": "Tout le monde commence masqué",
"selectCamera": "Caméra",
"selectMic": "Microphone",
"selectAudioOutput": "Sortie audio",
"followMe": "Tout le monde me suit",
"noDevice": "Aucun",
"noPermission": "L'autorisation d'utiliser l'appareil n'a pas été accordé",
"avatarUrl": "URL de l'avatar"
"cameraAndMic": "Caméra et microphone",
"moderator": "MODÉRATEUR",
"password": "DÉFINIR UN MOT DE PASSE",
"audioVideo": "AUDIO ET VIDÉO",
"setPasswordLabel": "Verrouiller votre salle avec un mot de passe."
},
"profile": {
"title": "",
"setDisplayNameLabel": "Choisissez un pseudo",
"setEmailLabel": "Définir votre courriel Gravatar",
"setEmailInput": ""
},
"videothumbnail": {
"editnickname": "Cliquez pour modifier<br/>votre nom",
"moderator": "Le propriétaire de<br/>cette conférence",
"videomute": "Un participant a<br/>arrêté sa caméra.",
"videomute": "Un participant a<br/>arrêté sa caméra",
"mute": "Un participant a coupé son micro",
"kick": "Exclure",
"muted": "Muet",
@@ -132,6 +157,7 @@
"flip": "Retourner"
},
"connectionindicator": {
"header": "",
"bitrate": "Débit :",
"packetloss": "Perte de paquets :",
"resolution": "Résolution :",
@@ -165,34 +191,49 @@
"raisedHand": "Aimerais prendre la parole."
},
"dialog": {
"add": "",
"kickMessage": "Oups! Vous avez été renvoyé de la réunion !",
"popupError": "Votre navigateur bloque les fenêtres popup de ce site. Merci d'activer les popups dans les paramètres de sécurité de votre navigateur et d'essayer à nouveau.",
"passwordErrorTitle": "",
"passwordError": "Cette conversation est actuellement protégée par un mot de passe. Seul le propriétaire de la conférence peut définir un mot de passe.",
"passwordError2": "Cette conversation n'est actuellement pas protégé par un mot de passe. Seul le propriétaire de la conférence peut définir un mot de passe.",
"connectError": "Oups! Un problème est survenu et la connexion à la conférence est impossible.",
"connectErrorWithMsg": "Oups! Un problème est survenu et la connexion à la conférence est impossible: __msg__",
"incorrectPassword": "",
"connecting": "Connexion en cours",
"copy": "Copier",
"error": "Erreur",
"roomLocked": "",
"addPassword": "",
"createPassword": "",
"detectext": "Une erreur est survenue pendant la détection de l'extension de partage d'écran.",
"failtoinstall": "Échec de l'installation de l'extension de partage d'écran",
"failedpermissions": "Échec d'obtention des permissions pour utiliser le micro et/ou la caméra.",
"bridgeUnavailable": "Le pont de visioconférence Jitsi est indisponible pour le moment. Réessayez plus tard !",
"jicofoUnavailable": "Le pont de visioconférence Jitsi est indisponible pour le moment. Réessayez plus tard !",
"conferenceReloadTitle": "",
"conferenceReloadMsg": "",
"conferenceDisconnectTitle": "",
"conferenceDisconnectMsg": "",
"reconnectNow": "",
"conferenceReloadTimeLeft": "",
"maxUsersLimitReached": "La limite pour le nombre maximum de participants à la conférence a été atteinte. La conférence est pleine. Veuillez réessayer plus tard !",
"lockTitle": "Échec du verrouillage",
"lockMessage": "Impossible de verrouiller la conférence.",
"warning": "Avertissement",
"passwordNotSupported": "Les mots de passe de conférence ne sont pas supportés.",
"sorry": "Désolé",
"internalError": "Une erreur interne de l'application est survenue [setRemoteDescription]",
"internalErrorTitle": "Erreur interne",
"internalError": "Oups ! Quelque chose s'est mal passé. L'erreur suivante est apparue : [setRemoteDescription]",
"unableToSwitch": "Impossible de changer le flux vidéo.",
"SLDFailure": "Oups! Un problème est survenu et le micro n'a pas été coupé! (Échec SLD)",
"SRDFailure": "Oups! Un problème est survenu et la caméra n'a pas été coupée! (Échec SRD)",
"oops": "Oups !",
"currentPassword": "",
"passwordLabel": "",
"defaultError": "Une erreur est survenue",
"passwordRequired": "Mot de passe requis",
"Ok": "Ok",
"done": "",
"Remove": "Supprimer",
"removePassword": "",
"shareVideoTitle": "Partager une vidéo",
"shareVideoLinkError": "Fournissez s'il vous plaît un lien Youtube fonctionnel.",
"removeSharedVideoTitle": "Supprimer la vidéo partagée",
@@ -202,6 +243,7 @@
"WaitForHostMsg": "La conférence <b>__room__</b> n'a pas encore commencé. Si vous êtes l'hôte, merci de vous authentifier. Sinon, merci d'attendre que l'hôte arrive.",
"IamHost": "Je suis lhôte",
"Cancel": "Annuler",
"Submit": "",
"retry": "Réessayer",
"logoutTitle": "Déconnexion",
"logoutQuestion": "Voulez-vous vraiment vous déconnecter et arrêter la conférence ?",
@@ -216,26 +258,29 @@
"sipMsg": "Saisissez un numéro SIP",
"passwordCheck": "Voulez-vous vraiment supprimer votre mot de passe ?",
"passwordMsg": "Saisissez un mot de passe pour verrouiller la conférence",
"Invite": "Inviter",
"shareLink": "Partagez ce lien avec toutes les personnes que vous voulez inviter",
"shareLink": "",
"settings1": "Configurez votre conférence",
"settings2": "Les participants rejoignent la conférence en étant muets",
"settings3": "Pseudonymes requis<br/><br/>Saisissez un mot de passe pour verrouiller la conférence :",
"yourPassword": "votre mot de passe",
"yourPassword": "Saisissez un nouveau mot de passe",
"Back": "Retour",
"serviceUnavailable": "Service indisponible",
"gracefulShutdown": "Le service est actuellement en maintenance. Réessayez plus tard.",
"Yes": "Oui",
"reservationError": "Erreur du système de réservation",
"reservationErrorMsg": "Code d'erreur: __code__, message: __msg__",
"password": "mot de passe",
"password": "Saisir le mot de passe",
"userPassword": "mot de passe utilisateur",
"token": "jeton",
"tokenAuthFailed": "Échec de l'authentification avec le serveur XMPP : jeton non valide",
"displayNameRequired": "Veuillez saisir votre nom",
"tokenAuthFailedTitle": "Échec de l'authentification",
"tokenAuthFailed": "Désolé, vous n'êtes pas autorisé à rejoindre cette conversation.",
"displayNameRequired": "",
"enterDisplayName": "Veuillez saisir votre nom",
"extensionRequired": "Extension requise :",
"firefoxExtensionPrompt": "Vous devez installer une extension Firefox pour utiliser le partage d'écran. Merci d'essayer de nouveau après l'installation <a href='__url__'>depuis ce lien</a> !",
"feedbackQuestion": "Comment était votre conférence ?",
"rateExperience": "Veuillez évaluer votre réunion.",
"feedbackHelp": "Vos retours nous permettrons d'améliorer notre expérience vidéo.",
"feedbackQuestion": "Informez-nous à propos de votre appel !",
"thankYou": "Merci d'avoir utilisé __appName__ !",
"sorryFeedback": "Nous sommes désolés d'apprendre cela. Voulez-vous nous en dire plus ?",
"liveStreaming": "Direct",
@@ -246,6 +291,7 @@
"stopLiveStreaming": "Arrêter le direct",
"stopRecording": "Arrêter l'enregistrement",
"doNotShowWarningAgain": "Ne plus afficher cet avertissement",
"doNotShowMessageAgain": "",
"permissionDenied": "Permission refusée",
"screenSharingPermissionDeniedError": "Vous n'avez pas autorisé le partage de votre écran.",
"micErrorPresent": "Une erreur est survenue lors de la connexion à votre microphone.",
@@ -253,12 +299,20 @@
"cameraUnsupportedResolutionError": "Votre appareil ne prend pas en charge la résolution vidéo requise.",
"cameraUnknownError": "Vous ne pouvez pas utiliser la caméra pour une raison inconnue.",
"cameraPermissionDeniedError": "Vous n'avez pas autorisé l'utilisation de votre caméra. Vous pouvez toujours participer à la conférence, mais les autres ne vont pas vous voir. Utilisez le bouton de la caméra dans la barre d'adresse pour résoudre ce problème.",
"cameraNotFoundError": "La caméra demandée n'a pas été trouvée.",
"cameraNotFoundError": "La caméra n'a pas été trouvée",
"cameraConstraintFailedError": "Votre caméra ne satisfait pas certaines des contraintes nécessaires.",
"micUnknownError": "Vous ne pouvez pas utiliser le microphone pour une raison inconnue.",
"micPermissionDeniedError": "Vous n'avez pas autorisé l'utilisation de votre microphone. Vous pouvez toujours participer à la conférence, mais les autres ne vont pas vous entendre. Utilisez le bouton du microphone dans la barre d'adresse pour résoudre ce problème.",
"micNotFoundError": "Le microphone demandé n'a pas été trouvé.",
"micConstraintFailedError": "Votre microphone ne satisfait pas certaines des contraintes nécessaires."
"micNotFoundError": "Le microphone n'a pas été détecté.",
"micConstraintFailedError": "Votre microphone ne satisfait pas certaines des contraintes nécessaires.",
"micNotSendingData": "Nous ne pouvons pas accéder à votre microphone. Veuillez sélectionner un autre périphérique dans le menu des paramètres ou essayez de redémarrer l'application.",
"cameraNotSendingData": "Nous ne pouvons pas accéder à votre caméra. Vérifiez si une autre application utilise ce périphérique, sélectionnez un autre périphérique dans le menu des paramètres ou essayez de redémarrer l'application.",
"goToStore": "Aller sur le webstore",
"externalInstallationTitle": "Extension requise : ",
"externalInstallationMsg": "Vous devez installer notre extension de partage de bureau.",
"muteParticipantTitle": "",
"muteParticipantBody": "",
"muteParticipantButton": "Couper le son"
},
"email": {
"sharedKey": [
@@ -305,7 +359,7 @@
"on": "Enregistrement",
"off": "Enregistrement arrêter",
"failedToStart": "L'enregistrement n'as pas réussi à démarrer",
"buttonTooltip": "Démarrer / arrêter l'enregistrement",
"buttonTooltip": "",
"error": "Échec de l'enregistrement. Veuillez réessayer.",
"unavailable": "Le service d'enregistrement est actuellement indisponible. Veuillez réessayer plus tard."
},
@@ -315,7 +369,7 @@
"off": "Le direct a été arrêter",
"unavailable": "Le direct est temporairement indisponible. Veuillez réessayer plus tard.",
"failedToStart": "Le direct n'as pas réussi à démarrer",
"buttonTooltip": "Démarrer / arrêter le direct",
"buttonTooltip": "",
"streamIdRequired": "Merci de renseigner le stream id pour lancer le direct.",
"error": "La retransmission en direct a échoué. Veuillez réessayer.",
"busy": "Tous les enregistreurs sont actuellement occupés. Veuillez réessayer plus tard."

View File

@@ -1,9 +1,13 @@
{
"contactlist": "Զանգ",
"contactlist": "",
"addParticipants": "",
"roomLocked": "",
"roomUnlocked": "",
"passwordSetRemotely": "",
"connectionsettings": "Միացման կարգավորումներ",
"poweredby": "Հիմնված է",
"feedback": "Հայտնեք ձեր կարծիքը",
"roomUrlDefaultMsg": "Ձեր կոնֆերանսը այժմ ստեղծվում է...",
"inviteUrlDefaultMsg": "Ձեր կոնֆերանսը այժմ ստեղծվում է...",
"me": "ես",
"speaker": "Հռետոր",
"raisedHand": "Ցանկանում է խոսել",
@@ -11,27 +15,28 @@
"defaultLink": "օրինակ՝ __url__",
"callingName": "__անուն__",
"userMedia": {
"react-nativeGrantPermissions": "",
"chromeGrantPermissions": "",
"androidGrantPermissions": "",
"react-nativeGrantPermissions": "Խնդրում ենք տրամադրել տեսախցիկը և խոսափողը օգտագործելու թույլտվություններ <b> <i>ընդունել</ i> </ b> կոճակը",
"chromeGrantPermissions": "Խնդրում ենք տրամադրել տեսախցիկը և խոսափողը օգտագործելու թույլտվություններ <b> <i>ընդունել</ i> </ b> կոճակը",
"androidGrantPermissions": "Խնդրում ենք տրամադրել տեսախցիկը և խոսափողը օգտագործելու թույլտվություններ <b> <i>ընդունել</ i> </ b> կոճակը",
"firefoxGrantPermissions": "Խնդրում ենք տրամադրել տեսախցիկը և խոսափողը օգտագործելու թույլտվություններ <b> <i> տարածել նշված սարքը </ i> </ b> կոճակը",
"operaGrantPermissions": "Խնդրում ենք տրամադրել տեսախցիկը և խոսափողը օգտագործելու թույլտվություններ <b> <i>ընդունել</ i> </ b> կոճակը",
"iexplorerGrantPermissions": "",
"iexplorerGrantPermissions": "Խնդրում ենք տրամադրել տեսախցիկը և խոսափողը օգտագործելու թույլտվություններ <b> <i>Այո</ i> </ b> կոճակը",
"safariGrantPermissions": "Խնդրում ենք տրամադրել տեսախցիկը և խոսափողը օգտագործելու թույլտվություններ <b> <i>Այո</ i> </ b> կոճակը",
"nwjsGrantPermissions": "Խնդրում ենք տրամադրել տեսախցիկը և խոսափողը օգտագործելու թույլտվություններ"
},
"keyboardShortcuts": {
"keyboardShortcuts": "Ստեղնաշարի դյուրանցումներ (shortcuts)",
"raiseHand": "Բարձրացրեք Ձեր ձեռքը",
"pushToTalk": "Սեղմեք խոսելու համար",
"toggleScreensharing": "Անցնել ֆոտոխցիկի և էկրանի փոխանակման միջև",
"toggleFilmstrip": "Ցույց տալ կամ թաքցնել տեսանյութերը",
"toggleShortcuts": "Ցույց տալ կամ թաքցնել այս օգնության մենյուն",
"focusLocal": "Կենտրոնանալ տեղական տեսանյութի վրա",
"focusRemote": "Կենտրոնանալ տեղական տեսանյութի վրա",
"toggleChat": "Բացել կամ փակել չատի պանելը",
"mute": "Անջատել կամ միացնել խոսափողը",
"videoMute": "Կանգնեցնել կամ սկսել տեղական տեսանյութը"
"keyboardShortcuts": "",
"raiseHand": "",
"pushToTalk": "",
"toggleScreensharing": "",
"toggleFilmstrip": "",
"toggleShortcuts": "",
"focusLocal": "",
"focusRemote": "",
"toggleChat": "",
"mute": "",
"fullScreen": "",
"videoMute": ""
},
"welcomepage": {
"go": "ՄՈՒՏՔ",
@@ -70,35 +75,45 @@
"content": "Օգտագործման վիճակագրություն կարելի է ստանալ հեշտ ինտեգրվող Piwik, Google Analytics կամ այլ մոնիտորինգի համակարգերի միջոցով:"
}
},
"startupoverlay": {
"policyText": "",
"title": ""
},
"suspendedoverlay": {
"title": "",
"rejoinKeyTitle": ""
},
"toolbar": {
"mute": "Ձայնը Միացնել/Անջատել ",
"videomute": "Տեսախցիկը Միացնել/Անջատել ",
"videomute": "",
"authenticate": "Վավերացում",
"lock": "Փակել/բացել սենյակը",
"invite": "Հրավիրել ուրիշներին",
"chat": "Բացել/փակել չատը",
"etherpad": "Համատեղ փաստաթուղթ",
"lock": "",
"invite": "",
"chat": "",
"etherpad": "",
"sharedvideo": "Կիսվել YouTube-ի նյութով",
"sharescreen": "Ցուցադրել էկրանը",
"fullscreen": "Ամբողջ Էկրանի ռեժիմը միացնել/անջատել",
"sharescreen": "",
"fullscreen": "",
"sip": "Զանգել SIP համարով",
"Settings": "Կարգավորումներ",
"hangup": "Անջատել",
"hangup": "",
"login": "Մուտք",
"logout": "Ելք",
"dialpad": "Ցույց տալ թվաշարը",
"dialpad": "",
"sharedVideoMutedPopup": "Ձեր ցուցադրված տեսանյութի ձայնը անջատված է, այնպես որ <br />, կարող եք խոսել մյուս մասնակիցների հետ:",
"micMutedPopup": "Ձեր խոսափողը անջատված է՝<br/> կարող եք լիովին վայելել ձեր ցուցադրված տեսանյութը:",
"talkWhileMutedPopup": "",
"unableToUnmutePopup": "Դուք չեք կարող միացնել ձայնը, քանի դեռ միանցված է ցուցադրվող տեսանյութը:",
"cameraDisabled": "Տեսախցիկը հասանելի չէ",
"micDisabled": "Խոսափողը հասանելի չէ",
"filmstrip": "",
"raiseHand": "Բարձրացրեք ձեռքը խոսելու համար"
"profile": "",
"raiseHand": ""
},
"bottomtoolbar": {
"chat": "Բացել/փակել չատը",
"filmstrip": "Ցույց տալ/թաքցնել տեսանյութները",
"contactlist": "Բացել/փակել կոնտակտների ցուցակը"
"contactlist": ""
},
"chat": {
"nickname": {
@@ -126,9 +141,10 @@
"setPasswordLabel": "Փակել սենյակը գաղտնաբառով"
},
"profile": {
"title": "Էջ",
"title": "",
"setDisplayNameLabel": "Դնել Ձեր երևացող անունը",
"setEmailLabel": "Սահմանեք Ձեր gravatar էլ.փոստը"
"setEmailLabel": "Սահմանեք Ձեր gravatar էլ.փոստը",
"setEmailInput": ""
},
"videothumbnail": {
"editnickname": "Սեղմեք Ձեր անունը <br/>փոխելու համար",
@@ -141,6 +157,7 @@
"flip": "Շրջել"
},
"connectionindicator": {
"header": "",
"bitrate": "Բիթրեյթ",
"packetloss": "Փաթեթների կորուստ՝",
"resolution": "Որակ՝",
@@ -170,20 +187,30 @@
"raisedHand": "Ցանկանում է խոսել"
},
"dialog": {
"add": "",
"kickMessage": "Վա՜յ: Ձեզ դուրս հանեցին հանդիպումից:",
"popupError": "Ձեր բրաուզերը արգելափակել է թռուցիկ(popup) պատուհանները այս կայքում: Խնդրում ենք միացրեք թռուցիկները Ձեր բրաուզերի անվտանգության կարգավորումներում և կրկին փորձեք:",
"passwordErrorTitle": "",
"passwordError": "Այս խոսակցությունը այս պահին պաշտպանված է գաղտնաբառով:Միայն կոնֆերանսի սեփականատերը կարող է սահմանել գաղտնաբառ:",
"passwordError2": "Այս խոսակցությունը այս պահին պաշտպանված չէ գաղտնաբառով:Միայն կոնֆերանսի սեփականատերը կարող է սահմանել գաղտնաբառ:",
"connectError": "Ու՜պս! Ինչոր բան այն չէ և մենք չկարողացանք միանալ կոնֆերանսին:",
"connectErrorWithMsg": "Ու՜պս! Ինչոր բան այն չէ և մենք չկարողացանք միանալ կոնֆերանսին: __msg__",
"incorrectPassword": "",
"connecting": "Միանում է...",
"copy": "Պատճենել",
"error": "Սխալ",
"roomLocked": "",
"addPassword": "",
"createPassword": "",
"detectext": "Սխալ, երբ փորձում է հայտնաբերել էկրանի ցուցադրման ընդլայնումը:",
"failtoinstall": "Չհաջողվեց տեղադրել էկրանի ցուցադրման ընդլայնումը",
"failedpermissions": "Չհաջողվեց ստանալ թույլտվություն օգտագործելու տեղի խոսափողը և/ կամ տեսախցիկը:",
"bridgeUnavailable": "Jitsi Videobridge-ը ներկայումս անհասանելի է: Խնդրում ենք փորձեք մի փոքր ուշ!",
"jicofoUnavailable": "Jicofo ներկայումս անհասանելի է: Խնդրում ենք փորձեք ավելի ուշ:",
"conferenceReloadTitle": "",
"conferenceReloadMsg": "",
"conferenceDisconnectTitle": "",
"conferenceDisconnectMsg": "",
"reconnectNow": "",
"conferenceReloadTimeLeft": "",
"maxUsersLimitReached": "Մասնակիցների առավելագույն թիվը արդեն լրացել է: Մասնակիցները արդեն հավաքվել են: Խնդրում ենք փորձեք ավելի ուշ:",
"lockTitle": "Փակումը ձախողվեց",
"lockMessage": "Ձախողվեց արգելափակել կոնֆերանսը:",
@@ -195,10 +222,14 @@
"SLDFailure": "Ու՜պս: Ինչ-որ բան գնաց սխալ, և մենք չկարողացանք անջատել ձայնը (SLD Failure)",
"SRDFailure": "Ու՜պս: Ինչ-որ բան գնաց սխալ, և մենք չկարողացանք անջատել տեսահոսքը (SRD Failure)",
"oops": "Ու՜պս:",
"currentPassword": "",
"passwordLabel": "",
"defaultError": "Առկա էր որոշակի սխալ",
"passwordRequired": "Պահանջվում է գաղտնաբառ",
"Ok": "Ok",
"done": "",
"Remove": "Հեռացնել",
"removePassword": "",
"shareVideoTitle": "Տարածել տեսանյութը",
"shareVideoLinkError": "Խնդրում ենք ներկայացնել ճիշտ Youtube հղում:",
"removeSharedVideoTitle": "Հեռացնել տարածված տեսանյութը",
@@ -208,6 +239,7 @@
"WaitForHostMsg": "Կոնֆերանսը <b> __ root__ </ b> դեռ չի սկսվել. Եթե դուք են հյուրընկալող եք ապա խնդրում ենք հաստատել իսկությունը: Հակառակ դեպքում, խնդրում ենք սպասել հյուրընկալող կժամանի.",
"IamHost": "Ես եմ ընդունողը",
"Cancel": "Չեղարկել",
"Submit": "",
"retry": "Կրկին փորձել",
"logoutTitle": "Ելք",
"logoutQuestion": "Համոզված եք, որ ցանկանում եք դուրս գալ, եւ դադարեցնել կոնֆերանսը:",
@@ -222,7 +254,7 @@
"sipMsg": "Նշեք SIP համարը",
"passwordCheck": "Դուք վստա՞հ էք որ ցանկանում էք ջնջել Ձեր գաղտնաբառը։",
"passwordMsg": "Սահմանել գաղտնաբառ ձեր սենյակը կողպելու համար",
"shareLink": "Պատճենել և կիսվել այս հղումով",
"shareLink": "",
"settings1": "Կարգավորել Ձեր կոնֆերանսը",
"settings2": "Մասնակիցները միացան անջատվախ ձայնով",
"settings3": "Պահանջվում է մականունը<br/><br/>Դրեք գաղտնաբառ Ձեր սենյակը արգելափակելու համար",
@@ -238,7 +270,8 @@
"token": "սիմվոլ",
"tokenAuthFailedTitle": "Վավերացումը չի ստացվել",
"tokenAuthFailed": "Ներողություն,Դուք ընդունված չեք այս զանգին միանալու համար",
"displayNameRequired": "Խնդրում ենք մուտքագրել Ձեր ցուցադրման անունը",
"displayNameRequired": "",
"enterDisplayName": "Խնդրում ենք մուտքագրել Ձեր ցուցադրման անունը",
"extensionRequired": "Ընդլայնում է պահանջվում:",
"firefoxExtensionPrompt": "Դուք պետք է տեղադրեք Firefox ընդլայնում, որպեսզի օգտագործել էկրանի փոխանակման ռեժիմը: Խնդրում ենք փորձեք կրկին՝ այն <a href='__url__'> այստեղից ձեռք բերելուց հետո</a>:",
"rateExperience": "Խնդրում ենք ներկայացրեք Ձեր հանդիպման փորձը",
@@ -254,6 +287,7 @@
"stopLiveStreaming": "Կանգնացնել ուղիղ հեռարձակումը:",
"stopRecording": "Կանգնացնել ձայնագրումը",
"doNotShowWarningAgain": "Այլևս ցույց չտալ այս նախազգուշական էջը",
"doNotShowMessageAgain": "",
"permissionDenied": "Թույլատվությունը արգելված է",
"screenSharingPermissionDeniedError": "Դուք չունեք թույլտվություն կիսվել Ձեր էկրանով",
"micErrorPresent": "Տեղի է ունեցել սխալ Ձեր խոսափողին միանալիս",
@@ -271,7 +305,10 @@
"cameraNotSendingData": "Մենք չեն կարողանում միանալ Ձեր տեսախցիկին: Խնդրում ենք ստուգեք թե արդյոք մեկ ուրիշ սարք չի օգտագործում այն կամ ընտրեք մեկ այլ սարք կարգավորումների ցանկից կամ փորձեք վերսկսել ծրագիրը:",
"goToStore": "Գնալ դեպի վեբ խանութ",
"externalInstallationTitle": "Ընդլայնում է պահանջվում:",
"externalInstallationMsg": "Չհաջողվեց տեղադրել էկրանի ցուցադրման ընդլայնումը"
"externalInstallationMsg": "Չհաջողվեց տեղադրել էկրանի ցուցադրման ընդլայնումը",
"muteParticipantTitle": "",
"muteParticipantBody": "",
"muteParticipantButton": "Անջատել ձայնը"
},
"email": {
"sharedKey": [
@@ -314,7 +351,7 @@
"on": "Գրանցում",
"off": "Ձայնագրությունը կանգնացված է",
"failedToStart": "Ձայնագրությունը ստացվեց սկսել",
"buttonTooltip": "Սկսել / կանգնացնել ձայնագրությունը",
"buttonTooltip": "",
"error": "Ձայնագրությյունը չստացվեց: Փորձեք կրկին",
"unavailable": "Ձայնագրության ծառայությունը ներկայումս անհասանելի է: Խնդրում եմ փորձեք մի փոքր ուշ:"
},
@@ -324,7 +361,7 @@
"off": "Ուղիղ Հեռարձակումը կանգնեցված է",
"unavailable": "Ուղիղ հեռարձակման ծառայությունը ներկայումս հասանելի չէ: Խնդրում եք փորձեք ավելի ուշ:",
"failedToStart": "Ուղիղ հեռարձակումը չստացվեց սկսել",
"buttonTooltip": "Սկսել / կանգնեցնել ուղիղ հեռարձակումը",
"buttonTooltip": "",
"streamIdRequired": "Խնդրում ենք լրացնել հոսքի ID-ն, որպեսզի կսկսի հեռարձակումը:",
"error": "Ուղիղ հեռարձակումը չստացվեց: Փորձեք կրկին",
"busy": "Բոլոր ձայնագրիչները ներկայումս զբաղված են: Խնդրում ենք փորձեք մի փոքր ուշ:"

View File

@@ -1,17 +1,19 @@
{
"contactlist": "LISTA CONTATTI",
"contactlist": "",
"addParticipants": "",
"roomLocked": "",
"roomUnlocked": "",
"passwordSetRemotely": "",
"connectionsettings": "Impostazioni Connessione",
"poweredby": "powered by",
"downloadlogs": "Scarica logs",
"feedback": "",
"roomUrlDefaultMsg": "La tua conferenza sta per essere creata...",
"participant": "Partecipante",
"inviteUrlDefaultMsg": "La tua conferenza sta per essere creata...",
"me": "io",
"speaker": "Relatore",
"raisedHand": "",
"defaultNickname": "",
"defaultLink": "es. __url__",
"calling": "",
"callingName": "",
"userMedia": {
"react-nativeGrantPermissions": "",
"chromeGrantPermissions": "",
@@ -33,6 +35,7 @@
"focusRemote": "",
"toggleChat": "",
"mute": "",
"fullScreen": "",
"videoMute": ""
},
"welcomepage": {
@@ -72,33 +75,45 @@
"content": "Impara come i tuoi utenti lo utilizzano con la facile integrazione con PiWik, Google Analytics, e altri sistemi di statistica e monitor dell'utilizzo."
}
},
"startupoverlay": {
"policyText": "",
"title": ""
},
"suspendedoverlay": {
"title": "",
"rejoinKeyTitle": ""
},
"toolbar": {
"mute": "Microfono Attiva / Disattiva",
"videomute": "Abilita / Disabilita video",
"videomute": "",
"authenticate": "Autenticazione",
"lock": "Blocca / Sblocca Stanza",
"invite": "Invita altri",
"chat": "Apri / Chiudi chat",
"etherpad": "Documento condiviso",
"lock": "",
"invite": "",
"chat": "",
"etherpad": "",
"sharedvideo": "",
"sharescreen": "Condividi schermo",
"fullscreen": "Entra / Esci da schermo intero",
"sharescreen": "",
"fullscreen": "",
"sip": "Chiama numero SIP",
"Settings": "Impostazioni",
"hangup": "Termina",
"hangup": "",
"login": "Login",
"logout": "Logout",
"dialpad": "Mostra il tastierino",
"dialpad": "",
"sharedVideoMutedPopup": "",
"micMutedPopup": "",
"talkWhileMutedPopup": "",
"unableToUnmutePopup": "",
"cameraDisabled": "",
"micDisabled": ""
"micDisabled": "",
"filmstrip": "",
"profile": "",
"raiseHand": ""
},
"bottomtoolbar": {
"chat": "Apri / Chiudi chat",
"filmstrip": "Mostra / Nascondi miniature",
"contactlist": "Apri / Chiudi la lista contatti"
"filmstrip": "",
"contactlist": ""
},
"chat": {
"nickname": {
@@ -108,7 +123,7 @@
"messagebox": "Inserisci testo..."
},
"settings": {
"title": "IMPOSTAZIONI",
"title": "Impostazioni",
"update": "Aggiorna",
"name": "Nome",
"startAudioMuted": "",
@@ -119,12 +134,22 @@
"followMe": "",
"noDevice": "",
"noPermission": "",
"avatarUrl": ""
"cameraAndMic": "",
"moderator": "",
"password": "",
"audioVideo": "",
"setPasswordLabel": ""
},
"profile": {
"title": "",
"setDisplayNameLabel": "",
"setEmailLabel": "",
"setEmailInput": ""
},
"videothumbnail": {
"editnickname": "Clicca per modificare il tuo<br/>nome visualizzato",
"moderator": "Il proprietario<br/>della conferenza",
"videomute": "Il partecipante ha<br/>fermato il video.",
"videomute": "",
"mute": "Il partecipante è in muto",
"kick": "Espelli",
"muted": "Audio disattivato",
@@ -132,6 +157,7 @@
"flip": ""
},
"connectionindicator": {
"header": "",
"bitrate": "Bitrate:",
"packetloss": "Perdita pacchetti:",
"resolution": "Risoluzione:",
@@ -165,43 +191,59 @@
"raisedHand": ""
},
"dialog": {
"add": "",
"kickMessage": "Accidenti! Sei stato espulso dalla conferenza !",
"popupError": "",
"passwordErrorTitle": "",
"passwordError": "",
"passwordError2": "",
"connectError": "Oops! Qualcosa è andato storto e non ti puoi collegare alla conferenza.",
"connectErrorWithMsg": "Oops! Qualcosa è andato storto e non ti puoi collegare alla conferenza: __msg__",
"incorrectPassword": "",
"connecting": "Connessione",
"copy": "",
"error": "Errore",
"roomLocked": "",
"addPassword": "",
"createPassword": "",
"detectext": "Errore durante il rilevamento dell'estensione per il desktopsharing.",
"failtoinstall": "Impossibile installare l'estensione per il desktop sharing",
"failedpermissions": "Impossibile ottenere i permessi per usare il microfono e/o il video locale.",
"bridgeUnavailable": "Il Videobridge non è al momento disponibile. Si prega di riprovare più tardi!",
"jicofoUnavailable": "",
"conferenceReloadTitle": "",
"conferenceReloadMsg": "",
"conferenceDisconnectTitle": "",
"conferenceDisconnectMsg": "",
"reconnectNow": "",
"conferenceReloadTimeLeft": "",
"maxUsersLimitReached": "",
"lockTitle": "Blocco fallito",
"lockMessage": "",
"lockMessage": "Impossibile bloccare la conferenza.",
"warning": "Attenzione",
"passwordNotSupported": "Le password sulla stanza non sono al momento supportate.",
"sorry": "Spiacente",
"internalError": "Errore interno dell'applicazione [setRemoteDescription]",
"internalErrorTitle": "",
"internalError": "",
"unableToSwitch": "Impossibile cambiare lo stream video.",
"SLDFailure": "Oops! Qualcosa è andato storto e non è possibile silenziare il microfono! (Errore SLD)",
"SRDFailure": "Oops! Qualcosa è andato storto e non è possibile fermare il video! (Errore SRD)",
"oops": "Oops!",
"currentPassword": "",
"passwordLabel": "",
"defaultError": "C'è stato qualche tipo di errore",
"passwordRequired": "Richiesta password ",
"Ok": "Ok",
"done": "",
"Remove": "Rimuovi",
"removePassword": "",
"shareVideoTitle": "",
"shareVideoLinkError": "",
"shareVideoLinkError": "Fornire un link Prezi esatto.",
"removeSharedVideoTitle": "",
"removeSharedVideoMsg": "",
"removeSharedVideoMsg": "Sei sicuro di voler rimuovere il tuo Prezi?",
"alreadySharedVideoMsg": "",
"WaitingForHost": "In attesa dell'organizzatore ...",
"WaitForHostMsg": "La conferenza <b>__room__ </b> non è ancora iniziata. Se sei l'organizzatore sei pregato di autenticarti, altrimenti ti preghiamo di attendere l'arrivo dell'organizzatore.",
"IamHost": "Sono l'organizzatore",
"Cancel": "Annulla",
"Submit": "",
"retry": "Riprova",
"logoutTitle": "Logout",
"logoutQuestion": "Vuoi disconnetterti e interrompere la conferenza ?",
@@ -216,25 +258,28 @@
"sipMsg": "Inserire numero SIP",
"passwordCheck": "Confermi la rimozione della password?",
"passwordMsg": "Imposta una password per bloccare la stanza",
"Invite": "Invita",
"shareLink": "Condividi questo link con tutte le persone che vuoi invitare",
"shareLink": "",
"settings1": "Configura la tua conferenza",
"settings2": "Partecipanti connessi in muto",
"settings3": "Richiedi nicknames<br/><br/>Imposta una password per bloccare la tua stanza:",
"yourPassword": "la tua password",
"yourPassword": "",
"Back": "Indietro",
"serviceUnavailable": "Servizio non disponibile",
"gracefulShutdown": "Il nostro servizio è al momento spento per manutenzione. Si prega di riprovare più tardi.",
"Yes": "Sì",
"reservationError": "Errore di sistema in prenotazione",
"reservationErrorMsg": "Codice di errore: __code__, messaggio: __msg__",
"password": "password",
"password": "",
"userPassword": "password utente",
"token": "token",
"tokenAuthFailedTitle": "",
"tokenAuthFailed": "",
"displayNameRequired": "",
"enterDisplayName": "Per favore, inserisci il tuo nome utente:",
"extensionRequired": "",
"firefoxExtensionPrompt": "",
"rateExperience": "",
"feedbackHelp": "",
"feedbackQuestion": "",
"thankYou": "",
"sorryFeedback": "",
@@ -246,6 +291,7 @@
"stopLiveStreaming": "",
"stopRecording": "",
"doNotShowWarningAgain": "",
"doNotShowMessageAgain": "",
"permissionDenied": "",
"screenSharingPermissionDeniedError": "",
"micErrorPresent": "",
@@ -258,8 +304,17 @@
"micUnknownError": "",
"micPermissionDeniedError": "",
"micNotFoundError": "",
"micConstraintFailedError": ""
"micConstraintFailedError": "",
"micNotSendingData": "",
"cameraNotSendingData": "",
"goToStore": "",
"externalInstallationTitle": "",
"externalInstallationMsg": "",
"muteParticipantTitle": "",
"muteParticipantBody": "",
"muteParticipantButton": "Disattiva audio"
},
"\u0005dialog": {},
"email": {
"sharedKey": "",
"subject": "Invito su __appName__ (__conferenceName__)",

View File

@@ -1,9 +1,13 @@
{
"contactlist": "Al telefòn",
"contactlist": "Participants (__pcount__)",
"addParticipants": "Partejatz lo ligam",
"roomLocked": "Los qu'apèlan devon picar un senhal",
"roomUnlocked": "Qual que siá amb lo ligam pòt participar",
"passwordSetRemotely": "causit per qualqu'un mai",
"connectionsettings": "Paramètres de connexion",
"poweredby": "Produit per",
"feedback": "Donatz-nos vòstre vejaire",
"roomUrlDefaultMsg": "Vòstra conferéncia es en cors de creacion...",
"inviteUrlDefaultMsg": "Vòstra conferéncia es en cors de creacion...",
"me": "ieu",
"speaker": "Nautparlaire",
"raisedHand": "Volriatz charrar",
@@ -22,16 +26,17 @@
},
"keyboardShortcuts": {
"keyboardShortcuts": "Acorchis de clavièr",
"raiseHand": "Demandar a parlar.",
"raiseHand": "Demandar o pas la paraula",
"pushToTalk": "Butar per parlar",
"toggleScreensharing": "Caplevar entre camerà e partatge d'ecran",
"toggleFilmstrip": "Mostrar o escondre la vidèo",
"toggleShortcuts": "Afichar o amagar aiceste menú d'ajuda",
"focusLocal": "Focus sus la vidèo locala.",
"focusRemote": "Focus sus una de las vidèas aluènhadas.",
"toggleChat": "Dubrir o tampar lo panèl de conversacion.",
"mute": "Activar o desactivar lo microfòn.",
"videoMute": "Arrestar o lançar la vidèo locala."
"focusLocal": "Centrar sus vòstra vidèo",
"focusRemote": "Centrar sus la vidèo de qualqu'un mai",
"toggleChat": "Dubrir o tampar lo panèl de conversacion",
"mute": "Activar o desactivar lo microfòn",
"fullScreen": "Activar / Desactivar l'ecran complet",
"videoMute": "Aviar o arrestar vòstra camerà"
},
"welcomepage": {
"go": "Crear",
@@ -70,35 +75,45 @@
"content": "Aprenètz mai a prepaus de vòstres utilizaires amb una integracion aisida de Piwik, Google Analytics e d'autres sistèmas d'estatisticas e supervision d'utilizacion."
}
},
"startupoverlay": {
"policyText": "&nbsp;",
"title": "__app__ a besonh d'utilizar vòstre microfòn e camerà."
},
"suspendedoverlay": {
"title": "Vòstra conferéncia vidèo es estada arrestada perque vòstre ordinador se botèt en velha.",
"rejoinKeyTitle": "Tornar participar"
},
"toolbar": {
"mute": "Mut / Actiu",
"videomute": "Aviar / Arrestar la camèra",
"videomute": "Aviar / Arrestar la camerà",
"authenticate": "Autentificatz-vos",
"lock": "Verrolhar / desverrolhar la sala",
"invite": "Convidar de participants",
"chat": "Dobrir / tampar lo chat",
"etherpad": "Document partejat",
"invite": "Partejatz lo ligam",
"chat": "Dobrir / tampar la conversacion",
"etherpad": "Dobrir / Tampar los documents partejats",
"sharedvideo": "Partejar una vidèo Youtube",
"sharescreen": "Partejar mon ecran",
"fullscreen": "Activar / Désactivar l'ecran complet",
"sharescreen": "Aviar / Arrestar lo partatge d'ecran",
"fullscreen": "Activar / Desactivar l'ecran complet",
"sip": "Sonar un numèro SIP",
"Settings": "Paramètres",
"hangup": "Tornar penjar",
"hangup": "Quitar",
"login": "Connexion",
"logout": "Desconnexion",
"dialpad": "Afichar lo clavièr de numerotacion",
"dialpad": "Dubrir / Tampar lo clavièr",
"sharedVideoMutedPopup": "Vòstra vidèo es estada mesa en mut<br/>per que poscatz parlar als autres participants.",
"micMutedPopup": "Vòstre microfòn es estat desactivat per fin que <br/>poscatz profeitar plenament de vòstra vidèo partejada.",
"talkWhileMutedPopup": "Ensajatz de parlar ? Vòstre microfòn es copat.",
"unableToUnmutePopup": "Podètz pas reactivar vòstre microfòn pendent que la vidèo partejada es activada.",
"cameraDisabled": "La camerà es pas disponibla",
"micDisabled": "Lo microfòn es pas disponible",
"filmstrip": "",
"raiseHand": "Demandar la paraula"
"filmstrip": "Mostrar / escondre vidèos",
"profile": "Modificar vòstre perfil",
"raiseHand": "Demandar / Demandar pas mai la paraula"
},
"bottomtoolbar": {
"chat": "Dobrir / tampar lo chat",
"filmstrip": "Mostrar / escondre vidèos",
"contactlist": "Dobrir / tampar ma lista de contactes"
"contactlist": "Veire e convidar de participants"
},
"chat": {
"nickname": {
@@ -126,9 +141,10 @@
"setPasswordLabel": "Verrolhar vòstra sala amb un senhal"
},
"profile": {
"title": "PERFIL",
"title": "Perfil",
"setDisplayNameLabel": "Causissètz vòstra nom",
"setEmailLabel": "Definir vòstre corrièl per gravatar"
"setEmailLabel": "Definir vòstre corrièl per gravatar",
"setEmailInput": "Picatz lo corrièl"
},
"videothumbnail": {
"editnickname": "Clicatz per modificar<br/>vòstre nom",
@@ -141,6 +157,7 @@
"flip": "Revirar"
},
"connectionindicator": {
"header": "Donadas de connexion",
"bitrate": "Debit :",
"packetloss": "Pèrda de paquets :",
"resolution": "Resolucion :",
@@ -174,20 +191,30 @@
"raisedHand": "Volriá parlar."
},
"dialog": {
"add": "Apondre",
"kickMessage": "Ops! Sètz estat bandit de la reünion !",
"popupError": "Vòstre navigador blòca las fenèstras popup d'aqueste site. Mercé d'activar las popups dins los paramètres de seguretat de vòstre navigador e d'ensajar tornamai.",
"passwordErrorTitle": "Error de senhal",
"passwordError": "Aquesta conversacion es actualament protegida per un senhal. Sol lo proprietari de la conferéncia pòt definir un senhal.",
"passwordError2": "Actualament, aquesta conversacion es pas protegida per un senhal. Sol lo proprietari de la conferéncia pòt definir un senhal.",
"connectError": "Ops! Quicòm a trucat e la connexion a la conferéncia es impossibla.",
"connectErrorWithMsg": "Ops! Quicòm a trucat e la connexion a la conferéncia es impossibla: __msg__",
"incorrectPassword": "Lo senhal es incorrècte",
"connecting": "Connexion en cors",
"copy": "Copiar",
"error": "Error",
"roomLocked": "Aquesta conversacion es verrolhada. Lo nòu-venguts devon aver lo ligam e lo senhal per participar.",
"addPassword": "Apondre un senhal",
"createPassword": "Crear un senhal",
"detectext": "Una error s'es produita pendent la deteccion de l'extension de partiment d'ecran.",
"failtoinstall": "Fracàs de l'installacion de l'extension de partiment d'ecran",
"failedpermissions": "Fracàs d'obtencion de las permissions per utilizar lo micro e/o la camèra.",
"bridgeUnavailable": "Lo pont de visioconferéncia Jitsi es indisponible pel moment. Ensajatz tornamai pus tard !",
"jicofoUnavailable": "Lo pont de visioconferéncia Jitsi es indisponible pel moment. Ensajatz tornamai pus tard !",
"conferenceReloadTitle": "Malurosament, quicòm truquèt",
"conferenceReloadMsg": "Sèm a trobar una solucion per aquò",
"conferenceDisconnectTitle": "Sètz estat desconnectat. Vos cal benlèu verificar vòstra connexion.",
"conferenceDisconnectMsg": "Se tòrna connectar dins...",
"reconnectNow": "Es a se tornar connectar ara",
"conferenceReloadTimeLeft": "__seconds__ segondas.",
"maxUsersLimitReached": "Lo limit pel nombre maximum de participants a la conferéncia es estat atent. La conferéncia es plena. Ensajatz tornamai pus tard !",
"lockTitle": "Fracàs del verrolhatge",
"lockMessage": "Impossible de verrolhar la conferéncia.",
@@ -199,10 +226,14 @@
"SLDFailure": "Ops! Quicòm a trucat e lo micro es pas estat copat! (Fracàs SLD)",
"SRDFailure": "Ops! Quicòm a trucat e la camèra es pas estada copada! (Fracàs SRD)",
"oops": "Ops !",
"currentPassword": "L'actual senhal es",
"passwordLabel": "Senhal",
"defaultError": "Una error s'es produita",
"passwordRequired": "Senhal requesit",
"Ok": "D'acòrdi",
"done": "Acabat",
"Remove": "Suprimir",
"removePassword": "Levar lo senhal",
"shareVideoTitle": "Partejar una vidèo",
"shareVideoLinkError": "Se vos plai, provesissètz un ligam Youtube foncional.",
"removeSharedVideoTitle": "Suprimir la vidèo partejada",
@@ -212,6 +243,7 @@
"WaitForHostMsg": "La conferéncia <b> __ room__ </b> es pas encara començat. Se sètz l'òste, mercé de vos autentificar. Siquenon, mercé d'esperar que l'òste arribe.",
"IamHost": "Soi lòste",
"Cancel": "Anullar",
"Submit": "Validar",
"retry": "Ensajar tornamai",
"logoutTitle": "Desconnexion",
"logoutQuestion": "Sètz segur que vos volètz desconnectar e arrestar la conferéncia ?",
@@ -226,7 +258,7 @@
"sipMsg": "Sasissètz un numèro SIP",
"passwordCheck": "Sètz segur que volètz suprimir vòstre senhal ?",
"passwordMsg": "Sasissètz un senhal per verrolhar la conferéncia",
"shareLink": "Copiatz e partejatz aqueste ligam",
"shareLink": "Partejatz lo ligam de la conversacion",
"settings1": "Configuratz vòstra conferéncia",
"settings2": "Los participants rejonhon la conferéncia en essent muts",
"settings3": "Escaisses requesits<br/><br/>Sasissètz un senhal per verrolhar la conferéncia :",
@@ -242,7 +274,8 @@
"token": "geton",
"tokenAuthFailedTitle": "Fracàs de l'autentificacion",
"tokenAuthFailed": "O planhèm, sètz pas autorizat a rejónher l'apèl.",
"displayNameRequired": "Sasissètz vòstre nom",
"displayNameRequired": "Un nom d'afichatge es necessari",
"enterDisplayName": "Sasissètz vòstre nom",
"extensionRequired": "Extension requesida :",
"firefoxExtensionPrompt": "Vos cal installar una extension Firefox per utilizar lo partiment d'ecran. Mercé ensajar tornamai aprèp l'installacion <a href='__url__'>dempuèi aqueste ligam</a> !",
"rateExperience": "Mercés de donar una nota à vòstra experiéncia.",
@@ -258,6 +291,7 @@
"stopLiveStreaming": "Arrestar lo dirècte",
"stopRecording": "Arrestar l'enregistrament",
"doNotShowWarningAgain": "Afichar pas mai aqueste avertiment",
"doNotShowMessageAgain": "Afichar pas mai aqueste messatge",
"permissionDenied": "Permission Refusada",
"screenSharingPermissionDeniedError": "Vos cal autorizar lo partatge de vòstre ecran.",
"micErrorPresent": "I a agut una error pendent la connexion al microfòn.",
@@ -273,9 +307,12 @@
"micConstraintFailedError": "Vòstre microfòn satisfà pas totas las constrentas necessàrias.",
"micNotSendingData": "Podèm pas aver l'accès a vòstre microfòn. Mercés de ne causir un autre dins lo menú de paramètres o ensajatz de tornar dubrir l'aplicacion.",
"cameraNotSendingData": "Podèm pas aver l'accès a vòstra camèra. Mercés de verificar se una autra aplicacion es pas a l'utilizar, causissètz una autra camèra dins lo menú de paramètres o ensajatz de tornar dubrir l'aplicacion.",
"goToStore": "Anatz sul webstore",
"goToStore": "Anar sul webstore",
"externalInstallationTitle": "Extension requesida :",
"externalInstallationMsg": "Avètz d'installar nòstra extension de partiment d'ecran."
"externalInstallationMsg": "Avètz d'installar nòstra extension de partiment d'ecran.",
"muteParticipantTitle": "Copar lo micro als participants ?",
"muteParticipantBody": "Poiretz pas lo tornar activar lo microfòn, mai eles pòdon o far quand vòlon.",
"muteParticipantButton": "Copar lo son"
},
"email": {
"sharedKey": [

View File

@@ -1,9 +1,13 @@
{
"contactlist": "w trakcie rozmowy",
"contactlist": "",
"addParticipants": "",
"roomLocked": "",
"roomUnlocked": "",
"passwordSetRemotely": "",
"connectionsettings": "ustawienia połączenia",
"poweredby": "Uruchomiono",
"feedback": "jaka jest twoja opinia ?",
"roomUrlDefaultMsg": "otwarto twoją konferencję",
"inviteUrlDefaultMsg": "otwarto twoją konferencję",
"me": "to ja",
"speaker": "głośnik",
"raisedHand": "Chcesz się odezwać ?",
@@ -11,27 +15,28 @@
"defaultLink": "np. _url_",
"callingName": "_nazwa_",
"userMedia": {
"react-nativeGrantPermissions": "",
"chromeGrantPermissions": "",
"androidGrantPermissions": "",
"react-nativeGrantPermissions": "wyraź zgodę na użycie kamery i mikrofonu naciskając <b><i>Allow</i></b> przycisk",
"chromeGrantPermissions": "wyraź zgodę na użycie kamery i mikrofonu naciskając <b><i>Allow</i></b> przycisk",
"androidGrantPermissions": "wyraź zgodę na użycie kamery i mikrofonu naciskając <b><i>Allow</i></b> przycisk",
"firefoxGrantPermissions": "wyraź zgodę na użycie kamery i mikrofonu naciskając <b><i>Share Selected Device</i></b> przycisk",
"operaGrantPermissions": "wyraź zgodę na użycie kamery i mikrofonu naciskając <b><i>Allow</i></b> przycisk",
"iexplorerGrantPermissions": "",
"iexplorerGrantPermissions": "wyraź zgodę na użycie kamery i mikrofonu naciskając <b><i>OK</i></b> przycisk",
"safariGrantPermissions": "wyraź zgodę na użycie kamery i mikrofonu naciskając <b><i>OK</i></b> przycisk",
"nwjsGrantPermissions": "wyraź zgodę na użycie kamery i mikrofonu"
},
"keyboardShortcuts": {
"keyboardShortcuts": "Skróty klawiaturowe:",
"raiseHand": "Unieś rękę.",
"pushToTalk": "naciśnij i mów",
"toggleScreensharing": "Przełączanie pomiędzy kamerą i wspóldzieleniem ekranu",
"toggleFilmstrip": "Pokaż lub ukryj klipy wideo",
"toggleShortcuts": "Pokaż lub ukryj pasek pomocy.",
"focusLocal": "Przełącz na lokalne wideo.",
"focusRemote": "Przełącz na któreś ze zdalnych wideo.",
"toggleChat": "Otwórz lub zamknij panel czat.",
"mute": "Wyłącz lub włącz mikrofon.",
"videoMute": "Start lub stop lokalne wideo."
"keyboardShortcuts": "",
"raiseHand": "",
"pushToTalk": "",
"toggleScreensharing": "",
"toggleFilmstrip": "",
"toggleShortcuts": "",
"focusLocal": "",
"focusRemote": "",
"toggleChat": "",
"mute": "",
"fullScreen": "",
"videoMute": ""
},
"welcomepage": {
"go": "IDŹ",
@@ -70,35 +75,45 @@
"content": "Analizuj uczestników konferencji z łatwościa integrując dane z Piwik i Google Analitics i innymi systemami monitorującymi."
}
},
"startupoverlay": {
"policyText": "",
"title": ""
},
"suspendedoverlay": {
"title": "",
"rejoinKeyTitle": ""
},
"toolbar": {
"mute": "Wycisz / Pogłośnij",
"videomute": "Kamera start / stop ",
"videomute": "",
"authenticate": "Uwierzytelnianie",
"lock": "Zamknij / Otwórz salę",
"invite": "Zaproś innych",
"lock": "",
"invite": "",
"chat": "",
"etherpad": "Udostępniaj dokument",
"etherpad": "",
"sharedvideo": "Udostępniaj wideo w Youtube",
"sharescreen": "Udostępnij ekran",
"fullscreen": "Otwórz / Zamknij pełny ekran",
"sharescreen": "",
"fullscreen": "",
"sip": "Wykręć numer SIP",
"Settings": "",
"hangup": "Rozłącz",
"Settings": "Ustawienia",
"hangup": "",
"login": "Zaloguj",
"logout": "",
"dialpad": "Wyświetl panel wybierania",
"logout": "Wyloguj",
"dialpad": "",
"sharedVideoMutedPopup": "Współdzielone wideo zostało wyciszone i <br/> możesz zacząć rozmawiać z innymi.",
"micMutedPopup": "Mikrofon został wyłączony i <br/> możesz spokojnie konsumować współdzielone wideo",
"talkWhileMutedPopup": "",
"unableToUnmutePopup": "Nie możesz pogłośnić audio podczas współużytkowania wideo",
"cameraDisabled": "Kamera nie jest dostępna",
"micDisabled": "Mikrofon nie jest dostępny",
"filmstrip": "",
"raiseHand": "Podnieś rękę chcąc zabrać głos"
"profile": "",
"raiseHand": ""
},
"bottomtoolbar": {
"chat": "Otwórz / Zamknij Czat",
"filmstrip": "Pokaż / Ukryj klipy wideo",
"contactlist": "Otwórz / Zamknij spis kontaktów"
"contactlist": ""
},
"chat": {
"nickname": {
@@ -126,21 +141,23 @@
"setPasswordLabel": "Zamknij salę konferencyjną z hasłem"
},
"profile": {
"title": "PROFIL",
"title": "",
"setDisplayNameLabel": "Podaj swoją wyświetlaną nazwę",
"setEmailLabel": "Ustaw email swojego gravatara"
"setEmailLabel": "Ustaw email swojego gravatara",
"setEmailInput": ""
},
"videothumbnail": {
"editnickname": "Kliknij <br/>celem edycji swojej nazwy",
"moderator": "Gospodarz <br/>tej konferencji",
"videomute": "Uczestnik <br/>wyłączyl kamerę",
"mute": "Uczestnik ma wyciszone audio",
"kick": "Kick out",
"kick": "Spadaj!",
"muted": "Wyciszony",
"domute": "Wyciszenie",
"flip": "Odwrócenie"
},
"connectionindicator": {
"header": "",
"bitrate": "Szybkość transmisji:",
"packetloss": "Strata pakietów:",
"resolution": "Rozdzielczość:",
@@ -178,20 +195,30 @@
"raisedHand": "Możesz mówić."
},
"dialog": {
"add": "",
"kickMessage": "Ocho! Zostałeś wyproszony z konferencji!",
"popupError": "Twoja przeglądarka blokuje wyskakujące okienka z tej witryny. Proszę, zmień w ustawieniach przeglądarki.",
"passwordErrorTitle": "",
"passwordError": "Ta konwersacja aktualnie jest zabezpieczona hasłem. Tylko gospodarz konferencji może zakładać hasło.",
"passwordError2": "Ta rozmowa nie jest zabezpieczona hasłem. Tylko gospodarz konferencji może ustanowić hasło zabezpieczające.",
"connectError": "Ocho! Cos poszło nie tak, nie można podłaczyć się do tej konferencji.",
"connectErrorWithMsg": "Ocho! Coś poszło nie tak i nie można podłączyć się do tej konferencji:_msg_",
"connecting": "",
"incorrectPassword": "",
"connecting": "Nawiązywanie połączenia",
"copy": "Kopiuj",
"error": "",
"error": "Błąd",
"roomLocked": "",
"addPassword": "",
"createPassword": "",
"detectext": "Błąd podczas rozpoznania rozszerzenia wspóldzielenia ekranu.",
"failtoinstall": "Instalacja współdzielenia ekranu nie powiodła się.",
"failedpermissions": "Brak akceptacji dla użycia kamery i mikrofonu",
"bridgeUnavailable": "Jitsi Videobridge aktualnie jest niedostępne. Proszę, spróbuj później!",
"jicofoUnavailable": "Jicofo jest aktualnie niedostępne. Proszę, spróbuj później!",
"conferenceReloadTitle": "",
"conferenceReloadMsg": "",
"conferenceDisconnectTitle": "",
"conferenceDisconnectMsg": "",
"reconnectNow": "",
"conferenceReloadTimeLeft": "",
"maxUsersLimitReached": "Osiągnięto max liczbę uczestników konferencji. Proszę spróbuj później! ",
"lockTitle": "Nie powiodło się zabezpieczenie konferencji",
"lockMessage": "Zabezpieczenie konferencji nie powiodło się.",
@@ -203,10 +230,14 @@
"SLDFailure": "Ocho! Coś poszło nie tak i nie można wyciszyć! (SLD Failure)",
"SRDFailure": "Ocho! Coś poszło nie tak i nie można zatrzymać wideo! (SRD Failure)",
"oops": "Ups",
"currentPassword": "",
"passwordLabel": "",
"defaultError": "Wystąpił jakiś błąd",
"passwordRequired": "Wymagane hasło",
"Ok": "Ok",
"done": "",
"Remove": "Usuń",
"removePassword": "",
"shareVideoTitle": "Współdziel wideo",
"shareVideoLinkError": "Podaj proszę prawidłowy link youtube.",
"removeSharedVideoTitle": "Usuń wideo współdzielone",
@@ -216,6 +247,7 @@
"WaitForHostMsg": "Konferencja <b>_room_</b> jeszcze nie wystartowała. Jeśli jesteś gospodarzem podaj dane autentykacji. Jeśli nie czekaj na gospodarza.",
"IamHost": "Jestem gospodarzem",
"Cancel": "Anuluj",
"Submit": "",
"retry": "Ponów",
"logoutTitle": "Wyloguj",
"logoutQuestion": "Na pewno chcesz się wylogować i zakończyć konferencję?",
@@ -224,13 +256,13 @@
"joinAgain": "Ponownie przystąp",
"Share": "Współdziel",
"Save": "Zapisz",
"recording": "",
"recording": "Nagrywanie",
"recordingToken": "Proszę podać token nagrywania",
"Dial": "Dzwoń",
"sipMsg": "Podaj numer SIP",
"passwordCheck": "Czy na pewno chcesz usunąć swoje hasło ?",
"passwordMsg": "Podaj hasło aby zabezpieczyć salę konferencyjną",
"shareLink": "Skopiuj i udostępnij ten link",
"shareLink": "",
"settings1": "Skonfiguruj swoją konferencję",
"settings2": "Wyciszenie współuczestników",
"settings3": "Wymagane nicki <br/><br/>Wprowadź hasło dla zabezpieczenia sali konferencyjnej:",
@@ -246,7 +278,8 @@
"token": "token",
"tokenAuthFailedTitle": "Problem uwierzytelnienia",
"tokenAuthFailed": "Przepraszam, ale nie jesteś upoważniony do uczestnictwa w tym połączeniu",
"displayNameRequired": "Wprowadź swoją nazwę użytkownika",
"displayNameRequired": "",
"enterDisplayName": "Wprowadź swoją nazwę użytkownika",
"extensionRequired": "Wymagane jest rozszerzenie:",
"firefoxExtensionPrompt": "Potrzebujesz zainstalować rozszerzenie firefox aby móc współdzielić ekran. Spróbuj ponownie później <a href='__url__'>weź z</a>!",
"rateExperience": "Oceń proszę swoje doświadczenia z konferencji.",
@@ -254,7 +287,7 @@
"feedbackQuestion": "Powiedz nam o twoim połączeniu!",
"thankYou": "Dziękujemy Ci za używanie _appName_!",
"sorryFeedback": "Przykro nam to słyszeć. Czy możesz powiedzieć więcej na ten temat?",
"liveStreaming": "",
"liveStreaming": "Strumień live",
"streamKey": "Nazwa strumienia/klucz",
"startLiveStreaming": "Uruchom strumień live",
"stopStreamingWarning": "Czy jesteś pewny, że chcesz zatrzymać ten strumień live?",
@@ -262,6 +295,7 @@
"stopLiveStreaming": "Zatrzymaj transmisję live",
"stopRecording": "Zatrzymaj nagrywanie",
"doNotShowWarningAgain": "Nie pokazuj tego ostrzeżenia ponownie",
"doNotShowMessageAgain": "",
"permissionDenied": "Brak uprawnień",
"screenSharingPermissionDeniedError": "Nie posiadasz uprawnień do współdzielenia ekranu.",
"micErrorPresent": "Wystąpił błąd w dostępie do mikrofonu.",
@@ -279,7 +313,10 @@
"cameraNotSendingData": "Nie możemy mieć dostępu do twojej kamery. Sprawdź czy inna aplikacja nie używa twojej kamery, wybierz inne urządzenie lub ponownie uruchom aplikację.",
"goToStore": "Idź do sklepu",
"externalInstallationTitle": "Wymagane rozszerzenie",
"externalInstallationMsg": "Zainstaluj rozszerzenie naszego współdzielenia ekranu."
"externalInstallationMsg": "Zainstaluj rozszerzenie naszego współdzielenia ekranu.",
"muteParticipantTitle": "",
"muteParticipantBody": "",
"muteParticipantButton": "Wyciszenie"
},
"email": {
"sharedKey": [
@@ -326,7 +363,7 @@
"on": "Nagrywanie",
"off": "Nagrywanie zatrzymane",
"failedToStart": "Nagrywanie nie jest możliwe",
"buttonTooltip": "Nagrywanie start / stop",
"buttonTooltip": "",
"error": "Nagranie się nie powiodło. Proszę, spróbuj ponownie.",
"unavailable": "Serwis nagrywania jest aktualnie niedostępny. Proszę, spróbować później."
},
@@ -336,7 +373,7 @@
"off": "Strumieniowanie live zastopowane",
"unavailable": "Strumieniowanie live aktualnie jest niedostepne. Proszę spróbować później.",
"failedToStart": "Strumieniowanie live nie powiodło się",
"buttonTooltip": "Strumieniowanie live start / stop",
"buttonTooltip": "",
"streamIdRequired": "Proszę podaj id strumieniowania aby uruchomić live.",
"error": "Strumieniowanie live nie powiodło się. Spróbuj później.",
"busy": "Wszystkie nagrywarki są zajęte. Proszę, sprawdź ponownie później."

View File

@@ -1,6 +1,6 @@
{
"contactlist": "Participantes (__pcount__)",
"addParticipants": "",
"addParticipants": "Compartilhar o link",
"roomLocked": "Visitantes precisam digitar uma senha",
"roomUnlocked": "Qualquer um com o link pode entrar",
"passwordSetRemotely": "Definido por outro participante",

View File

@@ -1,17 +1,19 @@
{
"contactlist": "ZOZNAM KONTAKTOV",
"contactlist": "",
"addParticipants": "",
"roomLocked": "",
"roomUnlocked": "",
"passwordSetRemotely": "",
"connectionsettings": "Nastavenie spojenia",
"poweredby": "založené na",
"downloadlogs": "Stiahnúť logy",
"feedback": "",
"roomUrlDefaultMsg": "Vaša konferencia bola práve vytvorená...",
"participant": "Účastník",
"inviteUrlDefaultMsg": "Vaša konferencia bola práve vytvorená...",
"me": "ja",
"speaker": "Rečník",
"raisedHand": "",
"defaultNickname": "",
"defaultLink": "napr. __url__",
"calling": "",
"callingName": "",
"userMedia": {
"react-nativeGrantPermissions": "",
"chromeGrantPermissions": "",
@@ -33,6 +35,7 @@
"focusRemote": "",
"toggleChat": "",
"mute": "",
"fullScreen": "",
"videoMute": ""
},
"welcomepage": {
@@ -72,33 +75,45 @@
"content": "Zistite o Vašich uživateľoch viac ľahko cez integráciu s Piwik, Google Analytics a inych monitorovacích a štatistických nástrojov."
}
},
"startupoverlay": {
"policyText": "",
"title": ""
},
"suspendedoverlay": {
"title": "",
"rejoinKeyTitle": ""
},
"toolbar": {
"mute": "Vypnúť / Zapnúť mikrofón",
"videomute": "Vypnúť / Zapnúť kameru",
"videomute": "",
"authenticate": "Overiť",
"lock": "Zamknúť / Odomknúť miestnosť",
"invite": "Pozvať ďalšich",
"chat": "Otvoriť / zatvoriť chat",
"etherpad": "Zdieľať dokument",
"lock": "",
"invite": "",
"chat": "",
"etherpad": "",
"sharedvideo": "",
"sharescreen": "Zdieľať prac. plochu",
"fullscreen": "Zapnúť / Vypnúť plnú obrazovku",
"sharescreen": "",
"fullscreen": "",
"sip": "Zavolať SIP číslo",
"Settings": "Nastavenia",
"hangup": "Zložiť",
"hangup": "",
"login": "Prihlásiť",
"logout": "Odhlásiť",
"dialpad": "Zobraziť číselník",
"dialpad": "",
"sharedVideoMutedPopup": "",
"micMutedPopup": "",
"talkWhileMutedPopup": "",
"unableToUnmutePopup": "",
"cameraDisabled": "",
"micDisabled": ""
"micDisabled": "",
"filmstrip": "",
"profile": "",
"raiseHand": ""
},
"bottomtoolbar": {
"chat": "Otvoriť / zatvoriť chat",
"filmstrip": "Zobraziť / skryť účastníkov",
"contactlist": "Otvoriť / zatvoriť zoznam kontaktov"
"filmstrip": "",
"contactlist": ""
},
"chat": {
"nickname": {
@@ -108,7 +123,7 @@
"messagebox": "Napíšte text..."
},
"settings": {
"title": "NASTAVENIA",
"title": "Nastavenia",
"update": "Nastaviť",
"name": "Meno",
"startAudioMuted": "",
@@ -119,12 +134,22 @@
"followMe": "",
"noDevice": "",
"noPermission": "",
"avatarUrl": ""
"cameraAndMic": "",
"moderator": "",
"password": "",
"audioVideo": "",
"setPasswordLabel": ""
},
"profile": {
"title": "",
"setDisplayNameLabel": "",
"setEmailLabel": "",
"setEmailInput": ""
},
"videothumbnail": {
"editnickname": "Kliknite pre zmenu<br/>Vášho mena",
"moderator": "Majiteľ tejto<br/>konferencie",
"videomute": "Učastník s<br/>vypnutou kamerou",
"videomute": "",
"mute": "Učastník s<br/>vypnutým mikrofónom",
"kick": "Vyhodiť",
"muted": "Vypnutý mikrofón",
@@ -132,6 +157,7 @@
"flip": ""
},
"connectionindicator": {
"header": "",
"bitrate": "Prenos. rýchlosť",
"packetloss": "Strata packetov:",
"resolution": "Rozlíšenie:",
@@ -169,34 +195,49 @@
"raisedHand": ""
},
"dialog": {
"add": "",
"kickMessage": "Boli ste vyhodený z konferencie!",
"popupError": "Váš prehliadač blokuje vyskakovacie okná pre túto stránku. Prosím, povoľte si vyskakovacie okná a skúste to znova.",
"passwordErrorTitle": "",
"passwordError": "Táto diskusia je momentálne zabezpečená heslom. Iba majiteľ tejto konferencie može nastaviť heslo.",
"passwordError2": "Táto diskusia nie je momentálne zabezpečená heslom. Iba majiteľ tejto konferencie može nastaviť heslo.",
"connectError": "Oops! Niečo je zle a nemožem sa pripojiť do konferencie.",
"connectErrorWithMsg": "Oops! Niečo je zle a nemožem sa pripojiť do konferencie. Správa: __msg__",
"incorrectPassword": "",
"connecting": "Pripájam",
"copy": "",
"error": "Chyba",
"roomLocked": "",
"addPassword": "",
"createPassword": "",
"detectext": "Chyba pri pokuse najsť rozšírenie pre zdieľanie prac. plochy",
"failtoinstall": "Zlyhanie pri inštalácií rozšírenia pre zdieľanie prac. plochy",
"failedpermissions": "Zlyhanie pri pokuse získať prístup k lokálnemu mikrofonu alebo kamere.",
"bridgeUnavailable": "Jitsi Videobridge je momentálne nedostupné. Prosím, skúste neskor!",
"jicofoUnavailable": "",
"conferenceReloadTitle": "",
"conferenceReloadMsg": "",
"conferenceDisconnectTitle": "",
"conferenceDisconnectMsg": "",
"reconnectNow": "",
"conferenceReloadTimeLeft": "",
"maxUsersLimitReached": "",
"lockTitle": "Zabezpečenie zlyhalo",
"lockMessage": "Zlyhanie pri pokuse o zabezpečenie konferencie.",
"warning": "Upozornenie",
"passwordNotSupported": "Heslá pre miestnosti nie sú momentálne podporované.",
"sorry": "Prepáčte",
"internalError": "Vnútorná aplikačná chyba [setRemoteDescription]",
"internalErrorTitle": "",
"internalError": "",
"unableToSwitch": "Nie je možne prepnúť video stream.",
"SLDFailure": "Oops! Niečo sa stalo a nie je možne vypnúť mikrofón! (Chyba SLD)",
"SRDFailure": "Oops! Niečo sa stalo a nie je možne vypnúť kameru! (Chyba SLD)",
"oops": "Oops!",
"currentPassword": "",
"passwordLabel": "",
"defaultError": "Nastala neznáma chyba",
"passwordRequired": "Je potrebné heslo",
"Ok": "Ok",
"done": "",
"Remove": "Odstrániť",
"removePassword": "",
"shareVideoTitle": "",
"shareVideoLinkError": "",
"removeSharedVideoTitle": "",
@@ -206,6 +247,7 @@
"WaitForHostMsg": "Konferencia <b>__room__ </b> ešte nezačala. Ak ste hostiteľ Vy, overte sa. Inak čakajte kým sa prihlási hostiteľ.",
"IamHost": "Ja som hostiteľ",
"Cancel": "Zrušiť",
"Submit": "",
"retry": "Skúsiť znova",
"logoutTitle": "Odhlásiť",
"logoutQuestion": "Ste si istý, že sa chcete odhlásiť a skončit konferenciu?",
@@ -220,25 +262,28 @@
"sipMsg": "Vložte SIP číslo",
"passwordCheck": "Ste si istý, že chcete odstrániť heslo?",
"passwordMsg": "Zadajte heslo pre zabezpečenie miestnosti",
"Invite": "Pozvať",
"shareLink": "Zdieľajte tento odkaz s každým koho chcete pozvať",
"shareLink": "",
"settings1": "Nastavte Vašu konferenciu",
"settings2": "Učastníkov pripájať stíšených",
"settings3": "Vyžaduj meno<br/><br/>Zadaj heslo pre zabezpečenie miestnosti:",
"yourPassword": "Vaše heslo",
"yourPassword": "",
"Back": "Späť",
"serviceUnavailable": "Služba nedostupná",
"gracefulShutdown": "Naša služba je momentálne vypnutá pre údržbu. Skúste to neskor.",
"Yes": "Áno",
"reservationError": "Systemová chyba rezervácie",
"reservationErrorMsg": "Chyba: __code__, správa: __msg__",
"password": "heslo",
"password": "",
"userPassword": "uživateľské heslo",
"token": "token",
"tokenAuthFailedTitle": "",
"tokenAuthFailed": "",
"displayNameRequired": "",
"enterDisplayName": "",
"extensionRequired": "Potrebné rozšírenie:",
"firefoxExtensionPrompt": "Potrebujete nainštalovať rozšírenie do Firefoxu pre možnosť zdieľať prac. plochu. Prosím, skúste znovu po nainštalovaní z: <a href='__url__'>",
"rateExperience": "",
"feedbackHelp": "",
"feedbackQuestion": "",
"thankYou": "",
"sorryFeedback": "",
@@ -250,6 +295,7 @@
"stopLiveStreaming": "",
"stopRecording": "",
"doNotShowWarningAgain": "",
"doNotShowMessageAgain": "",
"permissionDenied": "",
"screenSharingPermissionDeniedError": "",
"micErrorPresent": "",
@@ -262,7 +308,15 @@
"micUnknownError": "",
"micPermissionDeniedError": "",
"micNotFoundError": "",
"micConstraintFailedError": ""
"micConstraintFailedError": "",
"micNotSendingData": "",
"cameraNotSendingData": "",
"goToStore": "",
"externalInstallationTitle": "",
"externalInstallationMsg": "",
"muteParticipantTitle": "",
"muteParticipantBody": "",
"muteParticipantButton": "Vypnút mikrofón"
},
"email": {
"sharedKey": [

View File

@@ -1,17 +1,19 @@
{
"contactlist": "STIKI",
"contactlist": "",
"addParticipants": "",
"roomLocked": "",
"roomUnlocked": "",
"passwordSetRemotely": "",
"connectionsettings": "Nastavitve povezave",
"poweredby": "poganja",
"downloadlogs": "Shrani zapis",
"feedback": "",
"roomUrlDefaultMsg": "Ustvarjanje vaše konference ...",
"participant": "Udeleženec",
"inviteUrlDefaultMsg": "Ustvarjanje vaše konference ...",
"me": "jaz",
"speaker": "Govornik",
"raisedHand": "",
"defaultNickname": "",
"defaultLink": "npr. __url__",
"calling": "",
"callingName": "",
"userMedia": {
"react-nativeGrantPermissions": "",
"chromeGrantPermissions": "",
@@ -33,6 +35,7 @@
"focusRemote": "",
"toggleChat": "",
"mute": "",
"fullScreen": "",
"videoMute": ""
},
"welcomepage": {
@@ -72,33 +75,45 @@
"content": "Spoznajte svoje uporabnike z enostavno integracijo v Piwik, Google Analytics ter druge sisteme za nadzor uporabe in statistiko."
}
},
"startupoverlay": {
"policyText": "",
"title": ""
},
"suspendedoverlay": {
"title": "",
"rejoinKeyTitle": ""
},
"toolbar": {
"mute": "Utišaj / Povrni glasnost",
"videomute": "Zaženi / Ustavi kamero",
"videomute": "",
"authenticate": "Overi",
"lock": "Zakleni / Odkleni sobo",
"invite": "Povabite ostale",
"chat": "Odpri / zapri klepetalnico",
"etherpad": "Dokument v skupni rabi",
"lock": "",
"invite": "",
"chat": "",
"etherpad": "",
"sharedvideo": "",
"sharescreen": "Zaslon v souporabi",
"fullscreen": "Vklopi / Izklopi celozaslonski način",
"sharescreen": "",
"fullscreen": "",
"sip": "Pokliči številko SIP",
"Settings": "Nastavitve",
"hangup": "Odloži",
"hangup": "",
"login": "Prijava",
"logout": "Odjava",
"dialpad": "Pokaži številčnico",
"dialpad": "",
"sharedVideoMutedPopup": "",
"micMutedPopup": "",
"talkWhileMutedPopup": "",
"unableToUnmutePopup": "",
"cameraDisabled": "",
"micDisabled": ""
"micDisabled": "",
"filmstrip": "",
"profile": "",
"raiseHand": ""
},
"bottomtoolbar": {
"chat": "Odpri / zapri klepetalnico",
"filmstrip": "Pokaži / Skrij filmski trak",
"contactlist": "Odpri / Zapri stike"
"filmstrip": "",
"contactlist": ""
},
"chat": {
"nickname": {
@@ -108,7 +123,7 @@
"messagebox": "Vnesite besedilo ..."
},
"settings": {
"title": "NASTAVITVE",
"title": "Nastavitve",
"update": "Posodobi",
"name": "Ime",
"startAudioMuted": "",
@@ -119,12 +134,22 @@
"followMe": "",
"noDevice": "",
"noPermission": "",
"avatarUrl": ""
"cameraAndMic": "",
"moderator": "",
"password": "",
"audioVideo": "",
"setPasswordLabel": ""
},
"profile": {
"title": "",
"setDisplayNameLabel": "",
"setEmailLabel": "",
"setEmailInput": ""
},
"videothumbnail": {
"editnickname": "Kliknite, da spremenite<br/>svoje ime",
"moderator": "Lastnik<br/>konference",
"videomute": "Udeleženec je<br/>izključil kamero.",
"videomute": "",
"mute": "Udeleženec je utišan",
"kick": "Izženi",
"muted": "Utišan",
@@ -132,6 +157,7 @@
"flip": ""
},
"connectionindicator": {
"header": "",
"bitrate": "Bitna hitrost:",
"packetloss": "Izgubljeni paketi:",
"resolution": "Ločljivost:",
@@ -173,34 +199,49 @@
"raisedHand": ""
},
"dialog": {
"add": "",
"kickMessage": "Ojej! Izgnali so vas iz srečanja!",
"popupError": "",
"passwordErrorTitle": "",
"passwordError": "",
"passwordError2": "",
"connectError": "Ups! Nekaj je narobe in se ni bilo mogoče povezati s konferenco.",
"connectErrorWithMsg": "Ups! Nekaj je narobe in se ni bilo mogoče povezati s konferenco: __msg__",
"incorrectPassword": "",
"connecting": "Povezovanje",
"copy": "",
"error": "Napaka",
"roomLocked": "",
"addPassword": "",
"createPassword": "",
"detectext": "Napaka pri zaznavanju razširitve za skupno uporabo namizja.",
"failtoinstall": "Razširitve za skupno uporabo namizja ni bilo mogoče namestiti",
"failedpermissions": "Ni bilo mogoče pridobiti dovoljenja za uporabo lokalnega mikrofona ali kamere.",
"bridgeUnavailable": "Jitsi Videobridge trenutno ni na razpolago. Prosim poskusite kasneje!",
"jicofoUnavailable": "",
"conferenceReloadTitle": "",
"conferenceReloadMsg": "",
"conferenceDisconnectTitle": "",
"conferenceDisconnectMsg": "",
"reconnectNow": "",
"conferenceReloadTimeLeft": "",
"maxUsersLimitReached": "",
"lockTitle": "Zaklepanje ni uspelo",
"lockMessage": "",
"warning": "Opozorilo",
"passwordNotSupported": "Trenutno ni mogoče zakleniti sobe z geslom.",
"sorry": "Oprostite",
"internalError": "Notranja napaka [setRemoteDescription]",
"internalErrorTitle": "",
"internalError": "",
"unableToSwitch": "Ni mogoče preklopiti video pretoka.",
"SLDFailure": "Ups! Nekaj je narobe in zvoka se ne da utišati! (Napaka SLD)",
"SRDFailure": "Ups! Nekaj je narobe in slike ni mogoče ustaviti! (Napaka SRD)",
"oops": "Ups!",
"currentPassword": "",
"passwordLabel": "",
"defaultError": "Prišlo je do neke napake",
"passwordRequired": "Potrebno je geslo",
"Ok": "V redu",
"done": "",
"Remove": "Odstrani",
"removePassword": "",
"shareVideoTitle": "",
"shareVideoLinkError": "",
"removeSharedVideoTitle": "",
@@ -210,6 +251,7 @@
"WaitForHostMsg": "Ta konferenca <b>__room__ </b> se še ni začela. V primeru, da ste vi gostitelj se prosim overite. Drugače počakajte prosim na prihod gostitelja.",
"IamHost": "Jaz sem gostitelj",
"Cancel": "Prekliči",
"Submit": "",
"retry": "Poskusi ponovno",
"logoutTitle": "Odjava",
"logoutQuestion": "Ali se res želite odjaviti in prekiniti konferenco?",
@@ -224,25 +266,28 @@
"sipMsg": "Vnesite številko SIP",
"passwordCheck": "Ali res želite odstraniti geslo?",
"passwordMsg": "Nastavite geslo za zaklepanje sobe",
"Invite": "Povabi",
"shareLink": "To povezavo pošljite vsem, ki jih želite povabiti",
"shareLink": "",
"settings1": "Nastavite svojo konferenco",
"settings2": "Utišaj udeležence ob pristopu",
"settings3": "Zahtevaj vzdevke<br/><br/>Nastavi geslo za zaklep sobe:",
"yourPassword": "vaše geslo",
"yourPassword": "",
"Back": "Nazaj",
"serviceUnavailable": "Storitev ni na voljo",
"gracefulShutdown": "Storitev trenutno ni na voljo zaradi vzdrževanja. Poskusite ponovno kasneje.",
"Yes": "Da",
"reservationError": "Napaka v sistemu rezervacije",
"reservationErrorMsg": "Koda napake: __code__, sporočilo: __msg__",
"password": "geslo",
"password": "",
"userPassword": "uporabniško geslo",
"token": "žeton",
"tokenAuthFailedTitle": "",
"tokenAuthFailed": "",
"displayNameRequired": "",
"enterDisplayName": "",
"extensionRequired": "",
"firefoxExtensionPrompt": "",
"rateExperience": "",
"feedbackHelp": "",
"feedbackQuestion": "",
"thankYou": "",
"sorryFeedback": "",
@@ -254,6 +299,7 @@
"stopLiveStreaming": "",
"stopRecording": "",
"doNotShowWarningAgain": "",
"doNotShowMessageAgain": "",
"permissionDenied": "",
"screenSharingPermissionDeniedError": "",
"micErrorPresent": "",
@@ -266,7 +312,15 @@
"micUnknownError": "",
"micPermissionDeniedError": "",
"micNotFoundError": "",
"micConstraintFailedError": ""
"micConstraintFailedError": "",
"micNotSendingData": "",
"cameraNotSendingData": "",
"goToStore": "",
"externalInstallationTitle": "",
"externalInstallationMsg": "",
"muteParticipantTitle": "",
"muteParticipantBody": "",
"muteParticipantButton": "Utišaj"
},
"email": {
"sharedKey": "",

View File

@@ -1,17 +1,19 @@
{
"contactlist": "KONTAKTLISTA",
"contactlist": "",
"addParticipants": "",
"roomLocked": "",
"roomUnlocked": "",
"passwordSetRemotely": "",
"connectionsettings": "Anslutningsinställningar",
"poweredby": "drivs av",
"downloadlogs": "Hämta loggar",
"feedback": "Ge oss din feedback",
"roomUrlDefaultMsg": "Din konferens håller på att skapas...",
"participant": "Deltagare",
"inviteUrlDefaultMsg": "Din konferens håller på att skapas...",
"me": "jag",
"speaker": "Talare",
"raisedHand": "",
"defaultNickname": "",
"defaultLink": "t ex. __url__",
"calling": "",
"callingName": "",
"userMedia": {
"react-nativeGrantPermissions": "",
"chromeGrantPermissions": "",
@@ -33,6 +35,7 @@
"focusRemote": "",
"toggleChat": "",
"mute": "",
"fullScreen": "",
"videoMute": ""
},
"welcomepage": {
@@ -72,33 +75,45 @@
"content": "Studera användningsmönster genom enkel integration med Piwik, Google Analytics och andra monitorerings- och statistiksystem."
}
},
"startupoverlay": {
"policyText": "",
"title": ""
},
"suspendedoverlay": {
"title": "",
"rejoinKeyTitle": ""
},
"toolbar": {
"mute": "Slå av/på ljud",
"videomute": "Starta / stoppa kamera",
"videomute": "",
"authenticate": "Autentisera",
"lock": "Lås / lås upp rum",
"invite": "Bjud in andra",
"chat": "Öppna / stäng chat",
"etherpad": "Delat dokument",
"lock": "",
"invite": "",
"chat": "",
"etherpad": "",
"sharedvideo": "",
"sharescreen": "Dela skärm",
"fullscreen": "Aktivera / avaktivera helskärm",
"sharescreen": "",
"fullscreen": "",
"sip": "Ring SIP-nummer",
"Settings": "Inställningar",
"hangup": "Lägg på",
"hangup": "",
"login": "Logga in",
"logout": "Logga ut",
"dialpad": "Visa knappsats",
"dialpad": "",
"sharedVideoMutedPopup": "",
"micMutedPopup": "",
"talkWhileMutedPopup": "",
"unableToUnmutePopup": "",
"cameraDisabled": "",
"micDisabled": ""
"micDisabled": "",
"filmstrip": "",
"profile": "",
"raiseHand": ""
},
"bottomtoolbar": {
"chat": "Öppna / stäng chat",
"filmstrip": "Visa / dölj filmremsa",
"contactlist": "Öppna / stäng kontaktlista"
"filmstrip": "",
"contactlist": ""
},
"chat": {
"nickname": {
@@ -108,7 +123,7 @@
"messagebox": "Skriv text..."
},
"settings": {
"title": "INSTÄLLNINGAR",
"title": "Inställningar",
"update": "Uppdatera",
"name": "Namn",
"startAudioMuted": "",
@@ -119,12 +134,22 @@
"followMe": "",
"noDevice": "",
"noPermission": "",
"avatarUrl": ""
"cameraAndMic": "",
"moderator": "",
"password": "",
"audioVideo": "",
"setPasswordLabel": ""
},
"profile": {
"title": "",
"setDisplayNameLabel": "",
"setEmailLabel": "",
"setEmailInput": ""
},
"videothumbnail": {
"editnickname": "Klicka här för att <br/>redigera namn",
"moderator": "Ägaren av den<br/>här konferensen",
"videomute": "Deltagaren har<br/>stoppat kameran.",
"videomute": "",
"mute": "Deltagaren har avstängd mikrofon",
"kick": "Sparka ut",
"muted": "Tystad",
@@ -132,6 +157,7 @@
"flip": ""
},
"connectionindicator": {
"header": "",
"bitrate": "Bithastighet:",
"packetloss": "Paketförluster:",
"resolution": "Upplösning:",
@@ -165,34 +191,49 @@
"raisedHand": ""
},
"dialog": {
"add": "",
"kickMessage": "Aj! Du har sparkats ur mötet!",
"popupError": "Din webbläsare blockerar popup-fönster från den här webbplatsen. Vänligen aktivera popups i din webbläsares säkerhetsinställningar och försök igen.",
"passwordErrorTitle": "",
"passwordError": "Den här konversationen är för närvarande skyddad av lösenord. Bara ägaren till konferensen kan sätta ett lösenord.",
"passwordError2": "Den här konversationen är för närvarande inte skyddad av ett lösenord. Bara ägaren till konferensen kan sätta ett lösenord.",
"connectError": "Ojdå! Något gick fel och vi kunde inte ansluta till konferensen.",
"connectErrorWithMsg": "Ojdå! Något gick fel och vi kunde inte ansluta till konferensen: __msg__",
"incorrectPassword": "",
"connecting": "Ansluter",
"copy": "",
"error": "Fel",
"roomLocked": "",
"addPassword": "",
"createPassword": "",
"detectext": "Fel när skrivbordsdelnings-tillägget försökte hittas.",
"failtoinstall": "Misslyckades att installera skrivbordsdelnings-tillägget",
"failedpermissions": "Misslyckades med att få tillåtelse att använda lokal mikrofon och/eller kamera.",
"bridgeUnavailable": "Jitsi Videobridge är för tillfället inte tillgänglig. Vänligen försök senare!",
"jicofoUnavailable": "",
"conferenceReloadTitle": "",
"conferenceReloadMsg": "",
"conferenceDisconnectTitle": "",
"conferenceDisconnectMsg": "",
"reconnectNow": "",
"conferenceReloadTimeLeft": "",
"maxUsersLimitReached": "",
"lockTitle": "Låsning misslyckades",
"lockMessage": "Misslyckades att låsa konferensen.",
"warning": "Varning",
"passwordNotSupported": "Rumslösenord stöds inte för tillfället.",
"sorry": "Tyvärr",
"internalError": "Internt applikationsfel [setRemoteDescription]",
"internalErrorTitle": "",
"internalError": "",
"unableToSwitch": "Kunde inte byta videoström.",
"SLDFailure": "Ojdå! Något gick fel och vi kunde inte stänga av mikrofonen! (SLD Failure)",
"SRDFailure": "Ojdå! Något gick fel och vi kunde inte stänga av videokameran! (SRD Failure)",
"oops": "Ojdå!",
"currentPassword": "",
"passwordLabel": "",
"defaultError": "Det uppstod någon typ av fel",
"passwordRequired": "Lösenord krävs",
"Ok": "Ok",
"done": "",
"Remove": "Ta bort",
"removePassword": "",
"shareVideoTitle": "",
"shareVideoLinkError": "",
"removeSharedVideoTitle": "",
@@ -202,6 +243,7 @@
"WaitForHostMsg": "Konferensen <b>__room__</b> har inte startat än. Om du är värd för konferensen, vänligen logga in. Annars, vänta kvar på att konferensvärden kommer.",
"IamHost": "Jag är värd",
"Cancel": "Avbryt",
"Submit": "",
"retry": "Försök igen",
"logoutTitle": "Logga ut",
"logoutQuestion": "Är du säker på att du vill logga ut och stoppa konferensen?",
@@ -216,26 +258,29 @@
"sipMsg": "Skriv in SIP-nummer",
"passwordCheck": "Är du säker på att du vill ta bort ditt lösenord?",
"passwordMsg": "Sätt ett lösenord för att låsa ditt rum",
"Invite": "Bjud in",
"shareLink": "Dela den här länken med alla du vill bjuda in",
"shareLink": "",
"settings1": "Anpassa din konferens",
"settings2": "Deltagare går med med mikrofonen avstängd",
"settings3": "Kräver användarnamn<br/><br/>Sätt ett lösenord för att låsa ditt rum:",
"yourPassword": "ditt lösenord",
"yourPassword": "",
"Back": "Tillbaka",
"serviceUnavailable": "Tjänsten otillgänglig",
"gracefulShutdown": "Vår tjänst är för tillfället nedstängd för underhåll. Vänligen försök senare.",
"Yes": "Ja",
"reservationError": "Fel i reservationssystemet",
"reservationErrorMsg": "Felkod: __code__, meddelande: __msg__",
"password": "lösenord",
"password": "",
"userPassword": "användarlösenord",
"token": "token",
"tokenAuthFailed": "Misslyckades att autentisera mot XMPP-server: ogiltig token",
"tokenAuthFailedTitle": "",
"tokenAuthFailed": "",
"displayNameRequired": "",
"enterDisplayName": "",
"extensionRequired": "Tillägg krävs:",
"firefoxExtensionPrompt": "Du behöver installera ett Firefox-tillägg för att kunna använda skärmdelning. Vänligen försök igen efter att du <a href='__url__'>hämtat det här</a>!",
"feedbackQuestion": "Hur upplevde du samtalet?",
"rateExperience": "",
"feedbackHelp": "",
"feedbackQuestion": "",
"thankYou": "Tack för att du använder __appName__!",
"sorryFeedback": "Tråkigt att du känner så. Vill du berätta mer?",
"liveStreaming": "",
@@ -246,6 +291,7 @@
"stopLiveStreaming": "",
"stopRecording": "",
"doNotShowWarningAgain": "",
"doNotShowMessageAgain": "",
"permissionDenied": "",
"screenSharingPermissionDeniedError": "",
"micErrorPresent": "",
@@ -258,7 +304,15 @@
"micUnknownError": "",
"micPermissionDeniedError": "",
"micNotFoundError": "",
"micConstraintFailedError": ""
"micConstraintFailedError": "",
"micNotSendingData": "",
"cameraNotSendingData": "",
"goToStore": "",
"externalInstallationTitle": "",
"externalInstallationMsg": "",
"muteParticipantTitle": "",
"muteParticipantBody": "",
"muteParticipantButton": "Tysta"
},
"\u0005dialog": {},
"email": {

View File

@@ -1,17 +1,19 @@
{
"contactlist": "KİŞİ LİSTESİ",
"contactlist": "",
"addParticipants": "",
"roomLocked": "",
"roomUnlocked": "",
"passwordSetRemotely": "",
"connectionsettings": "Bağlantı Ayarları",
"poweredby": "Gücünün kaynağı",
"downloadlogs": "Günlükleri indir",
"feedback": "",
"roomUrlDefaultMsg": "",
"participant": "",
"inviteUrlDefaultMsg": "",
"me": "",
"speaker": "",
"raisedHand": "",
"defaultNickname": "",
"defaultLink": "",
"calling": "",
"callingName": "",
"userMedia": {
"react-nativeGrantPermissions": "",
"chromeGrantPermissions": "",
@@ -33,6 +35,7 @@
"focusRemote": "",
"toggleChat": "",
"mute": "",
"fullScreen": "",
"videoMute": ""
},
"welcomepage": {
@@ -72,33 +75,45 @@
"content": "Piwik, Google Analytics ve diğer kullanım izleme ve istatistik sistemleri ile kolay tümleştirmeyle kullanıcılar hakkında bilgi edinin."
}
},
"startupoverlay": {
"policyText": "",
"title": ""
},
"suspendedoverlay": {
"title": "",
"rejoinKeyTitle": ""
},
"toolbar": {
"mute": "Sessiz / Sesli",
"videomute": "Kamera başlat / durdur",
"videomute": "",
"authenticate": "Kimlik doğrula",
"lock": "Odayı kilitle / kilit aç",
"invite": "Arkadaşlarını davet et",
"chat": "Sohbeti aç / kapa",
"etherpad": "Paylaşımlı belge",
"lock": "",
"invite": "",
"chat": "",
"etherpad": "",
"sharedvideo": "",
"sharescreen": "Ekran paylaş",
"fullscreen": "Tam Ekrana Gir / Çık",
"sharescreen": "",
"fullscreen": "",
"sip": "SIP numara ara",
"Settings": "Ayarlar",
"hangup": "Kapat",
"hangup": "",
"login": "Oturum aç",
"logout": "Oturum kapat",
"dialpad": "",
"sharedVideoMutedPopup": "",
"micMutedPopup": "",
"talkWhileMutedPopup": "",
"unableToUnmutePopup": "",
"cameraDisabled": "",
"micDisabled": ""
"micDisabled": "",
"filmstrip": "",
"profile": "",
"raiseHand": ""
},
"bottomtoolbar": {
"chat": "Sohbeti aç / kapa",
"filmstrip": "Film şeridini göster / gizle",
"contactlist": "Kişi listesi aç / kapa"
"filmstrip": "",
"contactlist": ""
},
"chat": {
"nickname": {
@@ -108,7 +123,7 @@
"messagebox": "Metin girin..."
},
"settings": {
"title": "AYARLAR",
"title": "Ayarlar",
"update": "Güncelle",
"name": "Ad",
"startAudioMuted": "",
@@ -119,12 +134,22 @@
"followMe": "",
"noDevice": "",
"noPermission": "",
"avatarUrl": ""
"cameraAndMic": "",
"moderator": "",
"password": "",
"audioVideo": "",
"setPasswordLabel": ""
},
"profile": {
"title": "",
"setDisplayNameLabel": "",
"setEmailLabel": "",
"setEmailInput": ""
},
"videothumbnail": {
"editnickname": "Görünür adınızı değiştirmek<br/>için tıkla",
"moderator": "Bu görüşmenin<br/>sahibi",
"videomute": "Katılımcı<br/>kamera durdurdu.",
"videomute": "",
"mute": "Katılımcı sessiz",
"kick": "Kovuldu",
"muted": "Sessiz",
@@ -132,6 +157,7 @@
"flip": ""
},
"connectionindicator": {
"header": "",
"bitrate": "Bit hızı:",
"packetloss": "Paket kaybı:",
"resolution": "Çözünürlük:",
@@ -161,34 +187,49 @@
"raisedHand": ""
},
"dialog": {
"add": "",
"kickMessage": "Ahhh! Görüşmeden, kavuldun!",
"popupError": "",
"passwordErrorTitle": "",
"passwordError": "",
"passwordError2": "",
"connectError": "Amanin boo! Birşeyler ters gitti ve görüşmeye bağlanamadık.",
"connectErrorWithMsg": "Amanin boo! Birşeyler ters gitti ve görüşmeye bağlanamadık.",
"incorrectPassword": "",
"connecting": "",
"copy": "",
"error": "Hata",
"roomLocked": "",
"addPassword": "",
"createPassword": "",
"detectext": "Ekran paylaşımı eklentisi tespit edilirken hata.",
"failtoinstall": "Masaüstü paylaşım eklentisi yüklenemedi",
"failedpermissions": "Yerel mikrofon ve/veya kamerayı kullanmak için izinler alınamadı.",
"bridgeUnavailable": "Jitsi Videobridge şu anda kullanılamıyor. Daha sonra tekrar deneyiniz!",
"jicofoUnavailable": "",
"conferenceReloadTitle": "",
"conferenceReloadMsg": "",
"conferenceDisconnectTitle": "",
"conferenceDisconnectMsg": "",
"reconnectNow": "",
"conferenceReloadTimeLeft": "",
"maxUsersLimitReached": "",
"lockTitle": "Kilitlenemedi",
"lockMessage": "Görüşme kilitlenemedi.",
"warning": "Uyarı",
"passwordNotSupported": "Oda parolaları şu anda desteklenmemekte.",
"sorry": "Üzgünüz",
"internalError": "İç uygulama hatası [setRemoteDescription]",
"internalErrorTitle": "",
"internalError": "",
"unableToSwitch": "Video akışıılamıyor.",
"SLDFailure": "Amanin boo! Birşeyler ters gitti ve sessize alamadık! (SLD Başarısız)",
"SRDFailure": "Amanin boo! Birşeyler ters gitti ve videoyu durduramadık! (SRD Başarısız)",
"oops": "Amanin boo!",
"currentPassword": "",
"passwordLabel": "",
"defaultError": "Bir tür hata var",
"passwordRequired": "Parola gerekli",
"Ok": "Tamam",
"done": "",
"Remove": "Kaldır",
"removePassword": "",
"shareVideoTitle": "",
"shareVideoLinkError": "",
"removeSharedVideoTitle": "",
@@ -198,6 +239,7 @@
"WaitForHostMsg": "",
"IamHost": "",
"Cancel": "İptal",
"Submit": "",
"retry": "",
"logoutTitle": "Oturum kapat",
"logoutQuestion": "Oturumu ve görüşmeyi sonlandırmak istediğinizden emin misiniz?",
@@ -212,12 +254,11 @@
"sipMsg": "SIP numarası gir",
"passwordCheck": "Parolanızı kaldırmak istediğinizden emin misiniz?",
"passwordMsg": "Odanızı kilitlemek için bir parola koyun",
"Invite": "Davet et",
"shareLink": "Davet etmek istediğiniz herkesle bu bağlantıyı paylaşın",
"shareLink": "",
"settings1": "Görüşmenizi yapılandır",
"settings2": "Katılımcılar sessiz katılsın",
"settings3": "Takma adlar gerekli<br/><br/>Odanızı kitlemek için bir parola ayarlayın:",
"yourPassword": "parolanız",
"yourPassword": "",
"Back": "Geri",
"serviceUnavailable": "Hizmet kullanım dışı",
"gracefulShutdown": "Hizmetimiz bakıp için durduruldu. Daha sonra tekrar deneyiniz.",
@@ -227,10 +268,14 @@
"password": "",
"userPassword": "parolanız",
"token": "",
"tokenAuthFailedTitle": "",
"tokenAuthFailed": "",
"displayNameRequired": "",
"enterDisplayName": "",
"extensionRequired": "",
"firefoxExtensionPrompt": "",
"rateExperience": "",
"feedbackHelp": "",
"feedbackQuestion": "",
"thankYou": "",
"sorryFeedback": "",
@@ -242,6 +287,7 @@
"stopLiveStreaming": "",
"stopRecording": "",
"doNotShowWarningAgain": "",
"doNotShowMessageAgain": "",
"permissionDenied": "",
"screenSharingPermissionDeniedError": "",
"micErrorPresent": "",
@@ -254,7 +300,15 @@
"micUnknownError": "",
"micPermissionDeniedError": "",
"micNotFoundError": "",
"micConstraintFailedError": ""
"micConstraintFailedError": "",
"micNotSendingData": "",
"cameraNotSendingData": "",
"goToStore": "",
"externalInstallationTitle": "",
"externalInstallationMsg": "",
"muteParticipantTitle": "",
"muteParticipantBody": "",
"muteParticipantButton": "Sustur"
},
"\u0005dialog": {},
"email": {

View File

@@ -156,8 +156,8 @@
"kick": "Kick out",
"muted": "Muted",
"domute": "Mute",
"flip": "Flip"
"flip": "Flip",
"remoteControl": "Remote control"
},
"connectionindicator":
{
@@ -316,7 +316,12 @@
"externalInstallationMsg": "You need to install our desktop sharing extension.",
"muteParticipantTitle": "Mute this participant?",
"muteParticipantBody": "You won't be able to unmute them, but they can unmute themselves at any time.",
"muteParticipantButton": "Mute"
"muteParticipantButton": "Mute",
"remoteControlTitle": "Remote Control",
"remoteControlDeniedMessage": "__user__ rejected your remote control request!",
"remoteControlAllowedMessage": "__user__ accepted your remote control request!",
"remoteControlErrorMessage": "An error occurred while trying to request remote control permissions from __user__!",
"remoteControlStopMessage": "The remote control session ended!"
},
"email":
{

View File

@@ -1,5 +1,4 @@
/* global APP, getConfigParamsFromUrl */
const logger = require("jitsi-meet-logger").getLogger(__filename);
/**
* Implements API class that communicates with external api class
@@ -56,38 +55,15 @@ function initCommands() {
APP.conference.toggleScreenSharing.bind(APP.conference),
"video-hangup": () => APP.conference.hangup(),
"email": APP.conference.changeLocalEmail,
"avatar-url": APP.conference.changeLocalAvatarUrl
"avatar-url": APP.conference.changeLocalAvatarUrl,
"remote-control-event": event =>
APP.remoteControl.onRemoteControlAPIEvent(event)
};
Object.keys(commands).forEach(function (key) {
postis.listen(key, args => commands[key](...args));
});
}
/**
* Maps the supported events and their status
* (true it the event is enabled and false if it is disabled)
* @type {{
* incoming-message: boolean,
* outgoing-message: boolean,
* display-name-change: boolean,
* participant-left: boolean,
* participant-joined: boolean,
* video-conference-left: boolean,
* video-conference-joined: boolean
* }}
*/
const events = {
"incoming-message": false,
"outgoing-message":false,
"display-name-change": false,
"participant-joined": false,
"participant-left": false,
"video-conference-joined": false,
"video-conference-left": false,
"video-ready-to-close": false
};
/**
* Sends message to the external application.
* @param message {object}
@@ -95,27 +71,19 @@ const events = {
* @param params {object} the object that will be sent as JSON string
*/
function sendMessage(message) {
if(enabled)
if(enabled) {
postis.send(message);
}
}
/**
* Check whether the API should be enabled or not.
* @returns {boolean}
*/
function isEnabled () {
function shouldBeEnabled () {
return (typeof jitsi_meet_external_api_id === "number");
}
/**
* Checks whether the event is enabled ot not.
* @param name the name of the event.
* @returns {*}
*/
function isEventEnabled (name) {
return events[name];
}
/**
* Sends event object to the external application that has been subscribed
* for that event.
@@ -123,29 +91,18 @@ function isEventEnabled (name) {
* @param object data associated with the event
*/
function triggerEvent (name, object) {
if(isEventEnabled(name))
if(enabled) {
sendMessage({method: name, params: object});
}
/**
* Handles system messages. (for example: enable/disable events)
* @param message {object} the message
*/
function onSystemMessage(message) {
switch (message.type) {
case "eventStatus":
if(!message.name || !message.value) {
logger.warn("Unknown system message format", message);
break;
}
events[message.name] = message.value;
break;
default:
logger.warn("Unknown system message type", message);
}
}
export default {
class API {
/**
* Constructs new instance
* @constructor
*/
constructor() { }
/**
* Initializes the APIConnector. Setups message event listeners that will
* receive information from external applications that embed Jitsi Meet.
@@ -153,17 +110,23 @@ export default {
* is initialized.
* @param options {object}
* @param forceEnable {boolean} if true the module will be enabled.
* @param enabledEvents {array} array of events that should be enabled.
*/
init (options = {}) {
if(!isEnabled() && !options.forceEnable)
if(!shouldBeEnabled() && !options.forceEnable)
return;
enabled = true;
if(options.enabledEvents)
options.enabledEvents.forEach(function (eventName) {
events[eventName] = true;
});
if(!postis) {
this._initPostis();
}
}
/**
* initializes postis library.
* @private
*/
_initPostis() {
let postisOptions = {
window: target
};
@@ -171,9 +134,8 @@ export default {
postisOptions.scope
= "jitsi_meet_external_api_" + jitsi_meet_external_api_id;
postis = postisInit(postisOptions);
postis.listen("jitsiSystemMessage", onSystemMessage);
initCommands();
},
}
/**
* Notify external application (if API is enabled) that message was sent.
@@ -181,7 +143,7 @@ export default {
*/
notifySendingChatMessage (body) {
triggerEvent("outgoing-message", {"message": body});
},
}
/**
* Notify external application (if API is enabled) that
@@ -200,7 +162,7 @@ export default {
"incoming-message",
{"from": id, "nick": nick, "message": body, "stamp": ts}
);
},
}
/**
* Notify external application (if API is enabled) that
@@ -209,7 +171,7 @@ export default {
*/
notifyUserJoined (id) {
triggerEvent("participant-joined", {id});
},
}
/**
* Notify external application (if API is enabled) that
@@ -218,7 +180,7 @@ export default {
*/
notifyUserLeft (id) {
triggerEvent("participant-left", {id});
},
}
/**
* Notify external application (if API is enabled) that
@@ -228,7 +190,7 @@ export default {
*/
notifyDisplayNameChanged (id, displayName) {
triggerEvent("display-name-change", {id, displayname: displayName});
},
}
/**
* Notify external application (if API is enabled) that
@@ -238,7 +200,7 @@ export default {
*/
notifyConferenceJoined (room) {
triggerEvent("video-conference-joined", {roomName: room});
},
}
/**
* Notify external application (if API is enabled) that
@@ -248,7 +210,7 @@ export default {
*/
notifyConferenceLeft (room) {
triggerEvent("video-conference-left", {roomName: room});
},
}
/**
* Notify external application (if API is enabled) that
@@ -256,13 +218,23 @@ export default {
*/
notifyReadyToClose () {
triggerEvent("video-ready-to-close", {});
},
}
/**
* Sends remote control event.
* @param {RemoteControlEvent} event the remote control event.
*/
sendRemoteControlEvent(event) {
sendMessage({method: "remote-control-event", params: event});
}
/**
* Removes the listeners.
*/
dispose: function () {
dispose () {
if(enabled)
postis.destroy();
}
};
}
export default new API();

View File

@@ -69,20 +69,15 @@ function sendMessage(postis, object) {
}
/**
* Sends message for event enable/disable status change.
* @param postis {Postis object} the postis instance that is going to be used.
* @param event {string} the name of the event
* @param status {boolean} true - enabled; false - disabled;
* Adds given number to the numberOfParticipants property of given APIInstance.
* @param {JitsiMeetExternalAPI} APIInstance the instance of the
* JitsiMeetExternalAPI
* @param {int} number - the number of participants to be added to
* numberOfParticipants property (this parameter can be negative number if the
* numberOfParticipants should be decreased).
*/
function changeEventStatus(postis, event, status) {
if(!(event in events)) {
logger.error("Not supported event name.");
return;
}
sendMessage(postis, {
method: "jitsiSystemMessage",
params: {type: "eventStatus", name: events[event], value: status}
});
function changeParticipantNumber(APIInstance, number) {
APIInstance.numberOfParticipants += number;
}
/**
@@ -161,6 +156,12 @@ function JitsiMeetExternalAPI(domain, room_name, width, height, parentNode,
this.eventHandlers = {};
// Map<{string} event_name, {boolean} postis_listener_added>
this.postisListeners = {};
this.numberOfParticipants = 1;
this._setupListeners();
id++;
}
@@ -313,14 +314,15 @@ JitsiMeetExternalAPI.prototype.addEventListener = function(event, listener) {
}
// We cannot remove listeners from postis that's why we are handling the
// callback that way.
if(!(event in this.eventHandlers))
if(!this.postisListeners[event]) {
this.postis.listen(events[event], function(data) {
if((event in this.eventHandlers) &&
typeof this.eventHandlers[event] === "function")
this.eventHandlers[event].call(null, data);
}.bind(this));
this.postisListeners[event] = true;
}
this.eventHandlers[event] = listener;
changeEventStatus(this.postis, event, true);
};
/**
@@ -334,7 +336,6 @@ JitsiMeetExternalAPI.prototype.removeEventListener = function(event) {
return;
}
delete this.eventHandlers[event];
changeEventStatus(this.postis, event, false);
};
/**
@@ -346,6 +347,25 @@ JitsiMeetExternalAPI.prototype.removeEventListeners = function(events) {
this.removeEventListener(events[i]);
};
/**
* Returns the number of participants in the conference.
* NOTE: the local participant is included.
* @returns {int} the number of participants in the conference.
*/
JitsiMeetExternalAPI.prototype.getNumberOfParticipants = function() {
return this.numberOfParticipants;
};
/**
* Setups listeners that are used internally for JitsiMeetExternalAPI.
*/
JitsiMeetExternalAPI.prototype._setupListeners = function() {
this.postis.listen("participant-joined",
changeParticipantNumber.bind(null, this, 1));
this.postis.listen("participant-left",
changeParticipantNumber.bind(null, this, -1));
};
/**
* Removes the listeners and removes the Jitsi Meet frame.
*/

View File

@@ -1441,4 +1441,11 @@ UI.hideUserMediaPermissionsGuidanceOverlay = function () {
GumPermissionsOverlay.hide();
};
/**
* Handles user's features changes.
*/
UI.onUserFeaturesChanged = function (user) {
VideoLayout.onUserFeaturesChanged(user);
};
module.exports = UI;

View File

@@ -1,8 +1,9 @@
/* global $, APP, interfaceConfig */
/* global $, APP */
const logger = require("jitsi-meet-logger").getLogger(__filename);
import Avatar from "../avatar/Avatar";
import {createDeferred} from '../../util/helpers';
import UIEvents from "../../../service/UI/UIEvents";
import UIUtil from "../util/UIUtil";
import {VideoContainer, VIDEO_CONTAINER_TYPE} from "./VideoContainer";
@@ -19,6 +20,7 @@ export default class LargeVideoManager {
* @type {Object.<string, LargeContainer>}
*/
this.containers = {};
this.eventEmitter = emitter;
this.state = VIDEO_CONTAINER_TYPE;
this.videoContainer = new VideoContainer(
@@ -37,37 +39,6 @@ export default class LargeVideoManager {
display: 'inline-block'
});
if (interfaceConfig.SHOW_JITSI_WATERMARK
&& !interfaceConfig.filmStripOnly) {
let leftWatermarkDiv
= this.$container.find("div.watermark.leftwatermark");
leftWatermarkDiv.css({display: 'block'});
UIUtil.setLinkHref(
leftWatermarkDiv.parent(),
interfaceConfig.JITSI_WATERMARK_LINK);
}
if (interfaceConfig.SHOW_BRAND_WATERMARK
&& !interfaceConfig.filmStripOnly) {
let rightWatermarkDiv
= this.$container.find("div.watermark.rightwatermark");
rightWatermarkDiv.css({
display: 'block',
backgroundImage: 'url(images/rightwatermark.png)'
});
UIUtil.setLinkHref(
rightWatermarkDiv.parent(),
interfaceConfig.BRAND_WATERMARK_LINK);
}
if (interfaceConfig.SHOW_POWERED_BY) {
this.$container.children("a.poweredby").css({display: 'block'});
}
this.$container.hover(
e => this.onHoverIn(e),
e => this.onHoverOut(e)
@@ -195,6 +166,7 @@ export default class LargeVideoManager {
// after everything is done check again if there are any pending
// new streams.
this.updateInProcess = false;
this.eventEmitter.emit(UIEvents.LARGE_VIDEO_ID_CHANGED, this.id);
this.scheduleLargeVideoUpdate();
});
}

View File

@@ -29,6 +29,7 @@ function RemoteVideo(user, VideoLayout, emitter) {
this.videoSpanId = `participant_${this.id}`;
SmallVideo.call(this, VideoLayout);
this.hasRemoteVideoMenu = false;
this._supportsRemoteControl = false;
this.addRemoteVideoContainer();
this.connectionIndicator = new ConnectionIndicator(this, this.id);
this.setDisplayName();
@@ -64,7 +65,7 @@ RemoteVideo.prototype.addRemoteVideoContainer = function() {
this.initBrowserSpecificProperties();
if (APP.conference.isModerator) {
if (APP.conference.isModerator || this._supportsRemoteControl) {
this.addRemoteVideoMenu();
}
@@ -106,14 +107,6 @@ RemoteVideo.prototype._initPopupMenu = function (popupMenuElement) {
// call the original show, passing its actual this
origShowFunc.call(this.popover);
}.bind(this);
// override popover hide method so we can cleanup click handlers
let origHideFunc = this.popover.forceHide;
this.popover.forceHide = function () {
$(document).off("click", '#mutelink_' + this.id);
$(document).off("click", '#ejectlink_' + this.id);
origHideFunc.call(this.popover);
}.bind(this);
};
/**
@@ -139,38 +132,68 @@ RemoteVideo.prototype._generatePopupContent = function () {
let popupmenuElement = document.createElement('ul');
popupmenuElement.className = 'popupmenu';
popupmenuElement.id = `remote_popupmenu_${this.id}`;
let menuItems = [];
let muteTranslationKey;
let muteClassName;
if (this.isAudioMuted) {
muteTranslationKey = 'videothumbnail.muted';
muteClassName = 'mutelink disabled';
} else {
muteTranslationKey = 'videothumbnail.domute';
muteClassName = 'mutelink';
if(APP.conference.isModerator) {
let muteTranslationKey;
let muteClassName;
if (this.isAudioMuted) {
muteTranslationKey = 'videothumbnail.muted';
muteClassName = 'mutelink disabled';
} else {
muteTranslationKey = 'videothumbnail.domute';
muteClassName = 'mutelink';
}
let muteHandler = this._muteHandler.bind(this);
let kickHandler = this._kickHandler.bind(this);
menuItems = [
{
id: 'mutelink_' + this.id,
handler: muteHandler,
icon: 'icon-mic-disabled',
className: muteClassName,
data: {
i18n: muteTranslationKey
}
}, {
id: 'ejectlink_' + this.id,
handler: kickHandler,
icon: 'icon-kick',
data: {
i18n: 'videothumbnail.kick'
}
}
];
}
let muteHandler = this._muteHandler.bind(this);
let kickHandler = this._kickHandler.bind(this);
let menuItems = [
{
id: 'mutelink_' + this.id,
handler: muteHandler,
icon: 'icon-mic-disabled',
className: muteClassName,
data: {
i18n: muteTranslationKey
}
}, {
id: 'ejectlink_' + this.id,
handler: kickHandler,
icon: 'icon-kick',
data: {
i18n: 'videothumbnail.kick'
}
if(this._supportsRemoteControl) {
let icon, handler, className;
if(APP.remoteControl.controller.getRequestedParticipant()
=== this.id) {
handler = () => {};
className = "requestRemoteControlLink disabled";
icon = "remote-control-spinner fa fa-spinner fa-spin";
} else if(!APP.remoteControl.controller.isStarted()) {
handler = this._requestRemoteControlPermissions.bind(this);
icon = "fa fa-play";
className = "requestRemoteControlLink";
} else {
handler = this._stopRemoteControl.bind(this);
icon = "fa fa-stop";
className = "requestRemoteControlLink";
}
];
menuItems.push({
id: 'remoteControl_' + this.id,
handler,
icon,
className,
data: {
i18n: 'videothumbnail.remoteControl'
}
});
}
menuItems.forEach(el => {
let menuItem = this._generatePopupMenuItem(el);
@@ -182,6 +205,76 @@ RemoteVideo.prototype._generatePopupContent = function () {
return popupmenuElement;
};
/**
* Sets the remote control supported value and initializes or updates the menu
* depending on the remote control is supported or not.
* @param {boolean} isSupported
*/
RemoteVideo.prototype.setRemoteControlSupport = function(isSupported = false) {
if(this._supportsRemoteControl === isSupported) {
return;
}
this._supportsRemoteControl = isSupported;
if(!isSupported) {
return;
}
if(!this.hasRemoteVideoMenu) {
//create menu
this.addRemoteVideoMenu();
} else {
//update the content
this.updateRemoteVideoMenu(this.isAudioMuted, true);
}
};
/**
* Requests permissions for remote control session.
*/
RemoteVideo.prototype._requestRemoteControlPermissions = function () {
APP.remoteControl.controller.requestPermissions(
this.id, this.VideoLayout.getLargeVideoWrapper()).then(result => {
if(result === null) {
return;
}
this.updateRemoteVideoMenu(this.isAudioMuted, true);
APP.UI.messageHandler.openMessageDialog(
"dialog.remoteControlTitle",
(result === false) ? "dialog.remoteControlDeniedMessage"
: "dialog.remoteControlAllowedMessage",
{user: this.user.getDisplayName()
|| interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME}
);
if(result === true) {//the remote control permissions has been granted
// pin the controlled participant
let pinnedId = this.VideoLayout.getPinnedId();
if(pinnedId !== this.id) {
this.VideoLayout.handleVideoThumbClicked(this.id);
}
}
}, error => {
logger.error(error);
this.updateRemoteVideoMenu(this.isAudioMuted, true);
APP.UI.messageHandler.openMessageDialog(
"dialog.remoteControlTitle",
"dialog.remoteControlErrorMessage",
{user: this.user.getDisplayName()
|| interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME}
);
});
this.updateRemoteVideoMenu(this.isAudioMuted, true);
};
/**
* Stops remote control session.
*/
RemoteVideo.prototype._stopRemoteControl = function () {
// send message about stopping
APP.remoteControl.controller.stop();
this.updateRemoteVideoMenu(this.isAudioMuted, true);
};
RemoteVideo.prototype._muteHandler = function () {
if (this.isAudioMuted)
return;
@@ -244,8 +337,7 @@ RemoteVideo.prototype._generatePopupMenuItem = function (opts = {}) {
linkItem.appendChild(textContent);
linkItem.id = id;
// Delegate event to the document.
$(document).on("click", `#${id}`, handler);
linkItem.onclick = handler;
menuItem.appendChild(linkItem);
return menuItem;

View File

@@ -406,6 +406,7 @@ var VideoLayout = {
remoteVideo = smallVideo;
else
remoteVideo = new RemoteVideo(user, VideoLayout, eventEmitter);
this._setRemoteControlProperties(user, remoteVideo);
this.addRemoteVideoContainer(id, remoteVideo);
},
@@ -1158,12 +1159,44 @@ var VideoLayout = {
* Sets the flipX state of the local video.
* @param {boolean} true for flipped otherwise false;
*/
setLocalFlipX: function (val) {
setLocalFlipX (val) {
this.localFlipX = val;
},
getEventEmitter: () => {return eventEmitter;}
getEventEmitter() {return eventEmitter;},
/**
* Handles user's features changes.
*/
onUserFeaturesChanged (user) {
let video = this.getSmallVideo(user.getId());
if (!video) {
return;
}
this._setRemoteControlProperties(user, video);
},
/**
* Sets the remote control properties (checks whether remote control
* is supported and executes remoteVideo.setRemoteControlSupport).
* @param {JitsiParticipant} user the user that will be checked for remote
* control support.
* @param {RemoteVideo} remoteVideo the remoteVideo on which the properties
* will be set.
*/
_setRemoteControlProperties (user, remoteVideo) {
APP.remoteControl.checkUserRemoteControlSupport(user).then(result =>
remoteVideo.setRemoteControlSupport(result));
},
/**
* Returns the wrapper jquery selector for the largeVideo
* @returns {JQuerySelector} the wrapper jquery selector for the largeVideo
*/
getLargeVideoWrapper() {
return this.getCurrentlyOnLargeContainer().$wrapper;
}
};
export default VideoLayout;

View File

@@ -65,6 +65,12 @@ function showKeyboardShortcutsPanel(show) {
*/
let _shortcuts = {};
/**
* True if the keyboard shortcuts are enabled and false if not.
* @type {boolean}
*/
let enabled = true;
/**
* Maps keycode to character, id of popover for given function and function.
*/
@@ -74,6 +80,9 @@ var KeyboardShortcut = {
var self = this;
window.onkeyup = function(e) {
if(!enabled) {
return;
}
var key = self._getKeyboardKey(e).toUpperCase();
var num = parseInt(key, 10);
if(!($(":focus").is("input[type=text]") ||
@@ -93,6 +102,9 @@ var KeyboardShortcut = {
};
window.onkeydown = function(e) {
if(!enabled) {
return;
}
if(!($(":focus").is("input[type=text]") ||
$(":focus").is("input[type=password]") ||
$(":focus").is("textarea"))) {
@@ -105,6 +117,14 @@ var KeyboardShortcut = {
};
},
/**
* Enables/Disables the keyboard shortcuts.
* @param {boolean} value - the new value.
*/
enable: function (value) {
enabled = value;
},
/**
* Registers a new shortcut.
*

163
modules/keycode/keycode.js Normal file
View File

@@ -0,0 +1,163 @@
/**
* Enumerates the supported keys.
* NOTE: The maps represents physical keys on the keyboard, not chars.
* @readonly
* @enum {string}
*/
export const KEYS = {
BACKSPACE: "backspace" ,
DELETE : "delete",
RETURN : "enter",
TAB : "tab",
ESCAPE : "escape",
UP : "up",
DOWN : "down",
RIGHT : "right",
LEFT : "left",
HOME : "home",
END : "end",
PAGEUP : "pageup",
PAGEDOWN : "pagedown",
F1 : "f1",
F2 : "f2",
F3 : "f3",
F4 : "f4",
F5 : "f5",
F6 : "f6",
F7 : "f7",
F8 : "f8",
F9 : "f9",
F10 : "f10",
F11 : "f11",
F12 : "f12",
META : "command",
CMD_L: "command",
CMD_R: "command",
ALT : "alt",
CONTROL : "control",
SHIFT : "shift",
CAPS_LOCK: "caps_lock", //not supported by robotjs
SPACE : "space",
PRINTSCREEN : "printscreen",
INSERT : "insert",
NUMPAD_0 : "numpad_0",
NUMPAD_1 : "numpad_1",
NUMPAD_2 : "numpad_2",
NUMPAD_3 : "numpad_3",
NUMPAD_4 : "numpad_4",
NUMPAD_5 : "numpad_5",
NUMPAD_6 : "numpad_6",
NUMPAD_7 : "numpad_7",
NUMPAD_8 : "numpad_8",
NUMPAD_9 : "numpad_9",
COMMA: ",",
PERIOD: ".",
SEMICOLON: ";",
QUOTE: "'",
BRACKET_LEFT: "[",
BRACKET_RIGHT: "]",
BACKQUOTE: "`",
BACKSLASH: "\\",
MINUS: "-",
EQUAL: "=",
SLASH: "/"
};
/**
* Mapping between the key codes and keys deined in KEYS.
* The mappings are based on
* https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode#Specifications
*/
let keyCodeToKey = {
8: KEYS.BACKSPACE,
9: KEYS.TAB,
13: KEYS.RETURN,
16: KEYS.SHIFT,
17: KEYS.CONTROL,
18: KEYS.ALT,
20: KEYS.CAPS_LOCK,
27: KEYS.ESCAPE,
32: KEYS.SPACE,
33: KEYS.PAGEUP,
34: KEYS.PAGEDOWN,
35: KEYS.END,
36: KEYS.HOME,
37: KEYS.LEFT,
38: KEYS.UP,
39: KEYS.RIGHT,
40: KEYS.DOWN,
42: KEYS.PRINTSCREEN,
44: KEYS.PRINTSCREEN,
45: KEYS.INSERT,
46: KEYS.DELETE,
59: KEYS.SEMICOLON,
61: KEYS.EQUAL,
91: KEYS.CMD_L,
92: KEYS.CMD_R,
93: KEYS.CMD_R,
96: KEYS.NUMPAD_0,
97: KEYS.NUMPAD_1,
98: KEYS.NUMPAD_2,
99: KEYS.NUMPAD_3,
100: KEYS.NUMPAD_4,
101: KEYS.NUMPAD_5,
102: KEYS.NUMPAD_6,
103: KEYS.NUMPAD_7,
104: KEYS.NUMPAD_8,
105: KEYS.NUMPAD_9,
112: KEYS.F1,
113: KEYS.F2,
114: KEYS.F3,
115: KEYS.F4,
116: KEYS.F5,
117: KEYS.F6,
118: KEYS.F7,
119: KEYS.F8,
120: KEYS.F9,
121: KEYS.F10,
122: KEYS.F11,
123: KEYS.F12,
124: KEYS.PRINTSCREEN,
173: KEYS.MINUS,
186: KEYS.SEMICOLON,
187: KEYS.EQUAL,
188: KEYS.COMMA,
189: KEYS.MINUS,
190: KEYS.PERIOD,
191: KEYS.SLASH,
192: KEYS.BACKQUOTE,
219: KEYS.BRACKET_LEFT,
220: KEYS.BACKSLASH,
221: KEYS.BRACKET_RIGHT,
222: KEYS.QUOTE,
224: KEYS.META,
229: KEYS.SEMICOLON
};
/**
* Generate codes for digit keys (0-9)
*/
for(let i = 0; i < 10; i++) {
keyCodeToKey[i + 48] = `${i}`;
}
/**
* Generate codes for letter keys (a-z)
*/
for(let i = 0; i < 26; i++) {
let keyCode = i + 65;
keyCodeToKey[keyCode] = String.fromCharCode(keyCode).toLowerCase();
}
/**
* Returns key associated with the keyCode from the passed event.
* @param {KeyboardEvent} event the event
* @returns {KEYS} the key on the keyboard.
*/
export function keyboardEventToKey(event) {
return keyCodeToKey[event.which];
}

View File

@@ -0,0 +1,374 @@
/* global $, JitsiMeetJS, APP */
const logger = require("jitsi-meet-logger").getLogger(__filename);
import * as KeyCodes from "../keycode/keycode";
import {EVENT_TYPES, REMOTE_CONTROL_EVENT_TYPE, PERMISSIONS_ACTIONS}
from "../../service/remotecontrol/Constants";
import RemoteControlParticipant from "./RemoteControlParticipant";
import UIEvents from "../../service/UI/UIEvents";
const ConferenceEvents = JitsiMeetJS.events.conference;
/**
* Extract the keyboard key from the keyboard event.
* @param event {KeyboardEvent} the event.
* @returns {KEYS} the key that is pressed or undefined.
*/
function getKey(event) {
return KeyCodes.keyboardEventToKey(event);
}
/**
* Extract the modifiers from the keyboard event.
* @param event {KeyboardEvent} the event.
* @returns {Array} with possible values: "shift", "control", "alt", "command".
*/
function getModifiers(event) {
let modifiers = [];
if(event.shiftKey) {
modifiers.push("shift");
}
if(event.ctrlKey) {
modifiers.push("control");
}
if(event.altKey) {
modifiers.push("alt");
}
if(event.metaKey) {
modifiers.push("command");
}
return modifiers;
}
/**
* This class represents the controller party for a remote controller session.
* It listens for mouse and keyboard events and sends them to the receiver
* party of the remote control session.
*/
export default class Controller extends RemoteControlParticipant {
/**
* Creates new instance.
*/
constructor() {
super();
this.isCollectingEvents = false;
this.controlledParticipant = null;
this.requestedParticipant = null;
this._stopListener = this._handleRemoteControlStoppedEvent.bind(this);
this._userLeftListener = this._onUserLeft.bind(this);
this._largeVideoChangedListener
= this._onLargeVideoIdChanged.bind(this);
}
/**
* Requests permissions from the remote control receiver side.
* @param {string} userId the user id of the participant that will be
* requested.
* @param {JQuerySelector} eventCaptureArea the area that is going to be
* used mouse and keyboard event capture.
* @returns {Promise<boolean>} - resolve values:
* true - accept
* false - deny
* null - the participant has left.
*/
requestPermissions(userId, eventCaptureArea) {
if(!this.enabled) {
return Promise.reject(new Error("Remote control is disabled!"));
}
this.area = eventCaptureArea;// $("#largeVideoWrapper")
logger.log("Requsting remote control permissions from: " + userId);
return new Promise((resolve, reject) => {
const clearRequest = () => {
this.requestedParticipant = null;
APP.conference.removeConferenceListener(
ConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
permissionsReplyListener);
APP.conference.removeConferenceListener(
ConferenceEvents.USER_LEFT,
onUserLeft);
};
const permissionsReplyListener = (participant, event) => {
let result = null;
try {
result = this._handleReply(participant, event);
} catch (e) {
reject(e);
}
if(result !== null) {
clearRequest();
resolve(result);
}
};
const onUserLeft = (id) => {
if(id === this.requestedParticipant) {
clearRequest();
resolve(null);
}
};
APP.conference.addConferenceListener(
ConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
permissionsReplyListener);
APP.conference.addConferenceListener(ConferenceEvents.USER_LEFT,
onUserLeft);
this.requestedParticipant = userId;
this._sendRemoteControlEvent(userId, {
type: EVENT_TYPES.permissions,
action: PERMISSIONS_ACTIONS.request
}, e => {
clearRequest();
reject(e);
});
});
}
/**
* Handles the reply of the permissions request.
* @param {JitsiParticipant} participant the participant that has sent the
* reply
* @param {RemoteControlEvent} event the remote control event.
*/
_handleReply(participant, event) {
const remoteControlEvent = event.event;
const userId = participant.getId();
if(this.enabled && event.type === REMOTE_CONTROL_EVENT_TYPE
&& remoteControlEvent.type === EVENT_TYPES.permissions
&& userId === this.requestedParticipant) {
if(remoteControlEvent.action !== PERMISSIONS_ACTIONS.grant) {
this.area = null;
}
switch(remoteControlEvent.action) {
case PERMISSIONS_ACTIONS.grant: {
this.controlledParticipant = userId;
logger.log("Remote control permissions granted to: "
+ userId);
this._start();
return true;
}
case PERMISSIONS_ACTIONS.deny:
return false;
case PERMISSIONS_ACTIONS.error:
throw new Error("Error occurred on receiver side");
default:
throw new Error("Unknown reply received!");
}
} else {
//different message type or another user -> ignoring the message
return null;
}
}
/**
* Handles remote control stopped.
* @param {JitsiParticipant} participant the participant that has sent the
* event
* @param {Object} event EndpointMessage event from the data channels.
* @property {string} type property. The function process only events of
* type REMOTE_CONTROL_EVENT_TYPE
* @property {RemoteControlEvent} event - the remote control event.
*/
_handleRemoteControlStoppedEvent(participant, event) {
if(this.enabled && event.type === REMOTE_CONTROL_EVENT_TYPE
&& event.event.type === EVENT_TYPES.stop
&& participant.getId() === this.controlledParticipant) {
this._stop();
}
}
/**
* Starts processing the mouse and keyboard events. Sets conference
* listeners. Disables keyboard events.
*/
_start() {
logger.log("Starting remote control controller.");
APP.UI.addListener(UIEvents.LARGE_VIDEO_ID_CHANGED,
this._largeVideoChangedListener);
APP.conference.addConferenceListener(
ConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
this._stopListener);
APP.conference.addConferenceListener(ConferenceEvents.USER_LEFT,
this._userLeftListener);
this.resume();
}
/**
* Disables the keyboatd shortcuts. Starts collecting remote control
* events.
*
* It can be used to resume an active remote control session wchich was
* paused with this.pause().
*/
resume() {
if(!this.enabled || this.isCollectingEvents) {
return;
}
logger.log("Resuming remote control controller.");
this.isCollectingEvents = true;
APP.keyboardshortcut.enable(false);
this.area.mousemove(event => {
const position = this.area.position();
this._sendRemoteControlEvent(this.controlledParticipant, {
type: EVENT_TYPES.mousemove,
x: (event.pageX - position.left)/this.area.width(),
y: (event.pageY - position.top)/this.area.height()
});
});
this.area.mousedown(this._onMouseClickHandler.bind(this,
EVENT_TYPES.mousedown));
this.area.mouseup(this._onMouseClickHandler.bind(this,
EVENT_TYPES.mouseup));
this.area.dblclick(
this._onMouseClickHandler.bind(this, EVENT_TYPES.mousedblclick));
this.area.contextmenu(() => false);
this.area[0].onmousewheel = event => {
this._sendRemoteControlEvent(this.controlledParticipant, {
type: EVENT_TYPES.mousescroll,
x: event.deltaX,
y: event.deltaY
});
};
$(window).keydown(this._onKeyPessHandler.bind(this,
EVENT_TYPES.keydown));
$(window).keyup(this._onKeyPessHandler.bind(this, EVENT_TYPES.keyup));
}
/**
* Stops processing the mouse and keyboard events. Removes added listeners.
* Enables the keyboard shortcuts. Displays dialog to notify the user that
* remote control session has ended.
*/
_stop() {
if(!this.controlledParticipant) {
return;
}
logger.log("Stopping remote control controller.");
APP.UI.removeListener(UIEvents.LARGE_VIDEO_ID_CHANGED,
this._largeVideoChangedListener);
APP.conference.removeConferenceListener(
ConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
this._stopListener);
APP.conference.removeConferenceListener(ConferenceEvents.USER_LEFT,
this._userLeftListener);
this.controlledParticipant = null;
this.pause();
this.area = null;
APP.UI.messageHandler.openMessageDialog(
"dialog.remoteControlTitle",
"dialog.remoteControlStopMessage"
);
}
/**
* Executes this._stop() mehtod:
* Stops processing the mouse and keyboard events. Removes added listeners.
* Enables the keyboard shortcuts. Displays dialog to notify the user that
* remote control session has ended.
*
* In addition:
* Sends stop message to the controlled participant.
*/
stop() {
if(!this.controlledParticipant) {
return;
}
this._sendRemoteControlEvent(this.controlledParticipant, {
type: EVENT_TYPES.stop
});
this._stop();
}
/**
* Pauses the collecting of events and enables the keyboard shortcus. But
* it doesn't removes any other listeners. Basically the remote control
* session will be still active after this.pause(), but no events from the
* controller side will be captured and sent.
*
* You can resume the collecting of the events with this.resume().
*/
pause() {
if(!this.controlledParticipant) {
return;
}
logger.log("Pausing remote control controller.");
this.isCollectingEvents = false;
APP.keyboardshortcut.enable(true);
this.area.off( "mousemove" );
this.area.off( "mousedown" );
this.area.off( "mouseup" );
this.area.off( "contextmenu" );
this.area.off( "dblclick" );
$(window).off( "keydown");
$(window).off( "keyup");
this.area[0].onmousewheel = undefined;
}
/**
* Handler for mouse click events.
* @param {String} type the type of event ("mousedown"/"mouseup")
* @param {Event} event the mouse event.
*/
_onMouseClickHandler(type, event) {
this._sendRemoteControlEvent(this.controlledParticipant, {
type: type,
button: event.which
});
}
/**
* Returns true if the remote control session is started.
* @returns {boolean}
*/
isStarted() {
return this.controlledParticipant !== null;
}
/**
* Returns the id of the requested participant
* @returns {string} this.requestedParticipant.
* NOTE: This id should be the result of JitsiParticipant.getId() call.
*/
getRequestedParticipant() {
return this.requestedParticipant;
}
/**
* Handler for key press events.
* @param {String} type the type of event ("keydown"/"keyup")
* @param {Event} event the key event.
*/
_onKeyPessHandler(type, event) {
this._sendRemoteControlEvent(this.controlledParticipant, {
type: type,
key: getKey(event),
modifiers: getModifiers(event),
});
}
/**
* Calls the stop method if the other side have left.
* @param {string} id - the user id for the participant that have left
*/
_onUserLeft(id) {
if(this.controlledParticipant === id) {
this._stop();
}
}
/**
* Handles changes of the participant displayed on the large video.
* @param {string} id - the user id for the participant that is displayed.
*/
_onLargeVideoIdChanged(id) {
if (!this.controlledParticipant) {
return;
}
if(this.controlledParticipant == id) {
this.resume();
} else {
this.pause();
}
}
}

View File

@@ -0,0 +1,192 @@
/* global APP, JitsiMeetJS, interfaceConfig */
const logger = require("jitsi-meet-logger").getLogger(__filename);
import {DISCO_REMOTE_CONTROL_FEATURE, REMOTE_CONTROL_EVENT_TYPE, EVENT_TYPES,
PERMISSIONS_ACTIONS} from "../../service/remotecontrol/Constants";
import RemoteControlParticipant from "./RemoteControlParticipant";
import * as JitsiMeetConferenceEvents from '../../ConferenceEvents';
const ConferenceEvents = JitsiMeetJS.events.conference;
/**
* This class represents the receiver party for a remote controller session.
* It handles "remote-control-event" events and sends them to the
* API module. From there the events can be received from wrapper application
* and executed.
*/
export default class Receiver extends RemoteControlParticipant {
/**
* Creates new instance.
* @constructor
*/
constructor() {
super();
this.controller = null;
this._remoteControlEventsListener
= this._onRemoteControlEvent.bind(this);
this._userLeftListener = this._onUserLeft.bind(this);
this._hangupListener = this._onHangup.bind(this);
}
/**
* Enables / Disables the remote control
* @param {boolean} enabled the new state.
*/
enable(enabled) {
if(this.enabled === enabled) {
return;
}
this.enabled = enabled;
if(enabled === true) {
logger.log("Remote control receiver enabled.");
// Announce remote control support.
APP.connection.addFeature(DISCO_REMOTE_CONTROL_FEATURE, true);
APP.conference.addConferenceListener(
ConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
this._remoteControlEventsListener);
APP.conference.addListener(JitsiMeetConferenceEvents.BEFORE_HANGUP,
this._hangupListener);
} else {
logger.log("Remote control receiver disabled.");
this._stop(true);
APP.connection.removeFeature(DISCO_REMOTE_CONTROL_FEATURE);
APP.conference.removeConferenceListener(
ConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
this._remoteControlEventsListener);
APP.conference.removeListener(
JitsiMeetConferenceEvents.BEFORE_HANGUP,
this._hangupListener);
}
}
/**
* Removes the listener for ConferenceEvents.ENDPOINT_MESSAGE_RECEIVED
* events. Sends stop message to the wrapper application. Optionally
* displays dialog for informing the user that remote control session
* ended.
* @param {boolean} dontShowDialog - if true the dialog won't be displayed.
*/
_stop(dontShowDialog = false) {
if(!this.controller) {
return;
}
logger.log("Remote control receiver stop.");
this.controller = null;
APP.conference.removeConferenceListener(ConferenceEvents.USER_LEFT,
this._userLeftListener);
APP.API.sendRemoteControlEvent({
type: EVENT_TYPES.stop
});
if(!dontShowDialog) {
APP.UI.messageHandler.openMessageDialog(
"dialog.remoteControlTitle",
"dialog.remoteControlStopMessage"
);
}
}
/**
* Calls this._stop() and sends stop message to the controller participant
*/
stop() {
if(!this.controller) {
return;
}
this._sendRemoteControlEvent(this.controller, {
type: EVENT_TYPES.stop
});
this._stop();
}
/**
* Listens for data channel EndpointMessage events. Handles only events of
* type remote control. Sends "remote-control-event" events to the API
* module.
* @param {JitsiParticipant} participant the controller participant
* @param {Object} event EndpointMessage event from the data channels.
* @property {string} type property. The function process only events of
* type REMOTE_CONTROL_EVENT_TYPE
* @property {RemoteControlEvent} event - the remote control event.
*/
_onRemoteControlEvent(participant, event) {
if(this.enabled && event.type === REMOTE_CONTROL_EVENT_TYPE) {
const remoteControlEvent = event.event;
if(this.controller === null
&& remoteControlEvent.type === EVENT_TYPES.permissions
&& remoteControlEvent.action === PERMISSIONS_ACTIONS.request) {
remoteControlEvent.userId = participant.getId();
remoteControlEvent.userJID = participant.getJid();
remoteControlEvent.displayName = participant.getDisplayName()
|| interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME;
remoteControlEvent.screenSharing
= APP.conference.isSharingScreen;
} else if(this.controller !== participant.getId()) {
return;
} else if(remoteControlEvent.type === EVENT_TYPES.stop) {
this._stop();
return;
}
APP.API.sendRemoteControlEvent(remoteControlEvent);
} else if(event.type === REMOTE_CONTROL_EVENT_TYPE) {
logger.log("Remote control event is ignored because remote "
+ "control is disabled", event);
}
}
/**
* Handles remote control permission events received from the API module.
* @param {String} userId the user id of the participant related to the
* event.
* @param {PERMISSIONS_ACTIONS} action the action related to the event.
*/
_onRemoteControlPermissionsEvent(userId, action) {
if(action === PERMISSIONS_ACTIONS.grant) {
APP.conference.addConferenceListener(ConferenceEvents.USER_LEFT,
this._userLeftListener);
this.controller = userId;
logger.log("Remote control permissions granted to: " + userId);
if(!APP.conference.isSharingScreen) {
APP.conference.toggleScreenSharing();
APP.conference.screenSharingPromise.then(() => {
if(APP.conference.isSharingScreen) {
this._sendRemoteControlEvent(userId, {
type: EVENT_TYPES.permissions,
action: action
});
} else {
this._sendRemoteControlEvent(userId, {
type: EVENT_TYPES.permissions,
action: PERMISSIONS_ACTIONS.error
});
}
}).catch(() => {
this._sendRemoteControlEvent(userId, {
type: EVENT_TYPES.permissions,
action: PERMISSIONS_ACTIONS.error
});
});
return;
}
}
this._sendRemoteControlEvent(userId, {
type: EVENT_TYPES.permissions,
action: action
});
}
/**
* Calls the stop method if the other side have left.
* @param {string} id - the user id for the participant that have left
*/
_onUserLeft(id) {
if(this.controller === id) {
this._stop();
}
}
/**
* Handles hangup events. Disables the receiver.
*/
_onHangup() {
this.enable(false);
}
}

View File

@@ -0,0 +1,89 @@
/* global APP, config */
const logger = require("jitsi-meet-logger").getLogger(__filename);
import Controller from "./Controller";
import Receiver from "./Receiver";
import {EVENT_TYPES, DISCO_REMOTE_CONTROL_FEATURE}
from "../../service/remotecontrol/Constants";
/**
* Implements the remote control functionality.
*/
class RemoteControl {
/**
* Constructs new instance. Creates controller and receiver properties.
* @constructor
*/
constructor() {
this.controller = new Controller();
this.receiver = new Receiver();
this.enabled = false;
this.initialized = false;
}
/**
* Initializes the remote control - checks if the remote control should be
* enabled or not, initializes the API module.
*/
init() {
if(config.disableRemoteControl || this.initialized
|| !APP.conference.isDesktopSharingEnabled) {
return;
}
logger.log("Initializing remote control.");
this.initialized = true;
APP.API.init({
forceEnable: true,
});
this.controller.enable(true);
if(this.enabled) { // supported message came before init.
this._onRemoteControlSupported();
}
}
/**
* Handles remote control events from the API module. Currently only events
* with type = EVENT_TYPES.supported or EVENT_TYPES.permissions
* @param {RemoteControlEvent} event the remote control event.
*/
onRemoteControlAPIEvent(event) {
switch(event.type) {
case EVENT_TYPES.supported:
this._onRemoteControlSupported();
break;
case EVENT_TYPES.permissions:
this.receiver._onRemoteControlPermissionsEvent(
event.userId, event.action);
break;
}
}
/**
* Handles API event for support for executing remote control events into
* the wrapper application.
*/
_onRemoteControlSupported() {
logger.log("Remote Control supported.");
if(!config.disableRemoteControl) {
this.enabled = true;
if(this.initialized) {
this.receiver.enable(true);
}
} else {
logger.log("Remote Control disabled.");
}
}
/**
* Checks whether the passed user supports remote control or not
* @param {JitsiParticipant} user the user to be tested
* @returns {Promise<boolean>} the promise will be resolved with true if
* the user supports remote control and with false if not.
*/
checkUserRemoteControlSupport(user) {
return user.getFeatures().then(features =>
features.has(DISCO_REMOTE_CONTROL_FEATURE), () => false
);
}
}
export default new RemoteControl();

View File

@@ -0,0 +1,42 @@
/* global APP */
const logger = require("jitsi-meet-logger").getLogger(__filename);
import {REMOTE_CONTROL_EVENT_TYPE}
from "../../service/remotecontrol/Constants";
export default class RemoteControlParticipant {
/**
* Creates new instance.
*/
constructor() {
this.enabled = false;
}
/**
* Enables / Disables the remote control
* @param {boolean} enabled the new state.
*/
enable(enabled) {
this.enabled = enabled;
}
/**
* Sends remote control event to other participant trough data channel.
* @param {RemoteControlEvent} event the remote control event.
* @param {Function} onDataChannelFail handler for data channel failure.
*/
_sendRemoteControlEvent(to, event, onDataChannelFail = () => {}) {
if(!this.enabled || !to) {
logger.warn("Remote control: Skip sending remote control event."
+ " Params:", this.enable, to);
return;
}
try{
APP.conference.sendEndpointMessage(to,
{type: REMOTE_CONTROL_EVENT_TYPE, event});
} catch (e) {
logger.error("Failed to send EndpointMessage via the datachannels",
e);
onDataChannelFail(e);
}
}
}

View File

@@ -73,12 +73,6 @@ class TokenData{
this.jwt = jwt;
//External API settings
this.externalAPISettings = {
forceEnable: true,
enabledEvents: ["video-conference-joined", "video-conference-left",
"video-ready-to-close"]
};
this._decode();
// Use JWT param as token if there is not other token set and if the
// iss field is not anonymous. If you want to pass data with JWT token

View File

@@ -34,9 +34,10 @@
"postis": "^2.2.0",
"react": "15.4.2",
"react-dom": "15.4.2",
"react-native": "0.39.2",
"react-native": "0.40.0",
"react-native-keep-awake": "^1.0.7",
"react-native-prompt": "^1.0.0",
"react-native-vector-icons": "^3.0.0",
"react-native-vector-icons": "^4.0.0",
"react-native-webrtc": "jitsi/react-native-webrtc",
"react-redux": "^5.0.2",
"redux": "^3.5.2",
@@ -56,7 +57,7 @@
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-1": "^6.16.0",
"clean-css": "*",
"clean-css": "^3.0.0",
"css-loader": "*",
"eslint": "^3.13.1",
"eslint-plugin-jsdoc": "*",

View File

@@ -3,6 +3,8 @@
import { Linking } from 'react-native';
import { Platform } from '../../base/react';
import '../../audio-mode';
import '../../wake-lock';
import { AbstractApp } from './AbstractApp';

View File

@@ -23,7 +23,11 @@ export function init() {
APP.keyboardshortcut = KeyboardShortcut;
APP.tokenData = getTokenData();
APP.API.init(APP.tokenData.externalAPISettings);
// Force enable the API if jwt token is passed because most probably
// jitsi meet is displayed inside of wrapper that will need to communicate
// with jitsi meet.
APP.API.init(APP.tokenData.jwt ? { forceEnable: true } : undefined);
APP.translation.init(settings.getLanguage());
}

View File

@@ -1,3 +1,4 @@
export * from './actions';
export * from './actionTypes';
export * from './components';
export * from './functions';

View File

@@ -0,0 +1 @@
import './middleware';

View File

@@ -0,0 +1,57 @@
import { NativeModules } from 'react-native';
import { APP_WILL_MOUNT } from '../app';
import {
CONFERENCE_FAILED,
CONFERENCE_LEFT,
CONFERENCE_WILL_JOIN
} from '../base/conference';
import { MiddlewareRegistry } from '../base/redux';
/**
* Middleware that captures conference actions and sets the correct audio mode
* based on the type of conference. Audio-only conferences don't use the speaker
* by default, and video conferences do.
*
* @param {Store} store - Redux store.
* @returns {Function}
*/
MiddlewareRegistry.register(store => next => action => {
const AudioMode = NativeModules.AudioMode;
// The react-native module AudioMode is implemented on iOS at the time of
// this writing.
if (AudioMode) {
let audioMode;
switch (action.type) {
case APP_WILL_MOUNT:
case CONFERENCE_FAILED:
case CONFERENCE_LEFT:
audioMode = AudioMode.DEFAULT;
break;
case CONFERENCE_WILL_JOIN: {
const conference = store.getState()['features/base/conference'];
audioMode
= conference.audioOnly
? AudioMode.AUDIO_CALL
: AudioMode.VIDEO_CALL;
break;
}
default:
audioMode = null;
break;
}
if (audioMode !== null) {
AudioMode.setMode(audioMode).catch(err => {
console.error(`Failed to set audio mode ${audioMode}: ${err}`);
});
}
}
return next(action);
});

View File

@@ -34,6 +34,17 @@ export const CONFERENCE_JOINED = Symbol('CONFERENCE_JOINED');
*/
export const CONFERENCE_LEFT = Symbol('CONFERENCE_LEFT');
/**
* The type of the Redux action which signals that a specific conference will be
* joined.
*
* {
* type: CONFERENCE_WILL_JOIN,
* room: string
* }
*/
export const CONFERENCE_WILL_JOIN = Symbol('CONFERENCE_WILL_JOIN');
/**
* The type of the Redux action which signals that a specific conference will be
* left.

View File

@@ -12,6 +12,7 @@ import {
CONFERENCE_FAILED,
CONFERENCE_JOINED,
CONFERENCE_LEFT,
CONFERENCE_WILL_JOIN,
CONFERENCE_WILL_LEAVE,
LOCK_STATE_CHANGED,
SET_PASSWORD,
@@ -140,6 +141,25 @@ function _conferenceLeft(conference) {
};
}
/**
* Signals the intention of the application to have the local participant join a
* conference with a specific room (name). Similar in fashion
* to CONFERENCE_JOINED.
*
* @param {string} room - The room (name) which identifies the conference the
* local participant will (try to) join.
* @returns {{
* type: CONFERENCE_WILL_JOIN,
* room: string
* }}
*/
function _conferenceWillJoin(room) {
return {
type: CONFERENCE_WILL_JOIN,
room
};
}
/**
* Signals the intention of the application to have the local participant leave
* a specific conference. Similar in fashion to CONFERENCE_LEFT. Contrary to it
@@ -180,6 +200,8 @@ export function createConference() {
throw new Error('Cannot join conference without room name');
}
dispatch(_conferenceWillJoin(room));
// TODO Take options from config.
const conference
= connection.initJitsiConference(

View File

@@ -1,31 +1,31 @@
import { Symbol } from '../react';
/**
* Action to change muted state of the local audio.
* Action to set the muted state of the local audio.
*
* {
* type: AUDIO_MUTED_CHANGED,
* type: SET_AUDIO_MUTED,
* muted: boolean
* }
*/
export const AUDIO_MUTED_CHANGED = Symbol('AUDIO_MUTED_CHANGED');
export const SET_AUDIO_MUTED = Symbol('SET_AUDIO_MUTED');
/**
* Action to signal a change of the facing mode of the local video camera.
* Action to set the facing mode of the local video camera.
*
* {
* type: CAMERA_FACING_MODE_CHANGED,
* type: SET_CAMERA_FACING_MODE,
* cameraFacingMode: CAMERA_FACING_MODE
* }
*/
export const CAMERA_FACING_MODE_CHANGED = Symbol('CAMERA_FACING_MODE_CHANGED');
export const SET_CAMERA_FACING_MODE = Symbol('SET_CAMERA_FACING_MODE');
/**
* Action to change muted state of the local video.
* Action to set the muted state of the local video.
*
* {
* type: VIDEO_MUTED_CHANGED,
* type: SET_VIDEO_MUTED,
* muted: boolean
* }
*/
export const VIDEO_MUTED_CHANGED = Symbol('VIDEO_MUTED_CHANGED');
export const SET_VIDEO_MUTED = Symbol('SET_VIDEO_MUTED');

View File

@@ -1,44 +1,62 @@
import {
AUDIO_MUTED_CHANGED,
CAMERA_FACING_MODE_CHANGED,
VIDEO_MUTED_CHANGED
SET_AUDIO_MUTED,
SET_CAMERA_FACING_MODE,
SET_VIDEO_MUTED
} from './actionTypes';
import { CAMERA_FACING_MODE } from './constants';
import './middleware';
import './reducer';
/**
* Action to signal the change in local audio muted state.
* Action to set the muted state of the local audio.
*
* @param {boolean} muted - If local audio is muted.
* @param {boolean} muted - True if the local audio is to be muted or false if
* the local audio is to be unmuted.
* @returns {{
* type: AUDIO_MUTED_CHANGED,
* type: SET_AUDIO_MUTED,
* muted: boolean
* }}
*/
export function audioMutedChanged(muted) {
export function setAudioMuted(muted) {
return {
type: AUDIO_MUTED_CHANGED,
type: SET_AUDIO_MUTED,
muted
};
}
/**
* Action to signal the change in facing mode of local video camera.
* Action to set the facing mode of the local camera.
*
* @param {CAMERA_FACING_MODE} cameraFacingMode - Camera facing mode.
* @param {CAMERA_FACING_MODE} cameraFacingMode - The camera facing mode to set.
* @returns {{
* type: CAMERA_FACING_MODE_CHANGED,
* type: SET_CAMERA_FACING_MODE,
* cameraFacingMode: CAMERA_FACING_MODE
* }}
*/
export function cameraFacingModeChanged(cameraFacingMode) {
export function setCameraFacingMode(cameraFacingMode) {
return {
type: CAMERA_FACING_MODE_CHANGED,
type: SET_CAMERA_FACING_MODE,
cameraFacingMode
};
}
/**
* Action to set the muted state of the local video.
*
* @param {boolean} muted - True if the local video is to be muted or false if
* the local video is to be unmuted.
* @returns {{
* type: SET_VIDEO_MUTED,
* muted: boolean
* }}
*/
export function setVideoMuted(muted) {
return {
type: SET_VIDEO_MUTED,
muted
};
}
/**
* Toggles the mute state of the local audio track(s).
*
@@ -48,7 +66,7 @@ export function toggleAudioMuted() {
return (dispatch, getState) => {
const muted = getState()['features/base/media'].audio.muted;
return dispatch(audioMutedChanged(!muted));
return dispatch(setAudioMuted(!muted));
};
}
@@ -67,7 +85,7 @@ export function toggleCameraFacingMode() {
? CAMERA_FACING_MODE.ENVIRONMENT
: CAMERA_FACING_MODE.USER;
return dispatch(cameraFacingModeChanged(cameraFacingMode));
return dispatch(setCameraFacingMode(cameraFacingMode));
};
}
@@ -80,22 +98,6 @@ export function toggleVideoMuted() {
return (dispatch, getState) => {
const muted = getState()['features/base/media'].video.muted;
return dispatch(videoMutedChanged(!muted));
};
}
/**
* Action to signal the change in local video muted state.
*
* @param {boolean} muted - If local video is muted.
* @returns {{
* type: VIDEO_MUTED_CHANGED,
* muted: boolean
* }}
*/
export function videoMutedChanged(muted) {
return {
type: VIDEO_MUTED_CHANGED,
muted
return dispatch(setVideoMuted(!muted));
};
}

View File

@@ -3,9 +3,9 @@ import { MiddlewareRegistry } from '../redux';
import { setTrackMuted, TRACK_ADDED } from '../tracks';
import {
audioMutedChanged,
cameraFacingModeChanged,
videoMutedChanged
setAudioMuted,
setCameraFacingMode,
setVideoMuted
} from './actions';
import { CAMERA_FACING_MODE } from './constants';
@@ -42,10 +42,10 @@ function resetInitialMediaState(store) {
const { dispatch, getState } = store;
const state = getState()['features/base/media'];
state.audio.muted && dispatch(audioMutedChanged(false));
state.audio.muted && dispatch(setAudioMuted(false));
(state.video.facingMode !== CAMERA_FACING_MODE.USER)
&& dispatch(cameraFacingModeChanged(CAMERA_FACING_MODE.USER));
state.video.muted && dispatch(videoMutedChanged(false));
&& dispatch(setCameraFacingMode(CAMERA_FACING_MODE.USER));
state.video.muted && dispatch(setVideoMuted(false));
}
/**

View File

@@ -3,9 +3,9 @@ import { combineReducers } from 'redux';
import { ReducerRegistry } from '../redux';
import {
AUDIO_MUTED_CHANGED,
CAMERA_FACING_MODE_CHANGED,
VIDEO_MUTED_CHANGED
SET_AUDIO_MUTED,
SET_CAMERA_FACING_MODE,
SET_VIDEO_MUTED
} from './actionTypes';
import { CAMERA_FACING_MODE } from './constants';
@@ -35,7 +35,7 @@ const AUDIO_INITIAL_MEDIA_STATE = {
*/
function audio(state = AUDIO_INITIAL_MEDIA_STATE, action) {
switch (action.type) {
case AUDIO_MUTED_CHANGED:
case SET_AUDIO_MUTED:
return {
...state,
muted: action.muted
@@ -74,13 +74,13 @@ const VIDEO_INITIAL_MEDIA_STATE = {
*/
function video(state = VIDEO_INITIAL_MEDIA_STATE, action) {
switch (action.type) {
case CAMERA_FACING_MODE_CHANGED:
case SET_CAMERA_FACING_MODE:
return {
...state,
facingMode: action.cameraFacingMode
};
case VIDEO_MUTED_CHANGED:
case SET_VIDEO_MUTED:
return {
...state,
muted: action.muted

View File

@@ -0,0 +1,140 @@
/* global APP, interfaceConfig */
import React, { Component } from 'react';
/**
* The CSS style of the element with CSS class <tt>rightwatermark</tt>.
*/
const RIGHT_WATERMARK_STYLE = {
backgroundImage: 'url(images/rightwatermark.png)'
};
/**
* A Web Component which renders watermarks such as Jits, brand, powered by,
* etc.
*/
export class Watermarks extends Component {
/**
* Initializes a new Watermarks instance.
*
* @param {Object} props - The read-only properties with which the new
* instance is to be initialized.
*/
constructor(props) {
super(props);
let showBrandWatermark;
let showJitsiWatermark;
let showJitsiWatermarkForGuests;
if (interfaceConfig.filmStripOnly) {
showBrandWatermark = false;
showJitsiWatermark = false;
showJitsiWatermarkForGuests = false;
} else {
showBrandWatermark = interfaceConfig.SHOW_BRAND_WATERMARK;
showJitsiWatermark = interfaceConfig.SHOW_JITSI_WATERMARK;
showJitsiWatermarkForGuests
= interfaceConfig.SHOW_WATERMARK_FOR_GUESTS;
}
this.state = {
brandWatermarkLink:
showBrandWatermark ? interfaceConfig.BRAND_WATERMARK_LINK : '',
jitsiWatermarkLink:
showJitsiWatermark || showJitsiWatermarkForGuests
? interfaceConfig.JITSI_WATERMARK_LINK : '',
showBrandWatermark,
showJitsiWatermark,
showJitsiWatermarkForGuests,
showPoweredBy: interfaceConfig.SHOW_POWERED_BY
};
}
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
return (
<div>
{
this._renderJitsiWatermark()
}
{
this._renderBrandWatermark()
}
{
this._renderPoweredBy()
}
</div>
);
}
/**
* Renders a brand watermark if it is enabled.
*
* @private
* @returns {ReactElement|null} Watermark element or null.
*/
_renderBrandWatermark() {
if (this.state.showBrandWatermark) {
return (
<a
href = { this.state.brandWatermarkLink }
target = '_new'>
<div
className = 'watermark rightwatermark'
style = { RIGHT_WATERMARK_STYLE } />
</a>
);
}
return null;
}
/**
* Renders a Jitsi watermark if it is enabled.
*
* @private
* @returns {ReactElement|null}
*/
_renderJitsiWatermark() {
if (this.state.showJitsiWatermark
|| (APP.tokenData.isGuest
&& this.state.showJitsiWatermarkForGuests)) {
return (
<a
href = { this.state.jitsiWatermarkLink }
target = '_new'>
<div className = 'watermark leftwatermark' />
</a>
);
}
return null;
}
/**
* Renders a powered by block if it is enabled.
*
* @private
* @returns {ReactElement|null}
*/
_renderPoweredBy() {
if (this.state.showPoweredBy) {
return (
<a
className = 'poweredby'
href = 'http://jitsi.org'
target = '_new'>
<span data-i18n = 'poweredby' /> jitsi.org
</a>
);
}
return null;
}
}

View File

@@ -1,2 +1,3 @@
export * from './Container';
export * from './Link';
export * from './Watermarks';

View File

@@ -1,26 +1,17 @@
import { LIB_DISPOSED, LIB_INITIALIZED } from '../lib-jitsi-meet';
import {
LIB_DISPOSED,
LIB_INITIALIZED
} from '../lib-jitsi-meet';
import {
AUDIO_MUTED_CHANGED,
audioMutedChanged,
CAMERA_FACING_MODE_CHANGED,
MEDIA_TYPE,
VIDEO_MUTED_CHANGED,
videoMutedChanged
SET_AUDIO_MUTED,
SET_CAMERA_FACING_MODE,
SET_VIDEO_MUTED,
setAudioMuted,
setVideoMuted
} from '../media';
import { MiddlewareRegistry } from '../redux';
import {
createLocalTracks,
destroyLocalTracks
} from './actions';
import { createLocalTracks, destroyLocalTracks } from './actions';
import { TRACK_UPDATED } from './actionTypes';
import {
getLocalTrack,
setTrackMuted
} from './functions';
import { getLocalTrack, setTrackMuted } from './functions';
/**
* Middleware that captures LIB_INITIALIZED and LIB_DISPOSED actions
@@ -32,19 +23,6 @@ import {
*/
MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
case AUDIO_MUTED_CHANGED:
_mutedChanged(store, action, MEDIA_TYPE.AUDIO);
break;
case CAMERA_FACING_MODE_CHANGED:
store.dispatch(
createLocalTracks({
devices: [ MEDIA_TYPE.VIDEO ],
facingMode: action.cameraFacingMode
})
);
break;
case LIB_INITIALIZED:
store.dispatch(createLocalTracks());
break;
@@ -53,12 +31,25 @@ MiddlewareRegistry.register(store => next => action => {
store.dispatch(destroyLocalTracks());
break;
case SET_AUDIO_MUTED:
_setMuted(store, action, MEDIA_TYPE.AUDIO);
break;
case SET_CAMERA_FACING_MODE:
store.dispatch(
createLocalTracks({
devices: [ MEDIA_TYPE.VIDEO ],
facingMode: action.cameraFacingMode
})
);
break;
case SET_VIDEO_MUTED:
_setMuted(store, action, MEDIA_TYPE.VIDEO);
break;
case TRACK_UPDATED:
return _trackUpdated(store, next, action);
case VIDEO_MUTED_CHANGED:
_mutedChanged(store, action, MEDIA_TYPE.VIDEO);
break;
}
return next(action);
@@ -91,7 +82,7 @@ function _getLocalTrack(store, mediaType) {
* @private
* @returns {void}
*/
function _mutedChanged(store, action, mediaType) {
function _setMuted(store, action, mediaType) {
const localTrack = _getLocalTrack(store, mediaType);
localTrack && setTrackMuted(localTrack.jitsiTrack, action.muted);
@@ -145,10 +136,10 @@ function _trackUpdated(store, next, action) {
if (oldMuted !== newMuted) {
switch (mediaType) {
case MEDIA_TYPE.AUDIO:
store.dispatch(audioMutedChanged(newMuted));
store.dispatch(setAudioMuted(newMuted));
break;
case MEDIA_TYPE.VIDEO:
store.dispatch(videoMutedChanged(newMuted));
store.dispatch(setVideoMuted(newMuted));
break;
}
}

View File

@@ -3,8 +3,8 @@ import { connect as reactReduxConnect } from 'react-redux';
import { connect, disconnect } from '../../base/connection';
import { Container } from '../../base/react';
import { FilmStrip } from '../../filmStrip';
import { LargeVideo } from '../../largeVideo';
import { FilmStrip } from '../../film-strip';
import { LargeVideo } from '../../large-video';
import { RoomLockPrompt } from '../../room-lock';
import { Toolbar } from '../../toolbar';

View File

@@ -1,9 +1,10 @@
/* global $, APP, interfaceConfig */
/* global $, APP */
import React, { Component } from 'react';
import { connect as reactReduxConnect } from 'react-redux';
import { connect, disconnect } from '../../base/connection';
import { Watermarks } from '../../base/react';
/**
* For legacy reasons, inline style for display none.
@@ -53,34 +54,6 @@ class Conference extends Component {
this.props.dispatch(disconnect());
}
/**
* Initializes Conference component instance.
*
* @param {Object} props - The read-only properties with which the new
* instance is to be initialized.
*/
constructor(props) {
super(props);
const showBrandWatermark = interfaceConfig.SHOW_BRAND_WATERMARK;
const showJitsiWatermark = interfaceConfig.SHOW_JITSI_WATERMARK;
const showJitsiWatermarkForGuest
= interfaceConfig.SHOW_WATERMARK_FOR_GUESTS;
this.state = {
...this.state,
showBrandWatermark,
showJitsiWatermark,
showJitsiWatermarkForGuest,
brandWatermarkLink:
showBrandWatermark ? interfaceConfig.BRAND_WATERMARK_LINK : '',
jitsiWatermarkLink:
showJitsiWatermark || showJitsiWatermarkForGuest
? interfaceConfig.JITSI_WATERMARK_LINK : '',
showPoweredBy: interfaceConfig.SHOW_POWERED_BY
};
}
/**
* Implements React's {@link Component#render()}.
*
@@ -123,15 +96,9 @@ class Conference extends Component {
<div id = 'sharedVideoIFrame' />
</div>
<div id = 'etherpad' />
{
this._renderJitsiWatermark()
}
{
this._renderBrandWatermark()
}
{
this._renderPoweredBy()
}
<Watermarks />
<div id = 'dominantSpeaker'>
<div className = 'dynamic-shadow' />
<img
@@ -195,69 +162,6 @@ class Conference extends Component {
</div>
);
}
/**
* Method that returns brand watermark element if it is enabled.
*
* @returns {ReactElement|null}
* @private
*/
_renderBrandWatermark() {
if (this.state.showBrandWatermark) {
return (
<a
href = { this.state.brandWatermarkLink }
target = '_new'>
<div className = 'watermark rightwatermark' />
</a>
);
}
return null;
}
/**
* Method that returns jitsi watermark element if it is enabled.
*
* @returns {ReactElement|null}
* @private
*/
_renderJitsiWatermark() {
if (this.state.showJitsiWatermark
|| (APP.tokenData.isGuest
&& this.state.showJitsiWatermarkForGuest)) {
return (
<a
href = { this.state.jitsiWatermarkLink }
target = '_new'>
<div className = 'watermark leftwatermark' />
</a>
);
}
return null;
}
/**
* Renders powered by block if it is enabled.
*
* @returns {ReactElement|null}
* @private
*/
_renderPoweredBy() {
if (this.state.showPoweredBy) {
return (
<a
className = 'poweredby hide'
href = 'http://jitsi.org'
target = '_new'>
<span data-i18n = 'poweredby' /> jitsi.org
</a>
);
}
return null;
}
}
export default reactReduxConnect()(Conference);

View File

@@ -1,14 +1,8 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import {
Audio,
MEDIA_TYPE
} from '../../base/media';
import {
PARTICIPANT_ROLE,
pinParticipant
} from '../../base/participants';
import { Audio, MEDIA_TYPE } from '../../base/media';
import { PARTICIPANT_ROLE, pinParticipant } from '../../base/participants';
import { Container } from '../../base/react';
import { getTrackByMediaTypeAndParticipant } from '../../base/tracks';
import { ParticipantView } from '../../conference';
@@ -148,10 +142,10 @@ class Thumbnail extends Component {
* }}
*/
function mapStateToProps(state, ownProps) {
// We need read-only access to the state of features/largeVideo so that the
// We need read-only access to the state of features/large-video so that the
// film strip doesn't render the video of the participant who is rendered on
// the stage i.e. as a large video.
const largeVideo = state['features/largeVideo'];
const largeVideo = state['features/large-video'];
const tracks = state['features/base/tracks'];
const id = ownProps.participant.id;
const audioTrack

View File

@@ -0,0 +1,12 @@
import { Symbol } from '../base/react';
/**
* Action to select the participant to be displayed in LargeVideo.
*
* {
* type: SELECT_LARGE_VIDEO_PARTICIPANT,
* participantId: (string|undefined)
* }
*/
export const SELECT_LARGE_VIDEO_PARTICIPANT
= Symbol('SELECT_LARGE_VIDEO_PARTICIPANT');

View File

@@ -1,14 +1,11 @@
import { _handleParticipantError } from '../base/conference';
import {
MEDIA_TYPE,
VIDEO_TYPE
} from '../base/media';
import { MEDIA_TYPE, VIDEO_TYPE } from '../base/media';
import {
getLocalVideoTrack,
getTrackByMediaTypeAndParticipant
} from '../base/tracks';
import { LARGE_VIDEO_PARTICIPANT_CHANGED } from './actionTypes';
import { SELECT_LARGE_VIDEO_PARTICIPANT } from './actionTypes';
import './middleware';
import './reducer';
@@ -23,7 +20,7 @@ export function selectParticipant() {
const conference = state['features/base/conference'].conference;
if (conference) {
const largeVideo = state['features/largeVideo'];
const largeVideo = state['features/large-video'];
const tracks = state['features/base/tracks'];
const id = largeVideo.participantId;
@@ -48,7 +45,7 @@ export function selectParticipant() {
/**
* Action to select the participant to be displayed in LargeVideo based on a
* variety of factors: if there is a dominant or pinned speaker, or if there are
* remote tracks etc.
* remote tracks, etc.
*
* @returns {Function}
*/
@@ -56,11 +53,11 @@ export function selectParticipantInLargeVideo() {
return (dispatch, getState) => {
const state = getState();
const participantId = _electParticipantInLargeVideo(state);
const largeVideo = state['features/largeVideo'];
const largeVideo = state['features/large-video'];
if (participantId !== largeVideo.participantId) {
dispatch({
type: LARGE_VIDEO_PARTICIPANT_CHANGED,
type: SELECT_LARGE_VIDEO_PARTICIPANT,
participantId
});

View File

@@ -52,7 +52,7 @@ class LargeVideo extends Component {
*/
function mapStateToProps(state) {
return {
_participantId: state['features/largeVideo'].participantId
_participantId: state['features/large-video'].participantId
};
}

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