mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-01-09 16:20:19 +00:00
Compare commits
139 Commits
android-sd
...
4166
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a31f3c0c76 | ||
|
|
af39186a5f | ||
|
|
d4d1d0aa70 | ||
|
|
3a88f4939c | ||
|
|
fe221fe4be | ||
|
|
1caaa47f5e | ||
|
|
a2c4d17e4d | ||
|
|
ce1de9e1e7 | ||
|
|
3e7abf3da0 | ||
|
|
8b4f1789a6 | ||
|
|
444e2b90df | ||
|
|
7de88995a5 | ||
|
|
f0c6e934ce | ||
|
|
78b01d2c97 | ||
|
|
bf60be1654 | ||
|
|
5202a7e5b8 | ||
|
|
2af0c0ba17 | ||
|
|
fbb6486b5f | ||
|
|
a113151563 | ||
|
|
470fda3467 | ||
|
|
edea6316ab | ||
|
|
adac9ee5f8 | ||
|
|
af8bd876e6 | ||
|
|
403c4a7ee7 | ||
|
|
21fe3c87a6 | ||
|
|
6ddac3bddf | ||
|
|
663a65ad81 | ||
|
|
5977f09202 | ||
|
|
6be2a8575f | ||
|
|
0d14e2fa5c | ||
|
|
1e0669d33b | ||
|
|
d69c2c84d7 | ||
|
|
0ea7a31b08 | ||
|
|
6284e5fab3 | ||
|
|
647852bd82 | ||
|
|
4e0d6e56bc | ||
|
|
c02763a29e | ||
|
|
0b8ec5a342 | ||
|
|
1a4be30ea1 | ||
|
|
d53d6e5fa8 | ||
|
|
93b05d13c3 | ||
|
|
79f4531bd2 | ||
|
|
5348fa19c8 | ||
|
|
b25319fd2e | ||
|
|
63ca419e76 | ||
|
|
393fb692ca | ||
|
|
735b686b98 | ||
|
|
0598e7369b | ||
|
|
8c30e43b5f | ||
|
|
75c836c70c | ||
|
|
70d8fe91c3 | ||
|
|
c6d5e103f5 | ||
|
|
7f1f92cdf0 | ||
|
|
8c02ba5ee9 | ||
|
|
5591144693 | ||
|
|
fa43539718 | ||
|
|
7e0a36e88e | ||
|
|
532dadb245 | ||
|
|
55051cc203 | ||
|
|
4975f15345 | ||
|
|
2e2d40c1d0 | ||
|
|
c08638da51 | ||
|
|
9525cab60f | ||
|
|
21d5c895fc | ||
|
|
305a63e8f9 | ||
|
|
2fef06772b | ||
|
|
b2895b7095 | ||
|
|
41dc14d30c | ||
|
|
2ddfead4f5 | ||
|
|
d55b49b2c3 | ||
|
|
64d74852e0 | ||
|
|
7c4c8384fd | ||
|
|
262e855260 | ||
|
|
3f679407a9 | ||
|
|
4faeb84d2e | ||
|
|
eed5e31ec9 | ||
|
|
4b1d8ba877 | ||
|
|
3043f50ce3 | ||
|
|
b7f1f3c659 | ||
|
|
07f64d94c0 | ||
|
|
76e1217439 | ||
|
|
591ea0a44a | ||
|
|
24052e9f9a | ||
|
|
38b8772af0 | ||
|
|
5fdb7c176c | ||
|
|
a8da6d4095 | ||
|
|
01fc098d4b | ||
|
|
b50b30e3eb | ||
|
|
1b8e5d0244 | ||
|
|
908712b96f | ||
|
|
a41bda73ff | ||
|
|
75ea0070e2 | ||
|
|
65a8091e53 | ||
|
|
7fea8e2e6c | ||
|
|
d388a7bd3c | ||
|
|
a48aa2b999 | ||
|
|
b3f16926d4 | ||
|
|
f646bc7a7a | ||
|
|
e90b60d661 | ||
|
|
bdd129b9a2 | ||
|
|
4c635a2a63 | ||
|
|
2b526557e4 | ||
|
|
eee1f50ed2 | ||
|
|
e9562adddf | ||
|
|
8accd9e433 | ||
|
|
caabdadf19 | ||
|
|
062bc13d4f | ||
|
|
a56e451536 | ||
|
|
acbf641fb4 | ||
|
|
a18fd1cdb3 | ||
|
|
9be78c60eb | ||
|
|
a45cbf41ef | ||
|
|
5b53232964 | ||
|
|
d4d4490aa9 | ||
|
|
0fd0897531 | ||
|
|
360383440e | ||
|
|
1a40672427 | ||
|
|
1ffd75c0a6 | ||
|
|
77d38731e9 | ||
|
|
13f76c2cce | ||
|
|
9ad87f3706 | ||
|
|
eea8fef044 | ||
|
|
c2cb4ea6b6 | ||
|
|
d6cf0c0afd | ||
|
|
f5faf5bbaa | ||
|
|
363982fad4 | ||
|
|
62f47d5b87 | ||
|
|
223e8560ca | ||
|
|
2085851179 | ||
|
|
47bc6f0470 | ||
|
|
c5686386fa | ||
|
|
e1cededb76 | ||
|
|
268dc33324 | ||
|
|
baaf55a2ab | ||
|
|
a8252103ea | ||
|
|
b0ab51af90 | ||
|
|
69b20cd945 | ||
|
|
8bb0141c1a | ||
|
|
169906f4cb |
50
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
50
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
@@ -4,25 +4,45 @@ about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
*This Issue tracker is only for reporting bugs and tracking code related issues.*
|
||||
<!--
|
||||
|
||||
Before posting, please make sure you check community.jitsi.org to see if the same or similar bugs have already been discussed.
|
||||
General questions, installation help, and feature requests can also be posted to community.jitsi.org.
|
||||
This issue tracker is only for reporting bugs and tracking issues related to the source code.
|
||||
|
||||
## Description
|
||||
---
|
||||
Before posting, please make sure to check if the same or similar bugs have already been discussed: https://github.com/jitsi/jitsi-meet/issues
|
||||
|
||||
## Current behavior
|
||||
---
|
||||
General questions regarding usage, installation, etc. should be posted at https://community.jitsi.org. They will be closed if posted here.
|
||||
|
||||
## Expected Behavior
|
||||
---
|
||||
-->
|
||||
|
||||
## Possible Solution
|
||||
---
|
||||
### Description:
|
||||
|
||||
## Steps to reproduce
|
||||
---
|
||||
<!-- Please describe the bug clearly and concisely. -->
|
||||
|
||||
# Environment details
|
||||
---
|
||||
### Steps to reproduce:
|
||||
|
||||
1. <!-- Open '...' -->
|
||||
2. <!-- Click on '...' -->
|
||||
3. <!-- and so on... -->
|
||||
|
||||
### Expected behavior:
|
||||
|
||||
<!-- Please describe what should happen. -->
|
||||
|
||||
### Actual behavior:
|
||||
|
||||
<!-- Please describe what actually happens. -->
|
||||
<!-- Please attach screenshot if possible. -->
|
||||
|
||||
### Server information:
|
||||
|
||||
- Jitsi Meet version:
|
||||
- Operating System:
|
||||
|
||||
### Client information:
|
||||
|
||||
- Browser / app version:
|
||||
- Operating System:
|
||||
|
||||
### Additional information:
|
||||
|
||||
<!-- Please provide additional information about the bug, if any. -->
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/2-feature-request.md
vendored
2
.github/ISSUE_TEMPLATE/2-feature-request.md
vendored
@@ -9,7 +9,7 @@ Thank you for suggesting an idea to make Jitsi Meet better.
|
||||
|
||||
Please fill in as much of the template below as you're able.
|
||||
|
||||
Note that the ultimate decission for implementing features lies on the Jitsi team, not all feature requests shall be accepted.
|
||||
Note that the ultimate decision for implementing features lies on the Jitsi team, not all feature requests shall be accepted.
|
||||
-->
|
||||
|
||||
**Is your feature request related to a problem you are facing?**
|
||||
|
||||
@@ -27,3 +27,99 @@ in the agreement, unfortunately, we cannot accept your contribution.
|
||||
- Maintain a clean list of commits, squash them if necessary.
|
||||
- Rebase your topic branch on top of the master branch before creating the pull
|
||||
request.
|
||||
|
||||
## Coding style
|
||||
|
||||
### Comments
|
||||
|
||||
* Comments documenting the source code are required.
|
||||
|
||||
* Comments from which documentation is automatically generated are **not**
|
||||
subject to case-by-case decisions. Such comments are used, for example, on
|
||||
types and their members. Examples of tools which automatically generate
|
||||
documentation from such comments include JSDoc, Javadoc, Doxygen.
|
||||
|
||||
* Comments which are not automatically processed are strongly encouraged. They
|
||||
are subject to case-by-case decisions. Such comments are often observed in
|
||||
function bodies.
|
||||
|
||||
* Comments should be formatted as proper English sentences. Such formatting pays
|
||||
attention to, for example, capitalization and punctuation.
|
||||
|
||||
### Duplication
|
||||
|
||||
* Don't copy-paste source code. Reuse it.
|
||||
|
||||
### Formatting
|
||||
|
||||
* Line length is limited to 120 characters.
|
||||
|
||||
* Sort by alphabetical order in order to make the addition of new entities as
|
||||
easy as looking a word up in a dictionary. Otherwise, one risks duplicate
|
||||
entries (with conflicting values in the cases of key-value pairs). For
|
||||
example:
|
||||
|
||||
* Within an `import` of multiple names from a module, sort the names in
|
||||
alphabetical order. (Of course, the default name stays first as required by
|
||||
the `import` syntax.)
|
||||
|
||||
````javascript
|
||||
import {
|
||||
DOMINANT_SPEAKER_CHANGED,
|
||||
JITSI_CLIENT_CONNECTED,
|
||||
JITSI_CLIENT_CREATED,
|
||||
JITSI_CLIENT_DISCONNECTED,
|
||||
JITSI_CLIENT_ERROR,
|
||||
JITSI_CONFERENCE_JOINED,
|
||||
MODERATOR_CHANGED,
|
||||
PEER_JOINED,
|
||||
PEER_LEFT,
|
||||
RTC_ERROR
|
||||
} from './actionTypes';
|
||||
````
|
||||
|
||||
* Within a group of imports (e.g. groups of imports delimited by an empty line
|
||||
may be: third-party modules, then project modules, and eventually the
|
||||
private files of a module), sort the module names in alphabetical order.
|
||||
|
||||
````javascript
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
````
|
||||
|
||||
### Indentation
|
||||
|
||||
* Align `switch` and `case`/`default`. Don't indent the `case`/`default` more
|
||||
than its `switch`.
|
||||
|
||||
````javascript
|
||||
switch (i) {
|
||||
case 0:
|
||||
...
|
||||
break;
|
||||
default:
|
||||
...
|
||||
}
|
||||
````
|
||||
|
||||
### Naming
|
||||
|
||||
* An abstraction should have one name within the project and across multiple
|
||||
projects. For example:
|
||||
|
||||
* The instance of lib-jitsi-meet's `JitsiConnection` type should be named
|
||||
`connection` or `jitsiConnection` in jitsi-meet, not `client`.
|
||||
|
||||
* The class `ReducerRegistry` should be defined in ReducerRegistry.js and its
|
||||
imports in other files should use the same name. Don't define the class
|
||||
`Registry` in ReducerRegistry.js and then import it as `Reducers` in other
|
||||
files.
|
||||
|
||||
* The names of global constants (including ES6 module-global constants) should
|
||||
be written in uppercase with underscores to separate words. For example,
|
||||
`BACKGROUND_COLOR`.
|
||||
|
||||
* The underscore character at the beginning of a name signals that the
|
||||
respective variable, function, property is non-public i.e. private, protected,
|
||||
or internal. In contrast, the lack of an underscore at the beginning of a name
|
||||
signals public API.
|
||||
|
||||
2
Makefile
2
Makefile
@@ -21,6 +21,7 @@ compile:
|
||||
clean:
|
||||
rm -fr $(BUILD_DIR)
|
||||
|
||||
.NOTPARALLEL:
|
||||
deploy: deploy-init deploy-appbundle deploy-rnnoise-binary deploy-lib-jitsi-meet deploy-libflac deploy-css deploy-local
|
||||
|
||||
deploy-init:
|
||||
@@ -79,6 +80,7 @@ deploy-css:
|
||||
deploy-local:
|
||||
([ ! -x deploy-local.sh ] || ./deploy-local.sh)
|
||||
|
||||
.NOTPARALLEL:
|
||||
dev: deploy-init deploy-css deploy-rnnoise-binary deploy-lib-jitsi-meet deploy-libflac
|
||||
$(WEBPACK_DEV_SERVER)
|
||||
|
||||
|
||||
12
README.md
12
README.md
@@ -10,9 +10,11 @@ Jitsi Meet allows very efficient collaboration. Users can stream their desktop o
|
||||
|
||||
On the client side, no installation is necessary. You just point your browser to the URL of your deployment. This section is about installing a Jitsi Meet suite on your server and hosting your own conferencing service.
|
||||
|
||||
Installing Jitsi Meet is a simple experience. For Debian-based system, following the [quick-install](https://github.com/jitsi/jitsi-meet/blob/master/doc/quick-install.md) document, which uses the package system. You can also see a demonstration of the process in [this tutorial video](https://jitsi.org/tutorial).
|
||||
Installing Jitsi Meet is a simple experience. For Debian-based system, following the [quick install](https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-quickstart) document, which uses the package system. You can also see a demonstration of the process in [this tutorial video](https://jitsi.org/tutorial).
|
||||
|
||||
For other systems, or if you wish to install all components manually, see the [detailed manual installation instructions](https://github.com/jitsi/jitsi-meet/blob/master/doc/manual-install.md).
|
||||
For other systems, or if you wish to install all components manually, see the [detailed manual installation instructions](https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-manual).
|
||||
|
||||
Installation with Docker is also available. Please see the [instruction](https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-docker).
|
||||
|
||||
## Download
|
||||
|
||||
@@ -46,9 +48,13 @@ You can also sign up for our open beta testing here:
|
||||
* [Android](https://play.google.com/apps/testing/org.jitsi.meet)
|
||||
* [iOS](https://testflight.apple.com/join/isy6ja7S)
|
||||
|
||||
## Release notes
|
||||
|
||||
Release notes for Jitsi Meet are maintained on [this repository](https://github.com/jitsi/jitsi-meet-release-notes).
|
||||
|
||||
## Development
|
||||
|
||||
For web development see [here](doc/development.md), and for mobile see [here](doc/mobile.md).
|
||||
For web development see [here](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-web), and for mobile see [here](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-mobile).
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
@@ -1,380 +1,3 @@
|
||||
# Jitsi Meet SDK for Android
|
||||
|
||||
## Sample applications using the SDK
|
||||
|
||||
If you want to see how easy integrating the Jitsi Meet SDK into a native application is, take a look at the
|
||||
[sample applications repository](https://github.com/jitsi/jitsi-meet-sdk-samples).
|
||||
|
||||
## Build your own, or use a pre-build SDK artifacts/binaries
|
||||
|
||||
Jitsi conveniently provides a pre-build SDK artifacts/binaries in its Maven repository. When you do not require any
|
||||
modification to the SDK itself or any of its dependencies, it's suggested to use the pre-build SDK. This avoids the
|
||||
complexity of building and installing your own SDK artifacts/binaries.
|
||||
|
||||
### Use pre-build SDK artifacts/binaries
|
||||
|
||||
In your project, add the Maven repository
|
||||
`https://github.com/jitsi/jitsi-maven-repository/raw/master/releases` and the
|
||||
dependency `org.jitsi.react:jitsi-meet-sdk` into your `build.gradle` files.
|
||||
|
||||
The repository typically goes into the `build.gradle` file in the root of your project:
|
||||
|
||||
```gradle
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
maven {
|
||||
url "https://github.com/jitsi/jitsi-maven-repository/raw/master/releases"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Dependency definitions belong in the individual module `build.gradle` files:
|
||||
|
||||
```gradle
|
||||
dependencies {
|
||||
// (other dependencies)
|
||||
implementation ('org.jitsi.react:jitsi-meet-sdk:2.+') { transitive = true }
|
||||
}
|
||||
```
|
||||
|
||||
### Build and use your own SDK artifacts/binaries
|
||||
|
||||
<details>
|
||||
<summary>Show building instructions</summary>
|
||||
|
||||
Start by making sure that your development environment [is set up correctly](https://github.com/jitsi/jitsi-meet/blob/master/doc/mobile.md).
|
||||
|
||||
A note on dependencies: Apart from the SDK, Jitsi also publishes a binary Maven artifact for some of the SDK dependencies (that are not otherwise publicly available) to the Jitsi Maven repository. When you're planning to use a SDK that is built from source, you'll likely use a version of the source code that is newer (or at least _different_) than the version of the source that was used to create the binary SDK artifact. As a consequence, the dependencies that your project will need, might also be different from those that are published in the Jitsi Maven repository. This might lead to build problems, caused by dependencies that are unavailable.
|
||||
|
||||
If you want to use a SDK that is built from source, you will likely benefit from composing a local Maven repository that contains these dependencies. The text below describes how you create a repository that includes both the SDK as well as these dependencies. For illustration purposes, we'll define the location of this local Maven repository as `/tmp/repo`
|
||||
|
||||
In source code form, the Android SDK dependencies are locked/pinned by package.json and package-lock.json of the Jitsi Meet project. To obtain the data, execute NPM in the jitsi-meet project directory:
|
||||
|
||||
npm install
|
||||
|
||||
This will pull in the dependencies in either binary format, or in source code format, somewhere under /node_modules/
|
||||
|
||||
Third-party React Native _modules_, which Jitsi Meet SDK for Android depends on, are download by NPM in source code
|
||||
or binary form. These need to be assembled into Maven artifacts, and then published to your local Maven repository.
|
||||
A script is provided to facilitate this. From the root of the jitsi-meet project repository, run:
|
||||
|
||||
./android/scripts/release-sdk.sh /tmp/repo
|
||||
|
||||
This will build and publish the SDK, and all of its dependencies to the specified Maven repository (`/tmp/repo`) in
|
||||
this example.
|
||||
|
||||
You're now ready to use the artifacts. In _your_ project, add the Maven repository that you used above (`/tmp/repo`) into your top-level `build.gradle` file:
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
maven { url "file:/tmp/repo" }
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
You can use your local repository to replace the Jitsi repository (`maven { url "https://github.com/jitsi/jitsi-maven-repository/raw/master/releases" }`) when you published _all_ subprojects. If you didn't do that, you'll have to add both repositories. Make sure your local repository is listed first!
|
||||
|
||||
Then, define the dependency `org.jitsi.react:jitsi-meet-sdk` into the `build.gradle` file of your module:
|
||||
|
||||
implementation ('org.jitsi.react:jitsi-meet-sdk:+') { transitive = true }
|
||||
|
||||
Note that there should not be a need to explicitly add the other dependencies, as they will be pulled in as transitive
|
||||
dependencies of `jitsi-meet-sdk`.
|
||||
|
||||
</details>
|
||||
|
||||
## Using the API
|
||||
|
||||
Jitsi Meet SDK is an Android library which embodies the whole Jitsi Meet
|
||||
experience and makes it reusable by third-party apps.
|
||||
|
||||
First, add Java 1.8 compatibility support to your project by adding the
|
||||
following lines into your `build.gradle` file:
|
||||
|
||||
```
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
```
|
||||
|
||||
To get started, extends your `android.app.Activity` from
|
||||
`org.jitsi.meet.sdk.JitsiMeetActivity`:
|
||||
|
||||
```java
|
||||
package org.jitsi.example;
|
||||
|
||||
import org.jitsi.meet.sdk.JitsiMeetActivity;
|
||||
|
||||
public class MainActivity extends JitsiMeetActivity {
|
||||
}
|
||||
```
|
||||
|
||||
Alternatively, you can use the `org.jitsi.meet.sdk.JitsiMeetView` class which
|
||||
extends `android.view.View`.
|
||||
|
||||
Note that this should only be needed when `JitsiMeetActivity` cannot be used for
|
||||
some reason. Extending `JitsiMeetView` requires manual wiring of the view to
|
||||
the activity, using a lot of boilerplate code. Using the Activity instead of the
|
||||
View is strongly recommended.
|
||||
|
||||
<details>
|
||||
<summary>Show example</summary>
|
||||
|
||||
```java
|
||||
package org.jitsi.example;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
import org.jitsi.meet.sdk.JitsiMeetView;
|
||||
import org.jitsi.meet.sdk.ReactActivityLifecycleCallbacks;
|
||||
|
||||
// Example
|
||||
//
|
||||
public class MainActivity extends FragmentActivity implements JitsiMeetActivityInterface {
|
||||
private JitsiMeetView view;
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(
|
||||
int requestCode,
|
||||
int resultCode,
|
||||
Intent data) {
|
||||
JitsiMeetActivityDelegate.onActivityResult(
|
||||
this, requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
JitsiMeetActivityDelegate.onBackPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
view = new JitsiMeetView(this);
|
||||
JitsiMeetConferenceOptions options = new JitsiMeetConferenceOptions.Builder()
|
||||
.setRoom("https://meet.jit.si/test123")
|
||||
.build();
|
||||
view.join(options);
|
||||
|
||||
setContentView(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
view.dispose();
|
||||
view = null;
|
||||
|
||||
JitsiMeetActivityDelegate.onHostDestroy(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewIntent(Intent intent) {
|
||||
JitsiMeetActivityDelegate.onNewIntent(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(
|
||||
final int requestCode,
|
||||
final String[] permissions,
|
||||
final int[] grantResults) {
|
||||
JitsiMeetActivityDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
JitsiMeetActivityDelegate.onHostResume(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
||||
JitsiMeetActivityDelegate.onHostPause(this);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### JitsiMeetActivity
|
||||
|
||||
This class encapsulates a high level API in the form of an Android `FragmentActivity`
|
||||
which displays a single `JitsiMeetView`. You can pass a URL as a `ACTION_VIEW`
|
||||
on the Intent when starting it and it will join the conference, and will be
|
||||
automatically terminated (finish() will be called on the activity) when the
|
||||
conference ends or fails.
|
||||
|
||||
### JitsiMeetView
|
||||
|
||||
The `JitsiMeetView` class is the core of Jitsi Meet SDK. It's designed to
|
||||
display a Jitsi Meet conference (or a welcome page).
|
||||
|
||||
#### join(options)
|
||||
|
||||
Joins the conference specified by the given `JitsiMeetConferenceOptions`.
|
||||
|
||||
#### leave()
|
||||
|
||||
Leaves the currently active conference. If the welcome page is enabled it will
|
||||
go back to it, otherwise a black window will be shown.
|
||||
|
||||
#### dispose()
|
||||
|
||||
Releases all resources associated with this view. This method MUST be called
|
||||
when the Activity holding this view is going to be destroyed, usually in the
|
||||
`onDestroy()` method.
|
||||
|
||||
#### getListener()
|
||||
|
||||
Returns the `JitsiMeetViewListener` instance attached to the view.
|
||||
|
||||
#### setListener(listener)
|
||||
|
||||
Sets the given listener (class implementing the `JitsiMeetViewListener`
|
||||
interface) on the view.
|
||||
|
||||
### JitsiMeetConferenceOptions
|
||||
|
||||
This object encapsulates all the options that can be tweaked when joining
|
||||
a conference.
|
||||
|
||||
Example:
|
||||
|
||||
```java
|
||||
JitsiMeetConferenceOptions options = new JitsiMeetConferenceOptions.Builder()
|
||||
.setServerURL(new URL("https://meet.jit.si"))
|
||||
.setRoom("test123")
|
||||
.setAudioMuted(false)
|
||||
.setVideoMuted(false)
|
||||
.setAudioOnly(false)
|
||||
.setWelcomePageEnabled(false)
|
||||
.build();
|
||||
```
|
||||
|
||||
See the `JitsiMeetConferenceOptions` implementation for all available options.
|
||||
|
||||
### JitsiMeetActivityDelegate
|
||||
|
||||
This class handles the interaction between `JitsiMeetView` and its enclosing
|
||||
`Activity`. Generally this shouldn't be consumed by users, because they'd be
|
||||
using `JitsiMeetActivity` instead, which is already completely integrated.
|
||||
|
||||
All its methods are static.
|
||||
|
||||
#### onActivityResult(...)
|
||||
|
||||
Helper method to handle results of auxiliary activities launched by the SDK.
|
||||
Should be called from the activity method of the same name.
|
||||
|
||||
#### onBackPressed()
|
||||
|
||||
Helper method which should be called from the activity's `onBackPressed` method.
|
||||
If this function returns `true`, it means the action was handled and thus no
|
||||
extra processing is required; otherwise the app should call the parent's
|
||||
`onBackPressed` method.
|
||||
|
||||
#### onHostDestroy(...)
|
||||
|
||||
Helper method which should be called from the activity's `onDestroy` method.
|
||||
|
||||
#### onHostResume(...)
|
||||
|
||||
Helper method which should be called from the activity's `onResume` or `onStop`
|
||||
method.
|
||||
|
||||
#### onHostStop(...)
|
||||
|
||||
Helper method which should be called from the activity's `onSstop` method.
|
||||
|
||||
#### onNewIntent(...)
|
||||
|
||||
Helper method for integrating the *deep linking* functionality. If your app's
|
||||
activity is launched in "singleTask" mode this method should be called from the
|
||||
activity's `onNewIntent` method.
|
||||
|
||||
#### onRequestPermissionsResult(...)
|
||||
|
||||
Helper method to handle permission requests inside the SDK. It should be called
|
||||
from the activity method of the same name.
|
||||
|
||||
#### onUserLeaveHint()
|
||||
|
||||
Helper method for integrating automatic Picture-in-Picture. It should be called
|
||||
from the activity's `onUserLeaveHint` method.
|
||||
|
||||
This is a static method.
|
||||
|
||||
#### JitsiMeetViewListener
|
||||
|
||||
`JitsiMeetViewListener` provides an interface apps can implement to listen to
|
||||
the state of the Jitsi Meet conference displayed in a `JitsiMeetView`.
|
||||
|
||||
#### onConferenceJoined
|
||||
|
||||
Called when a conference was joined.
|
||||
|
||||
The `data` `Map` contains a "url" key with the conference URL.
|
||||
|
||||
#### onConferenceTerminated
|
||||
|
||||
Called when a conference was terminated either by user choice or due to a
|
||||
failure.
|
||||
|
||||
The `data` `Map` contains an "error" key with the error and a "url" key
|
||||
with the conference URL. If the conference finished gracefully no `error`
|
||||
key will be present.
|
||||
|
||||
#### onConferenceWillJoin
|
||||
|
||||
Called before a conference is joined.
|
||||
|
||||
The `data` `Map` contains a "url" key with the conference URL.
|
||||
|
||||
## ProGuard rules
|
||||
|
||||
When using the SDK on a project some proguard rules have to be added in order
|
||||
to avoid necessary code being stripped. Add the following to your project's
|
||||
rules file: https://github.com/jitsi/jitsi-meet/blob/master/android/app/proguard-rules.pro
|
||||
|
||||
## Picture-in-Picture
|
||||
|
||||
`JitsiMeetView` will automatically adjust its UI when presented in a
|
||||
Picture-in-Picture style scenario, in a rectangle too small to accommodate its
|
||||
"full" UI.
|
||||
|
||||
## Dropbox integration
|
||||
|
||||
To setup the Dropbox integration, follow these steps:
|
||||
|
||||
1. Add the following to the app's AndroidManifest.xml and change `<APP_KEY>` to
|
||||
your Dropbox app key:
|
||||
```
|
||||
<activity
|
||||
android:configChanges="keyboard|orientation"
|
||||
android:launchMode="singleTask"
|
||||
android:name="com.dropbox.core.android.AuthActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:scheme="db-<APP_KEY>" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
```
|
||||
|
||||
2. Add the following to the app's strings.xml and change `<APP_KEY>` to your
|
||||
Dropbox app key:
|
||||
```
|
||||
<string name="dropbox_app_key"><APP_KEY></string>
|
||||
```
|
||||
This document has been moved to [The Handbook](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-android-sdk).
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
boolean googleServicesEnabled \
|
||||
= project.file('google-services.json').exists() && !rootProject.ext.libreBuild
|
||||
|
||||
// Crashlytics integration is done as part of Firebase now, so it gets
|
||||
// automagically activated with google-services.json
|
||||
if (googleServicesEnabled) {
|
||||
@@ -13,7 +10,7 @@ if (googleServicesEnabled) {
|
||||
// This lets us upload a new build at most every 10 seconds for the
|
||||
// next ~680 years.
|
||||
// https://stackoverflow.com/a/38643838
|
||||
def vcode = (int)(((new Date().getTime()/1000) - 1546297200) / 10)
|
||||
def vcode = (int) (((new Date().getTime() / 1000) - 1546297200) / 10)
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
@@ -143,8 +140,8 @@ gradle.projectsEvaluated {
|
||||
def targetName = variant.name.capitalize()
|
||||
|
||||
def currentRunPackagerTask = tasks.create(
|
||||
name: "run${targetName}ReactPackager",
|
||||
type: Exec) {
|
||||
name: "run${targetName}ReactPackager",
|
||||
type: Exec) {
|
||||
group = "react"
|
||||
description = "Run the React packager."
|
||||
|
||||
@@ -175,5 +172,5 @@ gradle.projectsEvaluated {
|
||||
}
|
||||
|
||||
if (googleServicesEnabled) {
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.crashlytics.android.Crashlytics;
|
||||
import com.google.firebase.dynamiclinks.FirebaseDynamicLinks;
|
||||
import io.fabric.sdk.android.Fabric;
|
||||
|
||||
import org.jitsi.meet.sdk.JitsiMeet;
|
||||
import org.jitsi.meet.sdk.JitsiMeetActivity;
|
||||
|
||||
/**
|
||||
@@ -21,7 +22,9 @@ final class GoogleServicesHelper {
|
||||
if (BuildConfig.GOOGLE_SERVICES_ENABLED) {
|
||||
Log.d(activity.getClass().getSimpleName(), "Initializing Google Services");
|
||||
|
||||
Fabric.with(activity, new Crashlytics());
|
||||
if (!JitsiMeet.isCrashReportingDisabled(activity)) {
|
||||
Fabric.with(activity, new Crashlytics());
|
||||
}
|
||||
|
||||
FirebaseDynamicLinks.getInstance().getDynamicLink(activity.getIntent())
|
||||
.addOnSuccessListener(activity, pendingDynamicLinkData -> {
|
||||
|
||||
@@ -161,6 +161,8 @@ ext {
|
||||
|
||||
// Libre build
|
||||
libreBuild = (System.env.LIBRE_BUILD ?: "false").toBoolean()
|
||||
|
||||
googleServicesEnabled = project.file('app/google-services.json').exists() && !libreBuild
|
||||
}
|
||||
|
||||
// Force the version of the Android build tools we have chosen on all
|
||||
|
||||
@@ -21,4 +21,4 @@ android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
||||
appVersion=20.3.0
|
||||
sdkVersion=2.8.2
|
||||
sdkVersion=2.9.0
|
||||
|
||||
@@ -14,11 +14,13 @@ android {
|
||||
buildTypes {
|
||||
debug {
|
||||
buildConfigField "boolean", "LIBRE_BUILD", "${rootProject.ext.libreBuild}"
|
||||
buildConfigField "boolean", "GOOGLE_SERVICES_ENABLED", "${rootProject.ext.googleServicesEnabled}"
|
||||
}
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
buildConfigField "boolean", "LIBRE_BUILD", "${rootProject.ext.libreBuild}"
|
||||
buildConfigField "boolean", "GOOGLE_SERVICES_ENABLED", "${rootProject.ext.googleServicesEnabled}"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +72,7 @@ dependencies {
|
||||
implementation project(':react-native-calendar-events')
|
||||
implementation project(':react-native-community-async-storage')
|
||||
implementation project(':react-native-community_netinfo')
|
||||
implementation project(':react-native-default-preference')
|
||||
implementation project(':react-native-immersive')
|
||||
implementation project(':react-native-keep-awake')
|
||||
implementation project(':react-native-linear-gradient')
|
||||
|
||||
@@ -66,6 +66,10 @@ class AmplitudeModule
|
||||
String android_id = sharedPreferences.getString(AMPLITUDE_DEVICE_ID_KEY, "");
|
||||
if (!TextUtils.isEmpty(android_id)) {
|
||||
Amplitude.getInstance(instanceName).setDeviceId(android_id);
|
||||
} else {
|
||||
String amplitudeId = Amplitude.getInstance(instanceName).getDeviceId();
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.putString(JITSI_PREFERENCES, amplitudeId).apply();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ class AppInfoModule
|
||||
"version",
|
||||
packageInfo == null ? "" : packageInfo.versionName);
|
||||
constants.put("LIBRE_BUILD", BuildConfig.LIBRE_BUILD);
|
||||
constants.put("GOOGLE_SERVICES_ENABLED", BuildConfig.GOOGLE_SERVICES_ENABLED);
|
||||
|
||||
return constants;
|
||||
}
|
||||
|
||||
@@ -16,11 +16,14 @@
|
||||
*/
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
|
||||
public class JitsiMeet {
|
||||
|
||||
/**
|
||||
* Default {@link JitsiMeetConferenceOptions} which will be used for all conferences. When
|
||||
* joining a conference these options will be merged with the ones passed to
|
||||
@@ -72,4 +75,10 @@ public class JitsiMeet {
|
||||
reactInstanceManager.showDevOptionsDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isCrashReportingDisabled(Context context) {
|
||||
SharedPreferences preferences = context.getSharedPreferences("jitsi-default-preferences", Context.MODE_PRIVATE);
|
||||
String value = preferences.getString("isCrashReportingDisabled", "");
|
||||
return Boolean.parseBoolean(value);
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
@@ -67,6 +68,9 @@ public class JitsiMeetActivity extends FragmentActivity
|
||||
|
||||
setContentView(R.layout.activity_jitsi_meet);
|
||||
|
||||
// Listen for conference events.
|
||||
getJitsiView().setListener(this);
|
||||
|
||||
if (!extraInitialize()) {
|
||||
initialize();
|
||||
}
|
||||
@@ -151,9 +155,6 @@ public class JitsiMeetActivity extends FragmentActivity
|
||||
}
|
||||
|
||||
protected void initialize() {
|
||||
// Listen for conference events.
|
||||
getJitsiView().setListener(this);
|
||||
|
||||
// Join the room specified by the URL the app was launched with.
|
||||
// Joining without the room option displays the welcome page.
|
||||
join(getConferenceOptions(getIntent()));
|
||||
@@ -164,6 +165,8 @@ public class JitsiMeetActivity extends FragmentActivity
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
JitsiMeetActivityDelegate.onActivityResult(this, requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
|
||||
import com.calendarevents.CalendarEventsPackage;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
import com.facebook.react.bridge.Callback;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
@@ -167,13 +166,7 @@ public class JitsiMeetActivityDelegate {
|
||||
}
|
||||
|
||||
public static void onRequestPermissionsResult(
|
||||
final int requestCode,
|
||||
final String[] permissions,
|
||||
final int[] grantResults) {
|
||||
CalendarEventsPackage.onRequestPermissionsResult(
|
||||
requestCode,
|
||||
permissions,
|
||||
grantResults);
|
||||
final int requestCode, final String[] permissions, final int[] grantResults) {
|
||||
permissionsCallback = new Callback() {
|
||||
@Override
|
||||
public void invoke(Object... args) {
|
||||
|
||||
@@ -57,22 +57,6 @@ public class JitsiMeetFragment extends Fragment {
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
JitsiMeetActivityDelegate.onActivityResult(
|
||||
getActivity(), requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
if (view != null) {
|
||||
view.dispose();
|
||||
view = null;
|
||||
}
|
||||
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
@@ -201,4 +201,10 @@ public class JitsiMeetView extends BaseReactView<JitsiMeetViewListener>
|
||||
protected void onExternalAPIEvent(String name, ReadableMap data) {
|
||||
onExternalAPIEvent(LISTENER_METHODS, name, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
dispose();
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,6 +190,7 @@ class ReactInstanceManagerHolder {
|
||||
new com.corbt.keepawake.KCKeepAwakePackage(),
|
||||
new com.facebook.react.shell.MainReactPackage(),
|
||||
new com.horcrux.svg.SvgPackage(),
|
||||
new com.kevinresol.react_native_default_preference.RNDefaultPreferencePackage(),
|
||||
new com.ocetnik.timer.BackgroundTimerPackage(),
|
||||
new com.reactnativecommunity.asyncstorage.AsyncStoragePackage(),
|
||||
new com.reactnativecommunity.netinfo.NetInfoPackage(),
|
||||
|
||||
@@ -9,6 +9,8 @@ include ':react-native-community-async-storage'
|
||||
project(':react-native-community-async-storage').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/async-storage/android')
|
||||
include ':react-native-community_netinfo'
|
||||
project(':react-native-community_netinfo').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/netinfo/android')
|
||||
include ':react-native-default-preference'
|
||||
project(':react-native-default-preference').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-default-preference/android')
|
||||
include ':react-native-google-signin'
|
||||
project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/google-signin/android')
|
||||
include ':react-native-immersive'
|
||||
@@ -24,4 +26,4 @@ project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../
|
||||
include ':react-native-webrtc'
|
||||
project(':react-native-webrtc').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webrtc/android')
|
||||
include ':react-native-webview'
|
||||
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')
|
||||
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')
|
||||
2
app.js
2
app.js
@@ -6,10 +6,10 @@ import 'jQuery-Impromptu';
|
||||
|
||||
import conference from './conference';
|
||||
import API from './modules/API';
|
||||
import UI from './modules/UI/UI';
|
||||
import keyboardshortcut from './modules/keyboardshortcut/keyboardshortcut';
|
||||
import remoteControl from './modules/remotecontrol/RemoteControl';
|
||||
import translation from './modules/translation/translation';
|
||||
import UI from './modules/UI/UI';
|
||||
|
||||
window.APP = {
|
||||
API,
|
||||
|
||||
359
conference.js
359
conference.js
@@ -1,20 +1,16 @@
|
||||
/* global $, APP, JitsiMeetJS, config, interfaceConfig */
|
||||
|
||||
import { openConnection } from './connection';
|
||||
import EventEmitter from 'events';
|
||||
import Logger from 'jitsi-meet-logger';
|
||||
|
||||
import * as JitsiMeetConferenceEvents from './ConferenceEvents';
|
||||
import { openConnection } from './connection';
|
||||
import { ENDPOINT_TEXT_MESSAGE_NAME } from './modules/API/constants';
|
||||
import AuthHandler from './modules/UI/authentication/AuthHandler';
|
||||
import Recorder from './modules/recorder/Recorder';
|
||||
|
||||
import mediaDeviceHelper from './modules/devices/mediaDeviceHelper';
|
||||
|
||||
import * as RemoteControlEvents
|
||||
from './service/remotecontrol/RemoteControlEvents';
|
||||
import UIEvents from './service/UI/UIEvents';
|
||||
import UIUtil from './modules/UI/util/UIUtil';
|
||||
import mediaDeviceHelper from './modules/devices/mediaDeviceHelper';
|
||||
import Recorder from './modules/recorder/Recorder';
|
||||
import { createTaskQueue } from './modules/util/helpers';
|
||||
import * as JitsiMeetConferenceEvents from './ConferenceEvents';
|
||||
|
||||
import {
|
||||
createDeviceChangedEvent,
|
||||
createStartSilentEvent,
|
||||
@@ -27,9 +23,6 @@ import {
|
||||
redirectToStaticPage,
|
||||
reloadWithStoredParams
|
||||
} from './react/features/app';
|
||||
|
||||
import EventEmitter from 'events';
|
||||
|
||||
import {
|
||||
AVATAR_ID_COMMAND,
|
||||
AVATAR_URL_COMMAND,
|
||||
@@ -79,7 +72,6 @@ import {
|
||||
setVideoAvailable,
|
||||
setVideoMuted
|
||||
} from './react/features/base/media';
|
||||
import { showNotification } from './react/features/notifications';
|
||||
import {
|
||||
dominantSpeakerChanged,
|
||||
getLocalParticipant,
|
||||
@@ -109,7 +101,10 @@ import {
|
||||
trackAdded,
|
||||
trackRemoved
|
||||
} from './react/features/base/tracks';
|
||||
import { getJitsiMeetGlobalNS } from './react/features/base/util';
|
||||
import {
|
||||
getBackendSafePath,
|
||||
getJitsiMeetGlobalNS
|
||||
} from './react/features/base/util';
|
||||
import { showDesktopPicker } from './react/features/desktop-picker';
|
||||
import { appendSuffix } from './react/features/display-name';
|
||||
import { setE2EEKey } from './react/features/e2ee';
|
||||
@@ -117,22 +112,42 @@ import {
|
||||
maybeOpenFeedbackDialog,
|
||||
submitFeedback
|
||||
} from './react/features/feedback';
|
||||
import { showNotification } from './react/features/notifications';
|
||||
import { mediaPermissionPromptVisibilityChanged } from './react/features/overlay';
|
||||
import { suspendDetected } from './react/features/power-monitor';
|
||||
import {
|
||||
initPrejoin,
|
||||
isPrejoinPageEnabled,
|
||||
isPrejoinPageVisible,
|
||||
replacePrejoinAudioTrack,
|
||||
replacePrejoinVideoTrack
|
||||
} from './react/features/prejoin';
|
||||
import { createRnnoiseProcessorPromise } from './react/features/rnnoise';
|
||||
import { toggleScreenshotCaptureEffect } from './react/features/screenshot-capture';
|
||||
import { setSharedVideoStatus } from './react/features/shared-video';
|
||||
import { AudioMixerEffect } from './react/features/stream-effects/audio-mixer/AudioMixerEffect';
|
||||
import { createPresenterEffect } from './react/features/stream-effects/presenter';
|
||||
import { endpointMessageReceived } from './react/features/subtitles';
|
||||
import { createRnnoiseProcessorPromise } from './react/features/rnnoise';
|
||||
import { toggleScreenshotCaptureEffect } from './react/features/screenshot-capture';
|
||||
import UIEvents from './service/UI/UIEvents';
|
||||
import * as RemoteControlEvents
|
||||
from './service/remotecontrol/RemoteControlEvents';
|
||||
|
||||
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||
const logger = Logger.getLogger(__filename);
|
||||
|
||||
const eventEmitter = new EventEmitter();
|
||||
|
||||
let room;
|
||||
let connection;
|
||||
|
||||
/**
|
||||
* The promise is used when the prejoin screen is shown.
|
||||
* While the user configures the devices the connection can be made.
|
||||
*
|
||||
* @type {Promise<Object>}
|
||||
* @private
|
||||
*/
|
||||
let _connectionPromise;
|
||||
|
||||
/**
|
||||
* This promise is used for chaining mutePresenterVideo calls in order to avoid calling GUM multiple times if it takes
|
||||
* a while to finish.
|
||||
@@ -340,6 +355,7 @@ class ConferenceConnector {
|
||||
}
|
||||
|
||||
case JitsiConferenceErrors.FOCUS_LEFT:
|
||||
case JitsiConferenceErrors.ICE_FAILED:
|
||||
case JitsiConferenceErrors.VIDEOBRIDGE_NOT_AVAILABLE:
|
||||
case JitsiConferenceErrors.OFFER_ANSWER_FAILED:
|
||||
APP.store.dispatch(conferenceWillLeave(room));
|
||||
@@ -471,28 +487,13 @@ export default {
|
||||
localVideo: null,
|
||||
|
||||
/**
|
||||
* Creates local media tracks and connects to a room. Will show error
|
||||
* dialogs in case accessing the local microphone and/or camera failed. Will
|
||||
* show guidance overlay for users on how to give access to camera and/or
|
||||
* microphone.
|
||||
* @param {string} roomName
|
||||
* @param {object} options
|
||||
* @param {boolean} options.startAudioOnly=false - if <tt>true</tt> then
|
||||
* only audio track will be created and the audio only mode will be turned
|
||||
* on.
|
||||
* @param {boolean} options.startScreenSharing=false - if <tt>true</tt>
|
||||
* should start with screensharing instead of camera video.
|
||||
* @param {boolean} options.startWithAudioMuted - will start the conference
|
||||
* without any audio tracks.
|
||||
* @param {boolean} options.startWithVideoMuted - will start the conference
|
||||
* without any video tracks.
|
||||
* @returns {Promise.<JitsiLocalTrack[], JitsiConnection>}
|
||||
* Returns an object containing a promise which resolves with the created tracks &
|
||||
* the errors resulting from that process.
|
||||
*
|
||||
* @returns {Promise<JitsiLocalTrack[]>, Object}
|
||||
*/
|
||||
createInitialLocalTracksAndConnect(roomName, options = {}) {
|
||||
let audioAndVideoError,
|
||||
audioOnlyError,
|
||||
screenSharingError,
|
||||
videoOnlyError;
|
||||
createInitialLocalTracks(options = {}) {
|
||||
const errors = {};
|
||||
const initialDevices = [ 'audio' ];
|
||||
const requestedAudio = true;
|
||||
let requestedVideo = false;
|
||||
@@ -524,7 +525,7 @@ export default {
|
||||
// FIXME is there any simpler way to rewrite this spaghetti below ?
|
||||
if (options.startScreenSharing) {
|
||||
tryCreateLocalTracks = this._createDesktopTrack()
|
||||
.then(desktopStream => {
|
||||
.then(([ desktopStream ]) => {
|
||||
if (!requestedAudio) {
|
||||
return [ desktopStream ];
|
||||
}
|
||||
@@ -533,21 +534,21 @@ export default {
|
||||
.then(([ audioStream ]) =>
|
||||
[ desktopStream, audioStream ])
|
||||
.catch(error => {
|
||||
audioOnlyError = error;
|
||||
errors.audioOnlyError = error;
|
||||
|
||||
return [ desktopStream ];
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
logger.error('Failed to obtain desktop stream', error);
|
||||
screenSharingError = error;
|
||||
errors.screenSharingError = error;
|
||||
|
||||
return requestedAudio
|
||||
? createLocalTracksF({ devices: [ 'audio' ] }, true)
|
||||
: [];
|
||||
})
|
||||
.catch(error => {
|
||||
audioOnlyError = error;
|
||||
errors.audioOnlyError = error;
|
||||
|
||||
return [];
|
||||
});
|
||||
@@ -560,16 +561,16 @@ export default {
|
||||
if (requestedAudio && requestedVideo) {
|
||||
|
||||
// Try audio only...
|
||||
audioAndVideoError = err;
|
||||
errors.audioAndVideoError = err;
|
||||
|
||||
return (
|
||||
createLocalTracksF({ devices: [ 'audio' ] }, true));
|
||||
} else if (requestedAudio && !requestedVideo) {
|
||||
audioOnlyError = err;
|
||||
errors.audioOnlyError = err;
|
||||
|
||||
return [];
|
||||
} else if (requestedVideo && !requestedAudio) {
|
||||
videoOnlyError = err;
|
||||
errors.videoOnlyError = err;
|
||||
|
||||
return [];
|
||||
}
|
||||
@@ -580,7 +581,7 @@ export default {
|
||||
if (!requestedAudio) {
|
||||
logger.error('The impossible just happened', err);
|
||||
}
|
||||
audioOnlyError = err;
|
||||
errors.audioOnlyError = err;
|
||||
|
||||
// Try video only...
|
||||
return requestedVideo
|
||||
@@ -592,7 +593,7 @@ export default {
|
||||
if (!requestedVideo) {
|
||||
logger.error('The impossible just happened', err);
|
||||
}
|
||||
videoOnlyError = err;
|
||||
errors.videoOnlyError = err;
|
||||
|
||||
return [];
|
||||
});
|
||||
@@ -603,8 +604,44 @@ export default {
|
||||
// cases, when auth is rquired, for instance, that won't happen until
|
||||
// the user inputs their credentials, but the dialog would be
|
||||
// overshadowed by the overlay.
|
||||
tryCreateLocalTracks.then(() =>
|
||||
APP.store.dispatch(mediaPermissionPromptVisibilityChanged(false)));
|
||||
tryCreateLocalTracks.then(tracks => {
|
||||
APP.store.dispatch(mediaPermissionPromptVisibilityChanged(false));
|
||||
|
||||
return tracks;
|
||||
});
|
||||
|
||||
return {
|
||||
tryCreateLocalTracks,
|
||||
errors
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates local media tracks and connects to a room. Will show error
|
||||
* dialogs in case accessing the local microphone and/or camera failed. Will
|
||||
* show guidance overlay for users on how to give access to camera and/or
|
||||
* microphone.
|
||||
* @param {string} roomName
|
||||
* @param {object} options
|
||||
* @param {boolean} options.startAudioOnly=false - if <tt>true</tt> then
|
||||
* only audio track will be created and the audio only mode will be turned
|
||||
* on.
|
||||
* @param {boolean} options.startScreenSharing=false - if <tt>true</tt>
|
||||
* should start with screensharing instead of camera video.
|
||||
* @param {boolean} options.startWithAudioMuted - will start the conference
|
||||
* without any audio tracks.
|
||||
* @param {boolean} options.startWithVideoMuted - will start the conference
|
||||
* without any video tracks.
|
||||
* @returns {Promise.<JitsiLocalTrack[], JitsiConnection>}
|
||||
*/
|
||||
createInitialLocalTracksAndConnect(roomName, options = {}) {
|
||||
const { tryCreateLocalTracks, errors } = this.createInitialLocalTracks(options);
|
||||
const {
|
||||
audioAndVideoError,
|
||||
audioOnlyError,
|
||||
screenSharingError,
|
||||
videoOnlyError
|
||||
} = errors;
|
||||
|
||||
return Promise.all([ tryCreateLocalTracks, connect(roomName) ])
|
||||
.then(([ tracks, con ]) => {
|
||||
@@ -636,105 +673,132 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
startConference(con, tracks) {
|
||||
tracks.forEach(track => {
|
||||
if ((track.isAudioTrack() && this.isLocalAudioMuted())
|
||||
|| (track.isVideoTrack() && this.isLocalVideoMuted())) {
|
||||
const mediaType = track.getType();
|
||||
|
||||
sendAnalytics(
|
||||
createTrackMutedEvent(mediaType, 'initial mute'));
|
||||
logger.log(`${mediaType} mute: initially muted.`);
|
||||
track.mute();
|
||||
}
|
||||
});
|
||||
logger.log(`Initialized with ${tracks.length} local tracks`);
|
||||
|
||||
this._localTracksInitialized = true;
|
||||
con.addEventListener(JitsiConnectionEvents.CONNECTION_FAILED, _connectionFailedHandler);
|
||||
APP.connection = connection = con;
|
||||
|
||||
// Desktop sharing related stuff:
|
||||
this.isDesktopSharingEnabled
|
||||
= JitsiMeetJS.isDesktopSharingEnabled();
|
||||
eventEmitter.emit(JitsiMeetConferenceEvents.DESKTOP_SHARING_ENABLED_CHANGED, this.isDesktopSharingEnabled);
|
||||
|
||||
APP.store.dispatch(
|
||||
setDesktopSharingEnabled(this.isDesktopSharingEnabled));
|
||||
|
||||
this._createRoom(tracks);
|
||||
APP.remoteControl.init();
|
||||
|
||||
// if user didn't give access to mic or camera or doesn't have
|
||||
// them at all, we mark corresponding toolbar buttons as muted,
|
||||
// so that the user can try unmute later on and add audio/video
|
||||
// to the conference
|
||||
if (!tracks.find(t => t.isAudioTrack())) {
|
||||
this.setAudioMuteStatus(true);
|
||||
}
|
||||
|
||||
if (!tracks.find(t => t.isVideoTrack())) {
|
||||
this.setVideoMuteStatus(true);
|
||||
}
|
||||
|
||||
if (config.iAmRecorder) {
|
||||
this.recorder = new Recorder();
|
||||
}
|
||||
|
||||
if (config.startSilent) {
|
||||
sendAnalytics(createStartSilentEvent());
|
||||
APP.store.dispatch(showNotification({
|
||||
descriptionKey: 'notify.startSilentDescription',
|
||||
titleKey: 'notify.startSilentTitle'
|
||||
}));
|
||||
}
|
||||
|
||||
// XXX The API will take care of disconnecting from the XMPP
|
||||
// server (and, thus, leaving the room) on unload.
|
||||
return new Promise((resolve, reject) => {
|
||||
(new ConferenceConnector(resolve, reject)).connect();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Open new connection and join to the conference.
|
||||
* @param {object} options
|
||||
* @param {string} roomName - The name of the conference.
|
||||
* Open new connection and join the conference when prejoin page is not enabled.
|
||||
* If prejoin page is enabled open an new connection in the background
|
||||
* and create local tracks.
|
||||
*
|
||||
* @param {{ roomName: string }} options
|
||||
* @returns {Promise}
|
||||
*/
|
||||
init(options) {
|
||||
this.roomName = options.roomName;
|
||||
async init({ roomName }) {
|
||||
const initialOptions = {
|
||||
startAudioOnly: config.startAudioOnly,
|
||||
startScreenSharing: config.startScreenSharing,
|
||||
startWithAudioMuted: config.startWithAudioMuted
|
||||
|| config.startSilent
|
||||
|| isUserInteractionRequiredForUnmute(APP.store.getState()),
|
||||
startWithVideoMuted: config.startWithVideoMuted
|
||||
|| isUserInteractionRequiredForUnmute(APP.store.getState())
|
||||
};
|
||||
|
||||
this.roomName = roomName;
|
||||
|
||||
window.addEventListener('hashchange', this.onHashChange.bind(this), false);
|
||||
|
||||
return (
|
||||
|
||||
try {
|
||||
// Initialize the device list first. This way, when creating tracks
|
||||
// based on preferred devices, loose label matching can be done in
|
||||
// cases where the exact ID match is no longer available, such as
|
||||
// when the camera device has switched USB ports.
|
||||
// when in startSilent mode we want to start with audio muted
|
||||
this._initDeviceList()
|
||||
.catch(error => logger.warn(
|
||||
'initial device list initialization failed', error))
|
||||
.then(() => this.createInitialLocalTracksAndConnect(
|
||||
options.roomName, {
|
||||
startAudioOnly: config.startAudioOnly,
|
||||
startScreenSharing: config.startScreenSharing,
|
||||
startWithAudioMuted: config.startWithAudioMuted
|
||||
|| config.startSilent
|
||||
|| isUserInteractionRequiredForUnmute(APP.store.getState()),
|
||||
startWithVideoMuted: config.startWithVideoMuted
|
||||
|| isUserInteractionRequiredForUnmute(APP.store.getState())
|
||||
}))
|
||||
.then(([ tracks, con ]) => {
|
||||
tracks.forEach(track => {
|
||||
if ((track.isAudioTrack() && this.isLocalAudioMuted())
|
||||
|| (track.isVideoTrack() && this.isLocalVideoMuted())) {
|
||||
const mediaType = track.getType();
|
||||
await this._initDeviceList();
|
||||
} catch (error) {
|
||||
logger.warn('initial device list initialization failed', error);
|
||||
}
|
||||
|
||||
sendAnalytics(
|
||||
createTrackMutedEvent(mediaType, 'initial mute'));
|
||||
logger.log(`${mediaType} mute: initially muted.`);
|
||||
track.mute();
|
||||
}
|
||||
});
|
||||
logger.log(`initialized with ${tracks.length} local tracks`);
|
||||
this._localTracksInitialized = true;
|
||||
con.addEventListener(
|
||||
JitsiConnectionEvents.CONNECTION_FAILED,
|
||||
_connectionFailedHandler);
|
||||
APP.connection = connection = con;
|
||||
if (isPrejoinPageEnabled(APP.store.getState())) {
|
||||
_connectionPromise = connect(roomName);
|
||||
|
||||
// Desktop sharing related stuff:
|
||||
this.isDesktopSharingEnabled
|
||||
= JitsiMeetJS.isDesktopSharingEnabled();
|
||||
eventEmitter.emit(
|
||||
JitsiMeetConferenceEvents.DESKTOP_SHARING_ENABLED_CHANGED,
|
||||
this.isDesktopSharingEnabled);
|
||||
const { tryCreateLocalTracks, errors } = this.createInitialLocalTracks(initialOptions);
|
||||
const tracks = await tryCreateLocalTracks;
|
||||
|
||||
APP.store.dispatch(
|
||||
setDesktopSharingEnabled(this.isDesktopSharingEnabled));
|
||||
// Initialize device list a second time to ensure device labels
|
||||
// get populated in case of an initial gUM acceptance; otherwise
|
||||
// they may remain as empty strings.
|
||||
this._initDeviceList(true);
|
||||
|
||||
this._createRoom(tracks);
|
||||
APP.remoteControl.init();
|
||||
return APP.store.dispatch(initPrejoin(tracks, errors));
|
||||
}
|
||||
|
||||
// if user didn't give access to mic or camera or doesn't have
|
||||
// them at all, we mark corresponding toolbar buttons as muted,
|
||||
// so that the user can try unmute later on and add audio/video
|
||||
// to the conference
|
||||
if (!tracks.find(t => t.isAudioTrack())) {
|
||||
this.setAudioMuteStatus(true);
|
||||
}
|
||||
const [ tracks, con ] = await this.createInitialLocalTracksAndConnect(
|
||||
roomName, initialOptions);
|
||||
|
||||
if (!tracks.find(t => t.isVideoTrack())) {
|
||||
this.setVideoMuteStatus(true);
|
||||
}
|
||||
this._initDeviceList(true);
|
||||
|
||||
// Initialize device list a second time to ensure device labels
|
||||
// get populated in case of an initial gUM acceptance; otherwise
|
||||
// they may remain as empty strings.
|
||||
this._initDeviceList(true);
|
||||
return this.startConference(con, tracks);
|
||||
},
|
||||
|
||||
if (config.iAmRecorder) {
|
||||
this.recorder = new Recorder();
|
||||
}
|
||||
/**
|
||||
* Joins conference after the tracks have been configured in the prejoin screen.
|
||||
*
|
||||
* @param {Object[]} tracks - An array with the configured tracks
|
||||
* @returns {Promise}
|
||||
*/
|
||||
async prejoinStart(tracks) {
|
||||
const con = await _connectionPromise;
|
||||
|
||||
if (config.startSilent) {
|
||||
sendAnalytics(createStartSilentEvent());
|
||||
APP.store.dispatch(showNotification({
|
||||
descriptionKey: 'notify.startSilentDescription',
|
||||
titleKey: 'notify.startSilentTitle'
|
||||
}));
|
||||
}
|
||||
|
||||
// XXX The API will take care of disconnecting from the XMPP
|
||||
// server (and, thus, leaving the room) on unload.
|
||||
return new Promise((resolve, reject) => {
|
||||
(new ConferenceConnector(resolve, reject)).connect();
|
||||
});
|
||||
})
|
||||
);
|
||||
return this.startConference(con, tracks);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -1197,7 +1261,7 @@ export default {
|
||||
items[key] = param[1];
|
||||
}
|
||||
|
||||
if (typeof items.e2eekey !== undefined) {
|
||||
if (typeof items.e2eekey !== 'undefined') {
|
||||
APP.store.dispatch(setE2EEKey(items.e2eekey));
|
||||
|
||||
// Clean URL in browser history.
|
||||
@@ -1303,7 +1367,13 @@ export default {
|
||||
const options = config;
|
||||
const { email, name: nick } = getLocalParticipant(APP.store.getState());
|
||||
|
||||
const { locationURL } = APP.store.getState()['features/base/connection'];
|
||||
const state = APP.store.getState();
|
||||
const { locationURL } = state['features/base/connection'];
|
||||
const { tenant } = state['features/base/jwt'];
|
||||
|
||||
if (tenant) {
|
||||
options.siteID = tenant;
|
||||
}
|
||||
|
||||
if (options.enableDisplayNameInStats && nick) {
|
||||
options.statisticsDisplayName = nick;
|
||||
@@ -1315,7 +1385,7 @@ export default {
|
||||
|
||||
options.applicationName = interfaceConfig.APP_NAME;
|
||||
options.getWiFiStatsMethod = this._getWiFiStatsMethod;
|
||||
options.confID = `${locationURL.host}${locationURL.pathname}`;
|
||||
options.confID = `${locationURL.host}${getBackendSafePath(locationURL.pathname)}`;
|
||||
options.createVADProcessor = createRnnoiseProcessorPromise;
|
||||
|
||||
// Disable CallStats, if requessted.
|
||||
@@ -1352,6 +1422,18 @@ export default {
|
||||
useVideoStream(newStream) {
|
||||
return new Promise((resolve, reject) => {
|
||||
_replaceLocalVideoTrackQueue.enqueue(onFinish => {
|
||||
/**
|
||||
* When the prejoin page is visible there is no conference object
|
||||
* created. The prejoin tracks are managed separately,
|
||||
* so this updates the prejoin video track.
|
||||
*/
|
||||
if (isPrejoinPageVisible(APP.store.getState())) {
|
||||
return APP.store.dispatch(replacePrejoinVideoTrack(newStream))
|
||||
.then(resolve)
|
||||
.catch(reject)
|
||||
.then(onFinish);
|
||||
}
|
||||
|
||||
APP.store.dispatch(
|
||||
replaceLocalTrack(this.localVideo, newStream, room))
|
||||
.then(() => {
|
||||
@@ -1405,6 +1487,18 @@ export default {
|
||||
useAudioStream(newStream) {
|
||||
return new Promise((resolve, reject) => {
|
||||
_replaceLocalAudioTrackQueue.enqueue(onFinish => {
|
||||
/**
|
||||
* When the prejoin page is visible there is no conference object
|
||||
* created. The prejoin tracks are managed separately,
|
||||
* so this updates the prejoin audio stream.
|
||||
*/
|
||||
if (isPrejoinPageVisible(APP.store.getState())) {
|
||||
return APP.store.dispatch(replacePrejoinAudioTrack(newStream))
|
||||
.then(resolve)
|
||||
.catch(reject)
|
||||
.then(onFinish);
|
||||
}
|
||||
|
||||
APP.store.dispatch(
|
||||
replaceLocalTrack(this.localAudio, newStream, room))
|
||||
.then(() => {
|
||||
@@ -2005,6 +2099,7 @@ export default {
|
||||
logger.info(`My role changed, new role: ${role}`);
|
||||
|
||||
APP.store.dispatch(localParticipantRoleChanged(role));
|
||||
APP.API.notifyUserRoleChanged(id, role);
|
||||
} else {
|
||||
APP.store.dispatch(participantRoleChanged(id, role));
|
||||
}
|
||||
|
||||
26
config.js
26
config.js
@@ -54,6 +54,13 @@ var config = {
|
||||
// Disables the auto-play behavior of *all* newly created video element.
|
||||
// This is useful when the client runs on a host with limited resources.
|
||||
// noAutoPlayVideo: false
|
||||
|
||||
// Enable / disable 500 Kbps bitrate cap on desktop tracks. When enabled,
|
||||
// simulcast is turned off for the desktop share. If presenter is turned
|
||||
// on while screensharing is in progress, the max bitrate is automatically
|
||||
// adjusted to 2.5 Mbps. This takes a value between 0 and 1 which determines
|
||||
// the probability for this to be enabled.
|
||||
// capScreenshareBitrate: 1 // 0 to disable
|
||||
},
|
||||
|
||||
// Disables ICE/UDP by filtering out local and remote UDP candidates in
|
||||
@@ -226,6 +233,14 @@ var config = {
|
||||
// disabled, then bandwidth estimations are disabled.
|
||||
// enableRemb: false,
|
||||
|
||||
// Enables ICE restart logic in LJM and displays the page reload overlay on
|
||||
// ICE failure. Current disabled by default because it's causing issues with
|
||||
// signaling when Octo is enabled. Also when we do an "ICE restart"(which is
|
||||
// not a real ICE restart), the client maintains the TCC sequence number
|
||||
// counter, but the bridge resets it. The bridge sends media packets with
|
||||
// TCC sequence numbers starting from 0.
|
||||
// enableIceRestart: false,
|
||||
|
||||
// Defines the minimum number of participants to start a call (the default
|
||||
// is set in Jicofo and set to 2).
|
||||
// minParticipants: 2,
|
||||
@@ -289,6 +304,9 @@ var config = {
|
||||
// and microsoftApiApplicationClientID
|
||||
// enableCalendarIntegration: false,
|
||||
|
||||
// When 'true', it shows an intermediate page before joining, where the user can configure its devices.
|
||||
// prejoinPageEnabled: false,
|
||||
|
||||
// Stats
|
||||
//
|
||||
|
||||
@@ -341,7 +359,7 @@ var config = {
|
||||
|
||||
// { urls: 'stun:jitsi-meet.example.com:4446' },
|
||||
{ urls: 'stun:meet-jit-si-turnrelay.jitsi.net:443' }
|
||||
],
|
||||
]
|
||||
|
||||
// Sets the ICE transport policy for the p2p connection. At the time
|
||||
// of this writing the list of possible values are 'all' and 'relay',
|
||||
@@ -353,7 +371,7 @@ var config = {
|
||||
|
||||
// If set to true, it will prefer to use H.264 for P2P calls (if H.264
|
||||
// is supported).
|
||||
preferH264: true
|
||||
// preferH264: true
|
||||
|
||||
// If set to true, disable H.264 video codec by stripping it out of the
|
||||
// SDP.
|
||||
@@ -368,6 +386,10 @@ var config = {
|
||||
// The Google Analytics Tracking ID:
|
||||
// googleAnalyticsTrackingId: 'your-tracking-id-UA-123456-1'
|
||||
|
||||
// Matomo configuration:
|
||||
// matomoEndpoint: 'https://your-matomo-endpoint/',
|
||||
// matomoSiteID: '42',
|
||||
|
||||
// The Amplitude APP Key:
|
||||
// amplitudeAPPKey: '<APP_KEY>'
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/* global APP, JitsiMeetJS, config */
|
||||
|
||||
import AuthHandler from './modules/UI/authentication/AuthHandler';
|
||||
import jitsiLocalStorage from './modules/util/JitsiLocalStorage';
|
||||
import Logger from 'jitsi-meet-logger';
|
||||
import { jitsiLocalStorage } from 'js-utils';
|
||||
|
||||
import AuthHandler from './modules/UI/authentication/AuthHandler';
|
||||
import {
|
||||
connectionEstablished,
|
||||
connectionFailed
|
||||
@@ -13,7 +14,7 @@ import {
|
||||
JitsiConnectionEvents
|
||||
} from './react/features/base/lib-jitsi-meet';
|
||||
|
||||
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||
const logger = Logger.getLogger(__filename);
|
||||
|
||||
/**
|
||||
* The feature announced so we can distinguish jibri participants.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* global config, createConnectionExternally */
|
||||
|
||||
import getRoomName from '../react/features/base/config/getRoomName';
|
||||
import parseURLParams from '../react/features/base/config/parseURLParams';
|
||||
import { parseURLParams } from '../react/features/base/util/parseURLParams';
|
||||
|
||||
/**
|
||||
* Implements external connect using createConnectionExternally function defined
|
||||
|
||||
75
css/_country-picker.scss
Normal file
75
css/_country-picker.scss
Normal file
@@ -0,0 +1,75 @@
|
||||
.cpick {
|
||||
border: 1px solid #A4B8D1;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
font-size: 15px;
|
||||
height: 38px;
|
||||
line-height: 24px;
|
||||
|
||||
&-selector {
|
||||
align-items: center;
|
||||
background-color: #283447;
|
||||
border-right: 1px solid #A4B8D1;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
padding: 8px 10px;
|
||||
position: relative;
|
||||
width: 88px;
|
||||
}
|
||||
|
||||
&-icon {
|
||||
margin-right: 8px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 12px;
|
||||
|
||||
& > svg {
|
||||
fill: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&-input {
|
||||
padding: 8px;
|
||||
background: #1C2025;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
color: #fff;
|
||||
caret-color: #0376DA;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
&-dropdown {
|
||||
height: 190px;
|
||||
overflow-y: auto;
|
||||
width: 343px;
|
||||
}
|
||||
|
||||
&-dropdown-entry {
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
height: 40px;
|
||||
padding: 0 10px;
|
||||
|
||||
&:hover {
|
||||
background-color: #66768b;
|
||||
}
|
||||
|
||||
&-text {
|
||||
color: #fff;
|
||||
flex-grow: 1;
|
||||
font-size: 15px;
|
||||
line-height: 24px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Override @Atlaskit/inline-dialog styles
|
||||
.cpick-container > div > div:nth-child(2) > div > div {
|
||||
outline: none;
|
||||
padding: 8px 0 0 0;
|
||||
}
|
||||
68
css/_labels.scss
Normal file
68
css/_labels.scss
Normal file
@@ -0,0 +1,68 @@
|
||||
.large-video-labels {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
right: 30px;
|
||||
transition: right 0.5s;
|
||||
z-index: $zindex3;
|
||||
|
||||
.circular-label {
|
||||
align-items: center;
|
||||
color: white;
|
||||
display: flex;
|
||||
font-weight: bold;
|
||||
justify-content: center;
|
||||
margin-left: 8px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.circular-label {
|
||||
background: #B8C7E0;
|
||||
}
|
||||
|
||||
.circular-label.e2ee {
|
||||
align-items: center;
|
||||
background: #76CF9C;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.circular-label.file {
|
||||
background: #FF5630;
|
||||
}
|
||||
|
||||
.circular-label.local-rec {
|
||||
background: #FF5630;
|
||||
}
|
||||
|
||||
.circular-label.stream {
|
||||
background: #0065FF;
|
||||
}
|
||||
|
||||
.circular-label.insecure {
|
||||
background: $defaultWarningColor;
|
||||
}
|
||||
|
||||
.recording-label.center-message {
|
||||
background: $videoStateIndicatorBackground;
|
||||
bottom: 50%;
|
||||
display: block;
|
||||
left: 50%;
|
||||
padding: 10px;
|
||||
position: fixed;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: $centeredVideoLabelZ;
|
||||
}
|
||||
}
|
||||
|
||||
.circular-label {
|
||||
background: $videoStateIndicatorBackground;
|
||||
border-radius: 50%;
|
||||
box-sizing: border-box;
|
||||
cursor: default;
|
||||
font-size: 13px;
|
||||
height: $videoStateIndicatorSize;
|
||||
line-height: $videoStateIndicatorSize;
|
||||
text-align: center;
|
||||
min-width: $videoStateIndicatorSize;
|
||||
}
|
||||
182
css/_prejoin-dialog.scss
Normal file
182
css/_prejoin-dialog.scss
Normal file
@@ -0,0 +1,182 @@
|
||||
.prejoin-dialog {
|
||||
background: #1C2025;
|
||||
box-shadow: 0px 2px 20px rgba(0, 0, 0, 0.5);
|
||||
border-radius: 5px;
|
||||
color: #fff;
|
||||
height: 400px;
|
||||
width: 375px;
|
||||
|
||||
&--small {
|
||||
height: 300;
|
||||
width: 400;
|
||||
}
|
||||
|
||||
&-label {
|
||||
font-size: 15px;
|
||||
line-height: 24px;
|
||||
|
||||
&-num {
|
||||
background: #2b3b4b;
|
||||
border: 1px solid #A4B8D1;
|
||||
border-radius: 50%;
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||
height: 24px;
|
||||
margin-right: 8px;
|
||||
width: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
&-container {
|
||||
align-items: center;
|
||||
background: rgba(0,0,0,0.6);
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
justify-content: center;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100vw;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
&-flag {
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
&-title {
|
||||
display: inline-block;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
&-icon {
|
||||
cursor: pointer;
|
||||
|
||||
> svg {
|
||||
fill: #A4B8D1;
|
||||
}
|
||||
}
|
||||
|
||||
&-btn {
|
||||
width: 309px;
|
||||
}
|
||||
|
||||
&-dialin-container {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&-delimiter {
|
||||
background: #5f6266;
|
||||
border: 0;
|
||||
height: 1px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
|
||||
&-container {
|
||||
margin: 16px 0 24px 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&-txt-container {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
top: -8px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-txt {
|
||||
background: #1C2025;
|
||||
color: #5f6266;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
padding: 0 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.prejoin-dialog-callout {
|
||||
padding: 16px;
|
||||
|
||||
&-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
&-picker {
|
||||
margin: 8px 0 16px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.prejoin-dialog-dialin {
|
||||
text-align: center;
|
||||
|
||||
&-header {
|
||||
align-items: center;
|
||||
margin: 16px 0 32px 16px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&-icon {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
&-num {
|
||||
background: #3e474f;
|
||||
border-radius: 4px;
|
||||
display: inline-block;
|
||||
font-size: 15px;
|
||||
line-height: 24px;
|
||||
margin: 4px;
|
||||
padding: 8px;
|
||||
|
||||
&-container {
|
||||
min-height: 48px;
|
||||
margin: 8px 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-link {
|
||||
color: #6FB1EA;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
&-spaced-label {
|
||||
margin-bottom: 16px;
|
||||
margin-top: 28px;
|
||||
}
|
||||
|
||||
&-btns {
|
||||
&> div {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.prejoin-dialog-calling {
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
|
||||
&-header {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
&-label {
|
||||
font-size: 15px;
|
||||
margin: 8px 0 16px 0;
|
||||
}
|
||||
|
||||
&-number {
|
||||
font-size: 19px;
|
||||
line-height: 28px;
|
||||
margin: 16px 0;
|
||||
}
|
||||
}
|
||||
353
css/_prejoin.scss
Normal file
353
css/_prejoin.scss
Normal file
@@ -0,0 +1,353 @@
|
||||
.prejoin {
|
||||
&-full-page {
|
||||
background: #1C2025;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: $toolbarZ + 1;
|
||||
}
|
||||
|
||||
&-input-area-container {
|
||||
position: absolute;
|
||||
bottom: 48px;
|
||||
width: 100%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
&-input-area {
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
&-title {
|
||||
color: #fff;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
&-btn {
|
||||
border-radius: 3px;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-size: 15px;
|
||||
line-height: 24px;
|
||||
padding: 7px 16px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
width: 286px;
|
||||
|
||||
&--primary {
|
||||
background: #0376DA;
|
||||
border: 1px solid #0376DA;
|
||||
}
|
||||
|
||||
&--secondary {
|
||||
background: #2A3A4B;
|
||||
border: 1px solid #5E6D7A;
|
||||
}
|
||||
|
||||
&--text {
|
||||
width: auto;
|
||||
font-size: 13px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
background: #5E6D7A;
|
||||
border: 1px solid #5E6D7A;
|
||||
color: #AFB6BC;
|
||||
cursor: initial;
|
||||
|
||||
.prejoin-btn-icon {
|
||||
& > svg {
|
||||
fill: #AFB6BC;
|
||||
}
|
||||
}
|
||||
|
||||
.prejoin-btn-options {
|
||||
border-left: 1px solid #AFB6BC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-btn-options {
|
||||
align-items: center;
|
||||
border-left: 1px solid #fff;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
&-text-btns {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
&-input-label {
|
||||
color: #A4B8D1;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
margin-top: 32px 0 8px 0;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-checkbox {
|
||||
border: 0;
|
||||
height: 16px;
|
||||
margin-right: 8px;
|
||||
padding: 0;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
&-checkbox-container {
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
display: none;
|
||||
font-size: 13px;
|
||||
justify-content: center;
|
||||
line-height: 20px;
|
||||
margin-top: 16px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin name-placeholder {
|
||||
color: #fff;
|
||||
font-weight: 300;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.prejoin-preview {
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
|
||||
&--no-video {
|
||||
background: radial-gradient(50% 50% at 50% 50%, #5B6F80 0%, #365067 100%), #FFFFFF;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&-video {
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-name {
|
||||
color: #fff;
|
||||
font-size: 19px;
|
||||
line-height: 28px;
|
||||
|
||||
&--editable {
|
||||
background: none;
|
||||
border: 0;
|
||||
border-bottom: 1px solid #D1DBE8;
|
||||
margin: 24px 0 16px 0;
|
||||
outline: none;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
|
||||
&::-webkit-input-placeholder {
|
||||
@include name-placeholder;
|
||||
}
|
||||
&::-moz-placeholder {
|
||||
@include name-placeholder;
|
||||
}
|
||||
&:-ms-input-placeholder {
|
||||
@include name-placeholder;
|
||||
}
|
||||
}
|
||||
|
||||
&--text {
|
||||
margin: 16px 0;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-avatar.avatar {
|
||||
background: #A4B8D1;
|
||||
margin: 200px auto 0 auto;
|
||||
}
|
||||
|
||||
&-btn-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 32px;
|
||||
width: 100%;
|
||||
|
||||
&> div {
|
||||
margin: 0 12px;
|
||||
}
|
||||
|
||||
.settings-button-small-icon {
|
||||
right: -8px;
|
||||
|
||||
&--hovered {
|
||||
right: -10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-overlay {
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
background: linear-gradient(0deg, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3));
|
||||
}
|
||||
|
||||
&-bottom-overlay {
|
||||
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.9) 100%);
|
||||
bottom: 0;
|
||||
height: 50%;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&-status {
|
||||
align-items: center;
|
||||
bottom: 0;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
font-size: 13px;
|
||||
min-height: 24px;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
|
||||
&--warning {
|
||||
background: rgba(241, 173, 51, 0.5)
|
||||
}
|
||||
&--ok {
|
||||
background: rgba(49, 183, 106, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
&-icon {
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
margin-right: 8px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
&-error-desc {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.settings-button-container {
|
||||
width: 49px;
|
||||
margin: 0 8px;
|
||||
}
|
||||
|
||||
&-dropdown-btns {
|
||||
width: 320px;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
&-dropdown-btn {
|
||||
align-items: center;
|
||||
color: #1C2025;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
height: 40px;
|
||||
font-size: 15px;
|
||||
line-height: 24px;
|
||||
padding: 0 16px;
|
||||
|
||||
&:hover {
|
||||
background-color: #DAEBFA;
|
||||
}
|
||||
}
|
||||
|
||||
&-dropdown-icon {
|
||||
display: inline-block;
|
||||
margin-right: 16px;
|
||||
|
||||
& > svg {
|
||||
fill: #1C2025;
|
||||
}
|
||||
}
|
||||
|
||||
&-dropdown-container {
|
||||
& > div > div:nth-child(2) > div > div {
|
||||
background: #fff;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.prejoin-copy {
|
||||
&-meeting {
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
font-size: 15px;
|
||||
font-weight: 300;
|
||||
line-height: 24px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&-url {
|
||||
max-width: 278px;
|
||||
padding: 8px 10px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&-badge {
|
||||
border-radius: 4px;
|
||||
height: 100%;
|
||||
line-height: 38px;
|
||||
position: absolute;
|
||||
padding-left: 10px;
|
||||
text-align: left;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
|
||||
&--hover {
|
||||
background: #1C2025;
|
||||
}
|
||||
|
||||
&--done {
|
||||
background: #31B76A;
|
||||
}
|
||||
}
|
||||
|
||||
&-icon {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
top: 8px;
|
||||
|
||||
&--white {
|
||||
&> svg > path {
|
||||
fill: #fff
|
||||
}
|
||||
}
|
||||
|
||||
&--light {
|
||||
&> svg > path {
|
||||
fill: #D1DBE8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-textarea {
|
||||
position: absolute;
|
||||
left: -9999px;
|
||||
}
|
||||
}
|
||||
@@ -57,6 +57,7 @@
|
||||
width: 16px;
|
||||
|
||||
&> svg {
|
||||
fill: #5e6d7a;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
.video-preview {
|
||||
background: none;
|
||||
max-height: 290px;
|
||||
overflow: auto;
|
||||
|
||||
&-container {
|
||||
overflow: auto;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
&-entry {
|
||||
cursor: pointer;
|
||||
@@ -61,6 +65,6 @@
|
||||
// Override @atlaskit/InlineDialog container which is made with styled components
|
||||
& > div > div:nth-child(2) > div > div {
|
||||
outline: none;
|
||||
padding: 16px;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,9 +71,6 @@ body.welcome-page {
|
||||
text-align: left;
|
||||
color: #253858;
|
||||
height: fit-content;
|
||||
border-width: $welcomePageEnterRoomInputContainerBorderWidth;
|
||||
border-style: $welcomePageEnterRoomInputContainerBorderStyle;
|
||||
border-image: $welcomePageEnterRoomInputContainerBorderImage;
|
||||
|
||||
.enter-room-title {
|
||||
display: $welcomePageEnterRoomTitleDisplay;
|
||||
@@ -83,12 +80,26 @@ body.welcome-page {
|
||||
}
|
||||
|
||||
.enter-room-input {
|
||||
border: none;
|
||||
border-width: $welcomePageEnterRoomInputContainerBorderWidth;
|
||||
border-style: $welcomePageEnterRoomInputContainerBorderStyle;
|
||||
border-image: $welcomePageEnterRoomInputContainerBorderImage;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.insecure-room-name-warning {
|
||||
align-items: center;
|
||||
color: $defaultWarningColor;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-top: 5px;
|
||||
|
||||
svg {
|
||||
fill: $defaultWarningColor
|
||||
}
|
||||
}
|
||||
|
||||
::placeholder {
|
||||
color: #253858;
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ $flagsImagePath: "../images/";
|
||||
@import 'filmstrip/tile_view_overrides';
|
||||
@import 'filmstrip/vertical_filmstrip';
|
||||
@import 'filmstrip/vertical_filmstrip_overrides';
|
||||
@import 'labels';
|
||||
@import 'unsupported-browser/main';
|
||||
@import 'modals/invite/add-people';
|
||||
@import 'deep-linking/main';
|
||||
@@ -90,5 +91,10 @@ $flagsImagePath: "../images/";
|
||||
@import 'meter';
|
||||
@import 'audio-preview';
|
||||
@import 'video-preview';
|
||||
@import 'prejoin';
|
||||
@import 'prejoin-dialog';
|
||||
@import 'country-picker';
|
||||
@import 'modals/invite/invite_more';
|
||||
@import 'modals/security/security';
|
||||
|
||||
/* Modules END */
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
.modal-dialog-form {
|
||||
.add-people-form-wrap {
|
||||
margin-top: 8px;
|
||||
|
||||
.error {
|
||||
padding-left: 5px;
|
||||
|
||||
@@ -3,47 +3,6 @@
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
|
||||
.info-dialog-action-link {
|
||||
display: inline-block;
|
||||
line-height: 1.5em;
|
||||
|
||||
a {
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.info-dialog-action-link:before {
|
||||
color: $linkFontColor;
|
||||
content: '\2022';
|
||||
font-size: 1.5em;
|
||||
padding: 0 10px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.info-dialog-action-link:first-child:before {
|
||||
content: '';
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.info-dialog-action-links {
|
||||
font-weight: bold;
|
||||
margin-top: 10px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.info-dialog-action-separator {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.info-dialog-copy-element {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
-webkit-user-select: text;
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
.info-dialog-column {
|
||||
margin-right: 10px;
|
||||
overflow: hidden;
|
||||
@@ -56,52 +15,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.info-dialog-conference-url,
|
||||
.info-dialog-live-stream-url {
|
||||
width: max-content;
|
||||
width: -moz-max-content;
|
||||
width: -webkit-max-content;
|
||||
word-break: break-all;
|
||||
max-width: 400px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.info-dialog-dial-in {
|
||||
word-break: break-all;
|
||||
|
||||
.conference-id,
|
||||
.phone-number {
|
||||
user-select: text;
|
||||
}
|
||||
}
|
||||
|
||||
.info-dialog-icon {
|
||||
color: #6453C0;
|
||||
font-size: 16px;
|
||||
min-width: 30px;
|
||||
}
|
||||
|
||||
.info-dialog-url-text,
|
||||
.info-dialog-url-text:hover {
|
||||
color: inherit;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
.info-dialog-url-icon {
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
|
||||
svg {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.info-dialog-title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.info-dialog-password,
|
||||
.info-password,
|
||||
.info-password-form {
|
||||
@@ -125,6 +38,7 @@
|
||||
}
|
||||
|
||||
.info-password-input {
|
||||
width: 100%;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: inherit;
|
||||
@@ -223,10 +137,4 @@
|
||||
-moz-user-select: text;
|
||||
-webkit-user-select: text;
|
||||
}
|
||||
|
||||
.info-dialog-url-text-unselectable {
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
}
|
||||
|
||||
252
css/modals/invite/_invite_more.scss
Normal file
252
css/modals/invite/_invite_more.scss
Normal file
@@ -0,0 +1,252 @@
|
||||
.invite-more {
|
||||
&-container {
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
z-index: $zindex2;
|
||||
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||
|
||||
&.elevated {
|
||||
z-index: $filmstripVideosZ + 1;
|
||||
}
|
||||
}
|
||||
|
||||
&-header {
|
||||
font-size: 19px;
|
||||
line-height: 28px;
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
&-button {
|
||||
display: flex;
|
||||
margin: auto;
|
||||
padding: 8px 16px;
|
||||
width: fit-content;
|
||||
width: -moz-fit-content;
|
||||
height: 24px;
|
||||
background: #0376DA;
|
||||
border-radius: 3px;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: #278ADF;
|
||||
}
|
||||
|
||||
&-text {
|
||||
margin-left: 8px;
|
||||
font-size: 15px;
|
||||
line-height: 24px;
|
||||
}
|
||||
}
|
||||
&-dialog {
|
||||
color: #fff;
|
||||
font-size: 15px;
|
||||
line-height: 24px;
|
||||
|
||||
& > span {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 16px 16px 24px;
|
||||
width: calc(100% - 32px);
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
|
||||
& > div > svg {
|
||||
cursor: pointer;
|
||||
fill: #A4B8D1;
|
||||
}
|
||||
}
|
||||
|
||||
&.copy-link {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 8px 8px 16px;
|
||||
margin-top: 8px;
|
||||
width: calc(100% - 24px);
|
||||
height: 24px;
|
||||
|
||||
background: #0376DA;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: #278ADF;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&-text {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
max-width: 292px;
|
||||
|
||||
&.selected {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
&.clicked {
|
||||
background: #31B76A;
|
||||
}
|
||||
|
||||
& > div > svg > path {
|
||||
fill: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&.separator {
|
||||
margin: 24px 0 24px -20px;
|
||||
padding: 0 20px;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: #5E6D7A;
|
||||
}
|
||||
|
||||
&.email-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 8px 8px 16px;
|
||||
margin-top: 24px;
|
||||
width: calc(100% - 26px);
|
||||
height: 22px;
|
||||
|
||||
background: #2A3A4B;
|
||||
border: 1px solid #5E6D7A;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
|
||||
&.active {
|
||||
border-radius: 3px 3px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.icon-container {
|
||||
display: none;
|
||||
|
||||
&.active {
|
||||
display: flex;
|
||||
width: calc(100% - 26px);
|
||||
padding: 8px 8px 8px 16px;
|
||||
|
||||
background: #2A3A4B;
|
||||
border: 1px solid #5E6D7A;
|
||||
border-top: none;
|
||||
border-radius: 0 0 3px 3px;
|
||||
|
||||
& > * {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:hover > div:hover {
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
& > :not(:last-child) {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.copy-invite-icon > div > svg > path {
|
||||
fill: #A4B8D1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.dial-in-display {
|
||||
.info-label {
|
||||
color: #A4B8D1;
|
||||
}
|
||||
|
||||
.dial-in-copy {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-left: 21px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
&.invite-buttons {
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
margin-top: 8px;
|
||||
|
||||
& > a {
|
||||
display: inline-block;
|
||||
height: 24px;
|
||||
width: 48px;
|
||||
border-radius: 3px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&-cancel {
|
||||
margin-right: 16px;
|
||||
padding: 7px 15px;
|
||||
background: #2A3A4B;
|
||||
border: 1px solid #5E6D7A;
|
||||
}
|
||||
|
||||
&-add {
|
||||
padding: 8px 16px;
|
||||
background: #0376DA;
|
||||
}
|
||||
}
|
||||
|
||||
&.stream {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 8px 8px 16px;
|
||||
margin-top: 8px;
|
||||
width: calc(100% - 26px);
|
||||
height: 22px;
|
||||
|
||||
background: #2A3A4B;
|
||||
border: 1px solid #5E6D7A;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&-text {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
max-width: 292px;
|
||||
|
||||
&.selected {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
&.clicked {
|
||||
background: #31B76A;
|
||||
border: 1px solid #31B76A;
|
||||
}
|
||||
|
||||
& > div > svg > path {
|
||||
fill: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
css/modals/security/_security.scss
Normal file
37
css/modals/security/_security.scss
Normal file
@@ -0,0 +1,37 @@
|
||||
.security {
|
||||
&-dialog {
|
||||
color: #fff;
|
||||
font-size: 15px;
|
||||
line-height: 24px;
|
||||
|
||||
&.password {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
&-actions {
|
||||
a {
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
color: #6FB1EA;
|
||||
}
|
||||
|
||||
& > :first-child:not(:last-child) {
|
||||
margin-right: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.new-toolbox .toolbox-content .toolbox-icon.security-toolbar-button,
|
||||
.new-toolbox .toolbox-content .toolbox-icon.toggled.security-toolbar-button {
|
||||
background: rgba(241, 173, 51, 0.7);
|
||||
border: 1px solid rgba(255, 255, 255, 0.4);
|
||||
|
||||
&:hover {
|
||||
background: rgba(241, 173, 51, 0.7);
|
||||
border: 1px solid rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
}
|
||||
@@ -144,65 +144,3 @@
|
||||
#videoResolutionLabel {
|
||||
z-index: $zindex3 + 1;
|
||||
}
|
||||
|
||||
.large-video-labels {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
right: 30px;
|
||||
transition: right 0.5s;
|
||||
z-index: $zindex3;
|
||||
|
||||
.circular-label {
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
margin-left: 8px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.circular-label {
|
||||
background: #B8C7E0;
|
||||
}
|
||||
|
||||
.circular-label.e2ee {
|
||||
align-items: center;
|
||||
background: #76CF9C;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.circular-label.file {
|
||||
background: #FF5630;
|
||||
}
|
||||
|
||||
.circular-label.local-rec {
|
||||
background: #FF5630;
|
||||
}
|
||||
|
||||
.circular-label.stream {
|
||||
background: #0065FF;
|
||||
}
|
||||
|
||||
.recording-label.center-message {
|
||||
background: $videoStateIndicatorBackground;
|
||||
bottom: 50%;
|
||||
display: block;
|
||||
left: 50%;
|
||||
padding: 10px;
|
||||
position: fixed;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: $centeredVideoLabelZ;
|
||||
}
|
||||
}
|
||||
|
||||
.circular-label {
|
||||
background: $videoStateIndicatorBackground;
|
||||
border-radius: 50%;
|
||||
box-sizing: border-box;
|
||||
cursor: default;
|
||||
font-size: 13px;
|
||||
height: $videoStateIndicatorSize;
|
||||
line-height: $videoStateIndicatorSize;
|
||||
text-align: center;
|
||||
min-width: $videoStateIndicatorSize;
|
||||
}
|
||||
|
||||
2
debian/control
vendored
2
debian/control
vendored
@@ -3,7 +3,7 @@ Section: net
|
||||
Priority: extra
|
||||
Maintainer: Jitsi Team <dev@jitsi.org>
|
||||
Uploaders: Emil Ivov <emcho@jitsi.org>, Damian Minkov <damencho@jitsi.org>
|
||||
Build-Depends: debhelper (>= 8.0.0)
|
||||
Build-Depends: debhelper (>= 8.0.0), nodejs
|
||||
Standards-Version: 3.9.6
|
||||
Homepage: https://jitsi.org/meet
|
||||
|
||||
|
||||
2
debian/jitsi-meet-turnserver.postinst
vendored
2
debian/jitsi-meet-turnserver.postinst
vendored
@@ -106,7 +106,7 @@ case "$1" in
|
||||
TURN_SECRET="$RET"
|
||||
|
||||
# no turn config exists, lt's copy template and fill it in
|
||||
PUBLIC_IP=$(dig +short myip.opendns.com @resolver1.opendns.com) || true
|
||||
PUBLIC_IP=$(dig -4 +short myip.opendns.com a @resolver1.opendns.com) || true
|
||||
if [ -z "$PUBLIC_IP" ] ; then
|
||||
PUBLIC_IP="127.0.0.1"
|
||||
echo "------------------------------------------------"
|
||||
|
||||
@@ -1,45 +1,3 @@
|
||||
# Documentation
|
||||
|
||||
This document is the entrypoint to different guides, divided in three groups:
|
||||
|
||||
* User guide: these documents are designed to help users of the service, to better
|
||||
understand all the available features and how to use them.
|
||||
|
||||
* Developer guide: these documents are designed to help developers who want to either
|
||||
integrate the Jitsi Meet API / SDK in their products or want to improve Jitsi Meet
|
||||
itself by developing new features or fixing bugs.
|
||||
|
||||
* DevOps guide: these documents are designed for DevOps folks, system administrators
|
||||
or anyone who wishes to deploy and operate their own Jitsi Meet instance.
|
||||
|
||||
## User guide
|
||||
|
||||
Work in progress.
|
||||
|
||||
## Developer guide
|
||||
|
||||
### Web
|
||||
|
||||
* [iframe API](https://github.com/jitsi/jitsi-meet/blob/master/doc/api.md)
|
||||
* [Jitsi Meet development](https://github.com/jitsi/jitsi-meet/blob/master/doc/development.md)
|
||||
|
||||
### Mobile
|
||||
|
||||
* [Building the mobile apps](https://github.com/jitsi/jitsi-meet/blob/master/doc/mobile.md)
|
||||
* [SDK usage examples](https://github.com/jitsi/jitsi-meet-sdk-samples)
|
||||
* [Enabling Dropbox support](https://github.com/jitsi/jitsi-meet/blob/master/doc/mobile-dropbox.md)
|
||||
* [Enabling Google authentication](https://github.com/jitsi/jitsi-meet/blob/master/doc/mobile-google-auth.md)
|
||||
|
||||
## DevOps guide
|
||||
|
||||
* [Quick install](https://github.com/jitsi/jitsi-meet/blob/master/doc/quick-install.md)
|
||||
* [Docker install](https://github.com/jitsi/docker-jitsi-meet/blob/master/README.md)
|
||||
* [Google Calendar, MS Calendar, Dropbox integrations](https://github.com/jitsi/jitsi-meet/blob/master/doc/integrations.md)
|
||||
* [Video tutorials on deployment and scalability](https://jitsi.org/tutorials/)
|
||||
* [Configuring a video SIP gateway](https://github.com/jitsi/jitsi-meet/blob/master/doc/sipgw-config.md)
|
||||
* [Enabling speaker stats](https://github.com/jitsi/jitsi-meet/blob/master/doc/speakerstats-prosody.md)
|
||||
* [Enabling TURN](https://github.com/jitsi/jitsi-meet/blob/master/doc/turn.md)
|
||||
* [Networking FAQ](https://github.com/jitsi/jitsi-meet/blob/master/doc/faq.md)
|
||||
* [Cloud APIs](https://github.com/jitsi/jitsi-meet/blob/master/doc/cloud-api.md)
|
||||
* [Manual Installation](https://github.com/jitsi/jitsi-meet/blob/master/doc/manual-install.md)
|
||||
* [Scalable Installation](https://github.com/jitsi/jitsi-meet/blob/master/doc/scalable-installation.md)
|
||||
The Jitsi documentation has been moved to [The Handbook](https://jitsi.github.io/handbook/).
|
||||
|
||||
618
doc/api.md
618
doc/api.md
@@ -1,619 +1,3 @@
|
||||
# Jitsi Meet API
|
||||
|
||||
You can use the Jitsi Meet API to embed Jitsi Meet in to your application. You are also welcome to use it for embedding the globally distributed and highly available deployment on meet.jit.si itself. The only thing we ask for in that case is that you please DO NOT remove the jitsi.org logo from the top left corner.
|
||||
|
||||
## Installation
|
||||
|
||||
To embed Jitsi Meet in your application you need to add the Jitsi Meet API library:
|
||||
|
||||
```javascript
|
||||
<script src='https://meet.jit.si/external_api.js'></script>
|
||||
```
|
||||
## API
|
||||
|
||||
### `api = new JitsiMeetExternalAPI(domain, options)`
|
||||
|
||||
The next step for embedding Jitsi Meet is to create the Jitsi Meet API object.
|
||||
Its constructor gets a number of options:
|
||||
|
||||
* **domain**: domain used to build the conference URL, 'meet.jit.si' for
|
||||
example.
|
||||
* **options**: object with properties - the optional arguments:
|
||||
* **roomName**: (optional) name of the room to join.
|
||||
* **width**: (optional) width for the iframe which will be created. If a number is specified it's treated as pixel units. If a string is specified the format is number followed by 'px', 'em', 'pt' or '%'.
|
||||
* **height**: (optional) height for the iframe which will be created. If a number is specified it's treated as pixel units. If a string is specified the format is number followed by 'px', 'em', 'pt' or '%'.
|
||||
* **parentNode**: (optional) HTML DOM Element where the iframe will be added as a child.
|
||||
* **configOverwrite**: (optional) JS object with overrides for options defined in [config.js].
|
||||
* **interfaceConfigOverwrite**: (optional) JS object with overrides for options defined in [interface_config.js].
|
||||
* **noSSL**: (optional, defaults to true) Boolean indicating if the server should be contacted using HTTP or HTTPS.
|
||||
* **jwt**: (optional) [JWT](https://jwt.io/) token.
|
||||
* **onload**: (optional) handler for the iframe onload event.
|
||||
* **invitees**: (optional) Array of objects containing information about new participants that will be invited in the call.
|
||||
* **devices**: (optional) A map containing information about the initial devices that will be used in the call.
|
||||
* **userInfo**: (optional) JS object containing information about the participant opening the meeting, such as `email`.
|
||||
|
||||
Example:
|
||||
|
||||
```javascript
|
||||
const domain = 'meet.jit.si';
|
||||
const options = {
|
||||
roomName: 'JitsiMeetAPIExample',
|
||||
width: 700,
|
||||
height: 700,
|
||||
parentNode: document.querySelector('#meet')
|
||||
};
|
||||
const api = new JitsiMeetExternalAPI(domain, options);
|
||||
```
|
||||
|
||||
You can set the initial media devices for the call:
|
||||
|
||||
```javascript
|
||||
const domain = 'meet.jit.si';
|
||||
const options = {
|
||||
...
|
||||
devices: {
|
||||
audioInput: '<deviceLabel>',
|
||||
audioOutput: '<deviceLabel>',
|
||||
videoInput: '<deviceLabel>'
|
||||
},
|
||||
...
|
||||
};
|
||||
const api = new JitsiMeetExternalAPI(domain, options);
|
||||
```
|
||||
|
||||
You can overwrite options set in [config.js] and [interface_config.js].
|
||||
For example, to enable the filmstrip-only interface mode, you can use:
|
||||
|
||||
```javascript
|
||||
const options = {
|
||||
...
|
||||
interfaceConfigOverwrite: { filmStripOnly: true },
|
||||
...
|
||||
};
|
||||
const api = new JitsiMeetExternalAPI(domain, options);
|
||||
```
|
||||
|
||||
You can also pass a jwt token to Jitsi Meet:
|
||||
|
||||
```javascript
|
||||
const options = {
|
||||
...
|
||||
jwt: '<jwt_token>',
|
||||
noSsl: false,
|
||||
...
|
||||
};
|
||||
const api = new JitsiMeetExternalAPI(domain, options);
|
||||
```
|
||||
|
||||
You can set the userInfo(email, display name) for the call:
|
||||
|
||||
```javascript
|
||||
var domain = "meet.jit.si";
|
||||
var options = {
|
||||
...
|
||||
userInfo: {
|
||||
email: 'email@jitsiexamplemail.com',
|
||||
displayName: 'John Doe'
|
||||
}
|
||||
}
|
||||
var api = new JitsiMeetExternalAPI(domain, options);
|
||||
```
|
||||
|
||||
### Controlling the embedded Jitsi Meet Conference
|
||||
|
||||
Device management `JitsiMeetExternalAPI` methods:
|
||||
* **getAvailableDevices** - Retrieve a list of available devices.
|
||||
|
||||
```javascript
|
||||
api.getAvailableDevices().then(devices => {
|
||||
// devices = {
|
||||
// audioInput: [{
|
||||
// deviceId: 'ID'
|
||||
// groupId: 'grpID'
|
||||
// kind: 'audioinput'
|
||||
// label: 'label'
|
||||
// },....],
|
||||
// audioOutput: [{
|
||||
// deviceId: 'ID'
|
||||
// groupId: 'grpID'
|
||||
// kind: 'audioOutput'
|
||||
// label: 'label'
|
||||
// },....],
|
||||
// videoInput: [{
|
||||
// deviceId: 'ID'
|
||||
// groupId: 'grpID'
|
||||
// kind: 'videoInput'
|
||||
// label: 'label'
|
||||
// },....]
|
||||
// }
|
||||
...
|
||||
});
|
||||
```
|
||||
* **getCurrentDevices** - Retrieve a list with the devices that are currently selected.
|
||||
|
||||
```javascript
|
||||
api.getCurrentDevices().then(devices => {
|
||||
// devices = {
|
||||
// audioInput: {
|
||||
// deviceId: 'ID'
|
||||
// groupId: 'grpID'
|
||||
// kind: 'videoInput'
|
||||
// label: 'label'
|
||||
// },
|
||||
// audioOutput: {
|
||||
// deviceId: 'ID'
|
||||
// groupId: 'grpID'
|
||||
// kind: 'videoInput'
|
||||
// label: 'label'
|
||||
// },
|
||||
// videoInput: {
|
||||
// deviceId: 'ID'
|
||||
// groupId: 'grpID'
|
||||
// kind: 'videoInput'
|
||||
// label: 'label'
|
||||
// }
|
||||
// }
|
||||
...
|
||||
});
|
||||
```
|
||||
* **isDeviceChangeAvailable** - Resolves with true if the device change is available and with false if not.
|
||||
|
||||
```javascript
|
||||
// The accepted deviceType values are - 'output', 'input' or undefined.
|
||||
api.isDeviceChangeAvailable(deviceType).then(isDeviceChangeAvailable => {
|
||||
...
|
||||
});
|
||||
```
|
||||
* **isDeviceListAvailable** - Resolves with true if the device list is available and with false if not.
|
||||
|
||||
```javascript
|
||||
api.isDeviceListAvailable().then(isDeviceListAvailable => {
|
||||
...
|
||||
});
|
||||
```
|
||||
* **isMultipleAudioInputSupported** - Resolves with true if multiple audio input is supported and with false if not.
|
||||
|
||||
```javascript
|
||||
api.isMultipleAudioInputSupported().then(isMultipleAudioInputSupported => {
|
||||
...
|
||||
});
|
||||
```
|
||||
* **setAudioInputDevice** - Sets the audio input device to the one with the label or id that is passed.
|
||||
|
||||
```javascript
|
||||
api.setAudioInputDevice(deviceLabel, deviceId);
|
||||
```
|
||||
* **setAudioOutputDevice** - Sets the audio output device to the one with the label or id that is passed.
|
||||
|
||||
```javascript
|
||||
api.setAudioOutputDevice(deviceLabel, deviceId);
|
||||
```
|
||||
* **setVideoInputDevice** - Sets the video input device to the one with the label or id that is passed.
|
||||
|
||||
```javascript
|
||||
api.setVideoInputDevice(deviceLabel, deviceId);
|
||||
```
|
||||
|
||||
You can control the embedded Jitsi Meet conference using the `JitsiMeetExternalAPI` object by using `executeCommand`:
|
||||
|
||||
```javascript
|
||||
api.executeCommand(command, ...arguments);
|
||||
```
|
||||
|
||||
The `command` parameter is String object with the name of the command. The following commands are currently supported:
|
||||
|
||||
* **displayName** - Sets the display name of the local participant. This command requires one argument - the new display name to be set.
|
||||
```javascript
|
||||
api.executeCommand('displayName', 'New Nickname');
|
||||
```
|
||||
|
||||
* **password** - Sets the password for the room. This command requires one argument - the password name to be set.
|
||||
```javascript
|
||||
api.executeCommand('password', 'The Password');
|
||||
```
|
||||
|
||||
* **sendTones** - Play touch tones.
|
||||
```javascript
|
||||
api.executeCommand('sendTones', {
|
||||
tones: string, // The dial pad touch tones to play. For example, '12345#'.
|
||||
duration: number, // Optional. The number of milliseconds each tone should play. The default is 200.
|
||||
pause: number // Optional. The number of milliseconds between each tone. The default is 200.
|
||||
});
|
||||
```
|
||||
|
||||
* **subject** - Sets the subject of the conference. This command requires one argument - the new subject to be set.
|
||||
```javascript
|
||||
api.executeCommand('subject', 'New Conference Subject');
|
||||
```
|
||||
|
||||
* **toggleAudio** - Mutes / unmutes the audio for the local participant. No arguments are required.
|
||||
```javascript
|
||||
api.executeCommand('toggleAudio');
|
||||
```
|
||||
|
||||
* **toggleVideo** - Mutes / unmutes the video for the local participant. No arguments are required.
|
||||
```javascript
|
||||
api.executeCommand('toggleVideo');
|
||||
```
|
||||
|
||||
* **toggleFilmStrip** - Hides / shows the filmstrip. No arguments are required.
|
||||
```javascript
|
||||
api.executeCommand('toggleFilmStrip');
|
||||
```
|
||||
|
||||
* **toggleChat** - Hides / shows the chat. No arguments are required.
|
||||
```javascript
|
||||
api.executeCommand('toggleChat');
|
||||
```
|
||||
|
||||
* **toggleShareScreen** - Starts / stops screen sharing. No arguments are required.
|
||||
```javascript
|
||||
api.executeCommand('toggleShareScreen');
|
||||
```
|
||||
|
||||
* **toggleTileView** - Enter / exit tile view layout mode. No arguments are required.
|
||||
```javascript
|
||||
api.executeCommand('toggleTileView');
|
||||
```
|
||||
|
||||
* **hangup** - Hangups the call. No arguments are required.
|
||||
```javascript
|
||||
api.executeCommand('hangup');
|
||||
```
|
||||
|
||||
* **email** - Changes the local email address. This command requires one argument - the new email address to be set.
|
||||
```javascript
|
||||
api.executeCommand('email', 'example@example.com');
|
||||
```
|
||||
|
||||
* **avatarUrl** - Changes the local avatar URL. This command requires one argument - the new avatar URL to be set.
|
||||
```javascript
|
||||
api.executeCommand('avatarUrl', 'https://avatars0.githubusercontent.com/u/3671647');
|
||||
```
|
||||
|
||||
* **sendEndpointTextMessage** - Sends a text message to another participant through the datachannels.
|
||||
```javascript
|
||||
api.executeCommand('receiverParticipantId', 'text');
|
||||
```
|
||||
|
||||
You can also execute multiple commands using the `executeCommands` method:
|
||||
```javascript
|
||||
api.executeCommands(commands);
|
||||
```
|
||||
The `commands` parameter is an object with the names of the commands as keys and the arguments for the commands as values:
|
||||
```javascript
|
||||
api.executeCommands({
|
||||
displayName: [ 'nickname' ],
|
||||
toggleAudio: []
|
||||
});
|
||||
```
|
||||
|
||||
You can add event listeners to the embedded Jitsi Meet using the `addEventListener` method.
|
||||
**NOTE: This method still exists but it is deprecated. JitsiMeetExternalAPI class extends [EventEmitter]. Use [EventEmitter] methods (`addListener` or `on`).**
|
||||
```javascript
|
||||
api.addEventListener(event, listener);
|
||||
```
|
||||
|
||||
The `event` parameter is a String object with the name of the event.
|
||||
The `listener` parameter is a Function object with one argument that will be notified when the event occurs with data related to the event.
|
||||
|
||||
The following events are currently supported:
|
||||
* **cameraError** - event notifications about Jitsi-Meet having failed to access the camera. The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
type: string, // A constant representing the overall type of the error.
|
||||
message: string // Additional information about the error.
|
||||
}
|
||||
```
|
||||
|
||||
* **avatarChanged** - event notifications about avatar
|
||||
changes. The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
id: string, // the id of the participant that changed his avatar.
|
||||
avatarURL: string // the new avatar URL.
|
||||
}
|
||||
```
|
||||
|
||||
* **audioAvailabilityChanged** - event notifications about audio availability status changes. The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
available: boolean // new available status - boolean
|
||||
}
|
||||
```
|
||||
|
||||
* **audioMuteStatusChanged** - event notifications about audio mute status changes. The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
muted: boolean // new muted status - boolean
|
||||
}
|
||||
```
|
||||
|
||||
* **endpointTextMessageReceived** - event notifications about a text message received through datachannels.
|
||||
The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
senderInfo: {
|
||||
jid: string, // the jid of the sender
|
||||
id: string // the participant id of the sender
|
||||
},
|
||||
eventData: {
|
||||
name: string // the name of the datachannel event: `endpoint-text-message`
|
||||
text: string // the received text from the sender
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* **micError** - event notifications about Jitsi-Meet having failed to access the mic. The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
type: string, // A constant representing the overall type of the error.
|
||||
message: string // Additional information about the error.
|
||||
}
|
||||
```
|
||||
|
||||
* **screenSharingStatusChanged** - receives event notifications about turning on/off the local user screen sharing. The listener will receive object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
on: boolean, //whether screen sharing is on
|
||||
details: {
|
||||
|
||||
// From where the screen sharing is capturing, if known. Values which are
|
||||
// passed include 'window', 'screen', 'proxy', 'device'. The value undefined
|
||||
// will be passed if the source type is unknown or screen share is off.
|
||||
sourceType: string|undefined
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* **dominantSpeakerChanged** - receives event notifications about change in the dominant speaker. The listener will receive object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
id: string //participantId of the new dominant speaker
|
||||
}
|
||||
```
|
||||
|
||||
* **tileViewChanged** - event notifications about tile view layout mode being entered or exited. The listener will receive object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
enabled: boolean, // whether tile view is not displayed or not
|
||||
}
|
||||
```
|
||||
|
||||
* **incomingMessage** - Event notifications about incoming
|
||||
messages. The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
from: string, // The id of the user that sent the message
|
||||
nick: string, // the nickname of the user that sent the message
|
||||
message: string // the text of the message
|
||||
}
|
||||
```
|
||||
|
||||
* **outgoingMessage** - Event notifications about outgoing
|
||||
messages. The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
message: string // the text of the message
|
||||
}
|
||||
```
|
||||
|
||||
* **displayNameChange** - event notifications about display name
|
||||
changes. The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
id: string, // the id of the participant that changed his display name
|
||||
displayname: string // the new display name
|
||||
}
|
||||
```
|
||||
|
||||
* **deviceListChanged** - event notifications about device list changes. The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
devices: Object // the new list of available devices.
|
||||
}
|
||||
```
|
||||
NOTE: The devices object has the same format as the getAvailableDevices result format.
|
||||
|
||||
* **emailChange** - event notifications about email
|
||||
changes. The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
id: string, // the id of the participant that changed his email
|
||||
email: string // the new email
|
||||
}
|
||||
```
|
||||
* **feedbackSubmitted** - event notifications about conference feedback submission
|
||||
```javascript
|
||||
{
|
||||
error: string // The error which occurred during submission, if any.
|
||||
}
|
||||
```
|
||||
|
||||
* **filmstripDisplayChanged** - event notifications about the visibility of the filmstrip being updated.
|
||||
```javascript
|
||||
{
|
||||
visible: boolean // Whether or not the filmstrip is displayed or hidden.
|
||||
}
|
||||
```
|
||||
|
||||
* **participantJoined** - event notifications about new participants who join the room. The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
id: string, // the id of the participant
|
||||
displayName: string // the display name of the participant
|
||||
}
|
||||
```
|
||||
|
||||
* **participantKickedOut** - event notifications about a participants being removed from the room. The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
kicked: {
|
||||
id: string, // the id of the participant removed from the room
|
||||
local: boolean // whether or not the participant is the local particiapnt
|
||||
},
|
||||
kicker: {
|
||||
id: string // the id of the participant who kicked out the other participant
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* **participantLeft** - event notifications about participants that leave the room. The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
id: string // the id of the participant
|
||||
}
|
||||
```
|
||||
|
||||
* **passwordRequired** - event notifications fired when failing to join a room because it has a password.
|
||||
|
||||
* **videoConferenceJoined** - event notifications fired when the local user has joined the video conference. The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
roomName: string, // the room name of the conference
|
||||
id: string, // the id of the local participant
|
||||
displayName: string, // the display name of the local participant
|
||||
avatarURL: string // the avatar URL of the local participant
|
||||
}
|
||||
```
|
||||
|
||||
* **videoConferenceLeft** - event notifications fired when the local user has left the video conference. The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
roomName: string // the room name of the conference
|
||||
}
|
||||
```
|
||||
|
||||
* **videoAvailabilityChanged** - event notifications about video availability status changes. The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
available: boolean // new available status - boolean
|
||||
}
|
||||
```
|
||||
|
||||
* **videoMuteStatusChanged** - event notifications about video mute status changes. The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
muted: boolean // new muted status - boolean
|
||||
}
|
||||
```
|
||||
|
||||
* **readyToClose** - event notification fired when Jitsi Meet is ready to be closed (hangup operations are completed).
|
||||
|
||||
* **subjectChange** - event notifications about subject of conference changes.
|
||||
The listener will receive an object with the following structure:
|
||||
```javascript
|
||||
{
|
||||
subject: string // the new subject
|
||||
}
|
||||
```
|
||||
|
||||
* **suspendDetected** - event notifications about detecting suspend event in host computer.
|
||||
|
||||
You can also add multiple event listeners by using `addEventListeners`.
|
||||
This method requires one argument of type Object. The object argument must
|
||||
have the names of the events as keys and the listeners of the events as values.
|
||||
**NOTE: This method still exists but it is deprecated. JitsiMeetExternalAPI class extends [EventEmitter]. Use [EventEmitter] methods.**
|
||||
|
||||
```javascript
|
||||
function incomingMessageListener(object)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
function outgoingMessageListener(object)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
api.addEventListeners({
|
||||
incomingMessage: incomingMessageListener,
|
||||
outgoingMessage: outgoingMessageListener
|
||||
});
|
||||
```
|
||||
|
||||
If you want to remove a listener you can use `removeEventListener` method with argument the name of the event.
|
||||
**NOTE: This method still exists but it is deprecated. JitsiMeetExternalAPI class extends [EventEmitter]. Use [EventEmitter] methods( `removeListener`).**
|
||||
```javascript
|
||||
api.removeEventListener('incomingMessage');
|
||||
```
|
||||
|
||||
If you want to remove more than one event you can use `removeEventListeners` method with an Array with the names of the events as an argument.
|
||||
**NOTE: This method still exists but it is deprecated. JitsiMeetExternalAPI class extends [EventEmitter]. Use [EventEmitter] methods.**
|
||||
```javascript
|
||||
api.removeEventListeners([ 'incomingMessage', 'outgoingMessageListener' ]);
|
||||
```
|
||||
|
||||
You can get the number of participants in the conference with the following API function:
|
||||
```javascript
|
||||
const numberOfParticipants = api.getNumberOfParticipants();
|
||||
```
|
||||
|
||||
You can get the avatar URL of a participant in the conference with the following API function:
|
||||
```javascript
|
||||
const avatarURL = api.getAvatarURL(participantId);
|
||||
```
|
||||
|
||||
You can get the display name of a participant in the conference with the following API function:
|
||||
```javascript
|
||||
const displayName = api.getDisplayName(participantId);
|
||||
```
|
||||
|
||||
You can get the email of a participant in the conference with the following API function:
|
||||
```javascript
|
||||
const email = api.getEmail(participantId);
|
||||
```
|
||||
|
||||
You can get the iframe HTML element where Jitsi Meet is loaded with the following API function:
|
||||
```javascript
|
||||
const iframe = api.getIFrame();
|
||||
```
|
||||
|
||||
You can check whether the audio is muted with the following API function:
|
||||
```javascript
|
||||
api.isAudioMuted().then(muted => {
|
||||
...
|
||||
});
|
||||
```
|
||||
|
||||
You can check whether the video is muted with the following API function:
|
||||
```javascript
|
||||
api.isVideoMuted().then(muted => {
|
||||
...
|
||||
});
|
||||
```
|
||||
|
||||
You can check whether the audio is available with the following API function:
|
||||
```javascript
|
||||
api.isAudioAvailable().then(available => {
|
||||
...
|
||||
});
|
||||
```
|
||||
|
||||
You can check whether the video is available with the following API function:
|
||||
```javascript
|
||||
api.isVideoAvailable().then(available => {
|
||||
...
|
||||
});
|
||||
```
|
||||
|
||||
You can invite new participants to the call with the following API function:
|
||||
```javascript
|
||||
api.invite([ {...}, {...}, {...} ]).then(() => {
|
||||
// success
|
||||
}).catch(() => {
|
||||
// failure
|
||||
});
|
||||
```
|
||||
**NOTE: The format of the invitees in the array depends on the invite service used for the deployment.**
|
||||
|
||||
You can remove the embedded Jitsi Meet Conference with the following API function:
|
||||
```javascript
|
||||
api.dispose();
|
||||
```
|
||||
|
||||
NOTE: It's a good practice to remove the conference before the page is unloaded.
|
||||
|
||||
[config.js]: https://github.com/jitsi/jitsi-meet/blob/master/config.js
|
||||
[interface_config.js]: https://github.com/jitsi/jitsi-meet/blob/master/interface_config.js
|
||||
[EventEmitter]: https://nodejs.org/api/events.html
|
||||
This document has been moved [here](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-iframe).
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# Jitsi Meet Cloud API
|
||||
|
||||
The Jitsi Meet Cloud API is a specification for services which can support the integration of Jitsi Meet into other applications, for mapping conferences for dial-in support, and for supporting directory search and user invitations to conferences.
|
||||
|
||||
The swagger for these services is provided in [cloud-api.swagger](cloud-api.swagger) in this same repository and directory.
|
||||
@@ -1,93 +0,0 @@
|
||||
# Comments
|
||||
|
||||
* Comments documenting the source code are required.
|
||||
|
||||
* Comments from which documentation is automatically generated are **not**
|
||||
subject to case-by-case decisions. Such comments are used, for example, on
|
||||
types and their members. Examples of tools which automatically generate
|
||||
documentation from such comments include JSDoc, Javadoc, Doxygen.
|
||||
|
||||
* Comments which are not automatically processed are strongly encouraged. They
|
||||
are subject to case-by-case decisions. Such comments are often observed in
|
||||
function bodies.
|
||||
|
||||
* Comments should be formatted as proper English sentences. Such formatting pays
|
||||
attention to, for example, capitalization and punctuation.
|
||||
|
||||
# Duplication
|
||||
|
||||
* Don't copy-paste source code. Reuse it.
|
||||
|
||||
# Formatting
|
||||
|
||||
* Line length is limited to 80 characters.
|
||||
|
||||
* Sort by alphabetical order in order to make the addition of new entities as
|
||||
easy as looking a word up in a dictionary. Otherwise, one risks duplicate
|
||||
entries (with conflicting values in the cases of key-value pairs). For
|
||||
example:
|
||||
|
||||
* Within an `import` of multiple names from a module, sort the names in
|
||||
alphabetical order. (Of course, the default name stays first as required by
|
||||
the `import` syntax.)
|
||||
|
||||
````javascript
|
||||
import {
|
||||
DOMINANT_SPEAKER_CHANGED,
|
||||
JITSI_CLIENT_CONNECTED,
|
||||
JITSI_CLIENT_CREATED,
|
||||
JITSI_CLIENT_DISCONNECTED,
|
||||
JITSI_CLIENT_ERROR,
|
||||
JITSI_CONFERENCE_JOINED,
|
||||
MODERATOR_CHANGED,
|
||||
PEER_JOINED,
|
||||
PEER_LEFT,
|
||||
RTC_ERROR
|
||||
} from './actionTypes';
|
||||
````
|
||||
|
||||
* Within a group of imports (e.g. groups of imports delimited by an empty line
|
||||
may be: third-party modules, then project modules, and eventually the
|
||||
private files of a module), sort the module names in alphabetical order.
|
||||
|
||||
````javascript
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
````
|
||||
|
||||
# Indentation
|
||||
|
||||
* Align `switch` and `case`/`default`. Don't indent the `case`/`default` more
|
||||
than its `switch`.
|
||||
|
||||
````javascript
|
||||
switch (i) {
|
||||
case 0:
|
||||
...
|
||||
break;
|
||||
default:
|
||||
...
|
||||
}
|
||||
````
|
||||
|
||||
# Naming
|
||||
|
||||
* An abstraction should have one name within the project and across multiple
|
||||
projects. For example:
|
||||
|
||||
* The instance of lib-jitsi-meet's `JitsiConnection` type should be named
|
||||
`connection` or `jitsiConnection` in jitsi-meet, not `client`.
|
||||
|
||||
* The class `ReducerRegistry` should be defined in ReducerRegistry.js and its
|
||||
imports in other files should use the same name. Don't define the class
|
||||
`Registry` in ReducerRegistry.js and then import it as `Reducers` in other
|
||||
files.
|
||||
|
||||
* The names of global constants (including ES6 module-global constants) should
|
||||
be written in uppercase with underscores to separate words. For example,
|
||||
`BACKGROUND_COLOR`.
|
||||
|
||||
* The underscore character at the beginning of a name signals that the
|
||||
respective variable, function, property is non-public i.e. private, protected,
|
||||
or internal. In contrast, the lack of an underscore at the beginning of a name
|
||||
signals public API.
|
||||
@@ -13,6 +13,13 @@ turncredentials = {
|
||||
|
||||
cross_domain_bosh = false;
|
||||
consider_bosh_secure = true;
|
||||
-- https_ports = { }; -- Remove this line to prevent listening on port 5284
|
||||
|
||||
-- https://ssl-config.mozilla.org/#server=haproxy&version=2.1&config=intermediate&openssl=1.1.0g&guideline=5.4
|
||||
ssl = {
|
||||
protocol = "tlsv1_2+";
|
||||
ciphers = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"
|
||||
}
|
||||
|
||||
VirtualHost "jitmeet.example.com"
|
||||
-- enabled = false -- Remove this line to enable this host
|
||||
@@ -39,8 +46,12 @@ VirtualHost "jitmeet.example.com"
|
||||
"speakerstats";
|
||||
"turncredentials";
|
||||
"conference_duration";
|
||||
"muc_lobby_rooms";
|
||||
}
|
||||
c2s_require_encryption = false
|
||||
lobby_muc = "lobby.jitmeet.example.com"
|
||||
main_muc = "conference.jitmeet.example.com"
|
||||
-- muc_lobby_whitelist = { "recorder.jitmeet.example.com" } -- Here we can whitelist jibri to enter lobby enabled rooms
|
||||
|
||||
Component "conference.jitmeet.example.com" "muc"
|
||||
storage = "memory"
|
||||
@@ -74,3 +85,9 @@ Component "speakerstats.jitmeet.example.com" "speakerstats_component"
|
||||
|
||||
Component "conferenceduration.jitmeet.example.com" "conference_duration_component"
|
||||
muc_component = "conference.jitmeet.example.com"
|
||||
|
||||
Component "lobby.jitmeet.example.com" "muc"
|
||||
storage = "memory"
|
||||
restrict_room_creation = true
|
||||
muc_room_locking = false
|
||||
muc_room_default_public_jids = true
|
||||
|
||||
@@ -10,5 +10,9 @@ no-tcp
|
||||
listening-port=4446
|
||||
tls-listening-port=4445
|
||||
external-ip=__external_ip_address__
|
||||
no-tlsv1
|
||||
no-tlsv1_1
|
||||
# https://ssl-config.mozilla.org/#server=haproxy&version=2.1&config=intermediate&openssl=1.1.0g&guideline=5.4
|
||||
cipher-list=ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
|
||||
|
||||
syslog
|
||||
|
||||
@@ -21,11 +21,16 @@ server {
|
||||
listen [::]:443 ssl;
|
||||
server_name jitsi-meet.example.com;
|
||||
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_ciphers "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA256:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EDH+aRSA+AESGCM:EDH+aRSA+SHA256:EDH+aRSA:EECDH:!aNULL:!eNULL:!MEDIUM:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED";
|
||||
# Mozilla Guideline v5.4, nginx 1.17.7, OpenSSL 1.1.1d, intermediate configuration
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
add_header Strict-Transport-Security "max-age=31536000";
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_cache shared:SSL:10m; # about 40000 sessions
|
||||
ssl_session_tickets off;
|
||||
|
||||
add_header Strict-Transport-Security "max-age=63072000" always;
|
||||
|
||||
ssl_certificate /etc/jitsi/meet/jitsi-meet.example.com.crt;
|
||||
ssl_certificate_key /etc/jitsi/meet/jitsi-meet.example.com.key;
|
||||
|
||||
@@ -11,14 +11,15 @@
|
||||
|
||||
ServerName jitsi-meet.example.com
|
||||
|
||||
SSLProtocol TLSv1 TLSv1.1 TLSv1.2
|
||||
# enable HTTP/2, if available
|
||||
Protocols h2 http/1.1
|
||||
|
||||
SSLEngine on
|
||||
SSLProxyEngine on
|
||||
SSLCertificateFile /etc/jitsi/meet/jitsi-meet.example.com.crt
|
||||
SSLCertificateKeyFile /etc/jitsi/meet/jitsi-meet.example.com.key
|
||||
SSLCipherSuite "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA256:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EDH+aRSA+AESGCM:EDH+aRSA+SHA256:EDH+aRSA:EECDH:!aNULL:!eNULL:!MEDIUM:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED"
|
||||
SSLHonorCipherOrder on
|
||||
Header set Strict-Transport-Security "max-age=31536000"
|
||||
|
||||
Header always set Strict-Transport-Security "max-age=63072000"
|
||||
|
||||
DocumentRoot "/usr/share/jitsi-meet"
|
||||
<Directory "/usr/share/jitsi-meet">
|
||||
@@ -48,3 +49,9 @@
|
||||
RewriteEngine on
|
||||
RewriteRule ^/([a-zA-Z0-9]+)$ /index.html
|
||||
</VirtualHost>
|
||||
|
||||
# Mozilla Guideline v5.4, Apache 2.4.41, OpenSSL 1.1.1d, intermediate configuration, no OCSP
|
||||
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
|
||||
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
|
||||
SSLHonorCipherOrder off
|
||||
SSLSessionTickets off
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
# Developing Jitsi Meet
|
||||
|
||||
## Building the sources
|
||||
|
||||
Node.js >= 10 and npm >= 6 are required.
|
||||
|
||||
On Debian/Ubuntu systems, the required packages can be installed with:
|
||||
```
|
||||
sudo apt-get install npm nodejs
|
||||
cd jitsi-meet
|
||||
npm install
|
||||
```
|
||||
|
||||
To build the Jitsi Meet application, just type
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
### Working with the library sources (lib-jitsi-meet)
|
||||
|
||||
By default the library is build from its git repository sources. The default dependency path in package.json is :
|
||||
```json
|
||||
"lib-jitsi-meet": "jitsi/lib-jitsi-meet",
|
||||
```
|
||||
|
||||
To work with local copy you must change the path to:
|
||||
```json
|
||||
"lib-jitsi-meet": "file:///Users/name/local-lib-jitsi-meet-copy",
|
||||
```
|
||||
|
||||
To make the project you must force it to take the sources as 'npm update':
|
||||
```
|
||||
npm install lib-jitsi-meet --force && make
|
||||
```
|
||||
|
||||
Or if you are making only changes to the library:
|
||||
```
|
||||
npm install lib-jitsi-meet --force && make deploy-lib-jitsi-meet
|
||||
```
|
||||
|
||||
Alternative way is to use [npm link](https://docs.npmjs.com/cli/link).
|
||||
It allows to link `lib-jitsi-meet` dependency to local source in few steps:
|
||||
|
||||
```bash
|
||||
cd lib-jitsi-meet
|
||||
|
||||
#### create global symlink for lib-jitsi-meet package
|
||||
npm link
|
||||
|
||||
cd ../jitsi-meet
|
||||
|
||||
#### create symlink from the local node_modules folder to the global lib-jitsi-meet symlink
|
||||
npm link lib-jitsi-meet
|
||||
```
|
||||
|
||||
After changes in local `lib-jitsi-meet` repository, you can rebuild it with `npm run install` and your `jitsi-meet` repository will use that modified library.
|
||||
Note: when using node version 4.x, the make file of jitsi-meet do npm update which will delete the link. It is no longer the case with version 6.x.
|
||||
|
||||
If you do not want to use local repository anymore you should run
|
||||
```bash
|
||||
cd jitsi-meet
|
||||
npm unlink lib-jitsi-meet
|
||||
npm install
|
||||
```
|
||||
### Running with webpack-dev-server for development
|
||||
|
||||
Use it at the CLI, type
|
||||
```
|
||||
make dev
|
||||
```
|
||||
|
||||
By default the backend deployment used is `alpha.jitsi.net`. You can point the Jitsi-Meet app at a different backend by using a proxy server. To do this, set the WEBPACK_DEV_SERVER_PROXY_TARGET variable:
|
||||
```
|
||||
export WEBPACK_DEV_SERVER_PROXY_TARGET=https://your-example-server.com
|
||||
make dev
|
||||
```
|
||||
|
||||
The app should be running at https://localhost:8080/
|
||||
|
||||
#### Chrome Privacy Error
|
||||
|
||||
Newer versions of Chrome may block localhost under https and show `NET::ERR_CERT_INVALID` on the page. To solve this open [chrome://flags/#allow-insecure-localhost](chrome://flags/#allow-insecure-localhost) and select Enable, then press Relaunch or quit and restart Chrome.
|
||||
@@ -1,7 +0,0 @@
|
||||
**1. How to tell if my server instance is behind NAT?**
|
||||
|
||||
A. In general, if the tool ifconfig (or ipconfig) shows the assigned IP address to be some local address (10.x.x.x or 192.x.x.x) but you know that its public IP address is different from that, the server is most probably behind NAT
|
||||
|
||||
**2. Clients could communicate well in room created at meet.jit.si . The same clients still could connect to my self-hosted instance but can neither hear nor see one another. What's wrong?**
|
||||
|
||||
A. Most probably, the server is behind NAT. See this [resolved question](https://community.jitsi.org/t/cannot-see-video-or-hear-audio-on-self-hosted-instance/). You need to follow the steps detailed [here](https://github.com/jitsi/jitsi-meet/blob/master/doc/quick-install.md#Advanced-configuration)
|
||||
@@ -1,38 +0,0 @@
|
||||
Document describing enabling various jitsi-meet integrations.
|
||||
|
||||
## Creating the Google API client for Google Calendar and Youtube integration
|
||||
1. Log into a Google admin account.
|
||||
1. Go to Google cloud platform dashboard. https://console.cloud.google.com/apis/dashboard
|
||||
1. In the Select a Project dropdown, click New Project.
|
||||
1. Give the project a name.
|
||||
1. Proceed to the Credentials settings of the new project.
|
||||
1. In the Credentials tab of the Credentials settings, click Create Credentials and select the type OAuth client ID.
|
||||
1. Proceed with creating a Web application and add the domains (origins) on which the application will be hosted. Local development environments (http://localhost:8000 for example) can be added here.
|
||||
1. While still in the Google cloud platform dashboard, click the Library settings for the calendar project.
|
||||
1. Search for the Google Calendar API (used for calendar accessing), click its result, and enable it.
|
||||
1. Do the same for YouTube Data API v3
|
||||
|
||||
## Creating the Microsoft app for Microsoft Outlook integration
|
||||
1. Go to https://apps.dev.microsoft.com/
|
||||
1. Proceed through the "Add an app" flow. Once created, a page with several Graph Permissions fields should display.
|
||||
1. Under "Platforms" add "Web"
|
||||
1. Add a redirect URL for the Microsoft auth flow to visit once a user has confirmed authentication. Target domain if available is just 'yourdomain.com' (the deployment address) and the redirect URL is `https://yourdomain.com/static/msredirect.html`.
|
||||
1. Add Microsoft Graph delegated permissions, if this option is available: Calendars.Read, Calendars.ReadWrite, Calendars.Read.Shared, Calendars.ReadWrite.Shared.
|
||||
1. Check `Allow Implicit Flow` (and `Restrict token issuing to this app` if available).
|
||||
1. Save the changes.
|
||||
|
||||
## Creating the Dropbox app for Dropbox recording integration
|
||||
1. You need a Dropbox account (If you don't already have one, you can sign up for a free account [here](https://www.dropbox.com/register).)
|
||||
1. Create new App as described in [Getting Started Guide](https://www.dropbox.com/developers/reference/getting-started?_tk=guides_lp&_ad=guides2&_camp=get_started#app%20console) in App Console section.
|
||||
1. Choose
|
||||
1. 'Dropbox API - For apps that need to access files in Dropbox.'
|
||||
1. 'App folder– Access to a single folder created specifically for your app.'
|
||||
1. Fill in the name of your app
|
||||
1. You need only, the newly created App key, goes in config.js in
|
||||
```
|
||||
dropbox: {
|
||||
appKey: '__dropbox_app_key__'
|
||||
}
|
||||
```
|
||||
1. Add your Redirect URIs in the form `https://yourdeployment.com//static/oauth.html`
|
||||
1. Fill in Branding
|
||||
@@ -1,270 +0,0 @@
|
||||
# Server Installation for Jitsi Meet
|
||||
|
||||
:warning: **WARNING:** Manual installation is not recommended. We recommend following the [quick-install](https://github.com/jitsi/jitsi-meet/blob/master/doc/quick-install.md) document. The current document describes the steps that are needed to install a working deployment, but steps are easy to mess up, and the debian packages are more up-to-date, where this document is sometimes not updated to reflect latest changes.
|
||||
|
||||
This describes configuring a server `jitsi.example.com` running Debian or a Debian Derivative. You will need to
|
||||
change references to that to match your host, and generate some passwords for
|
||||
`YOURSECRET1`, `YOURSECRET2` and `YOURSECRET3`.
|
||||
|
||||
There are also some complete [example config files](https://github.com/jitsi/jitsi-meet/tree/master/doc/example-config-files/) available, mentioned in each section.
|
||||
|
||||
There are additional configurations to be done for a [scalable installation](https://github.com/jitsi/jitsi-meet/tree/master/doc/scalable-installation.md)
|
||||
|
||||
## Network description
|
||||
|
||||
This is how the network looks:
|
||||
```
|
||||
+ +
|
||||
| |
|
||||
| |
|
||||
v |
|
||||
443 |
|
||||
+-------+ |
|
||||
| | |
|
||||
| Nginx | |
|
||||
| | |
|
||||
+--+-+--+ |
|
||||
| | |
|
||||
+------------+ | | +--------------+ |
|
||||
| | | | | | |
|
||||
| jitsi-meet +<---+ +--->+ prosody/xmpp | |
|
||||
| |files 5280 | | |
|
||||
+------------+ +--------------+ v
|
||||
5222,5347^ ^5347 4443,10000
|
||||
+--------+ | | +-------------+
|
||||
| | | | | |
|
||||
| jicofo +----^ ^----+ videobridge |
|
||||
| | | |
|
||||
+--------+ +-------------+
|
||||
```
|
||||
|
||||
## Install prosody
|
||||
```sh
|
||||
apt-get install prosody
|
||||
```
|
||||
|
||||
## Configure prosody
|
||||
Add config file in `/etc/prosody/conf.avail/jitsi.example.com.cfg.lua` :
|
||||
|
||||
- add your domain virtual host section:
|
||||
|
||||
```
|
||||
VirtualHost "jitsi.example.com"
|
||||
authentication = "anonymous"
|
||||
ssl = {
|
||||
key = "/var/lib/prosody/jitsi.example.com.key";
|
||||
certificate = "/var/lib/prosody/jitsi.example.com.crt";
|
||||
}
|
||||
modules_enabled = {
|
||||
"bosh";
|
||||
"pubsub";
|
||||
}
|
||||
c2s_require_encryption = false
|
||||
```
|
||||
- add domain with authentication for conference focus user:
|
||||
```
|
||||
VirtualHost "auth.jitsi.example.com"
|
||||
ssl = {
|
||||
key = "/var/lib/prosody/auth.jitsi.example.com.key";
|
||||
certificate = "/var/lib/prosody/auth.jitsi.example.com.crt";
|
||||
}
|
||||
authentication = "internal_plain"
|
||||
```
|
||||
- add focus user to server admins:
|
||||
```
|
||||
admins = { "focus@auth.jitsi.example.com" }
|
||||
```
|
||||
- and finally configure components:
|
||||
```
|
||||
Component "conference.jitsi.example.com" "muc"
|
||||
Component "jitsi-videobridge.jitsi.example.com"
|
||||
component_secret = "YOURSECRET1"
|
||||
Component "focus.jitsi.example.com"
|
||||
component_secret = "YOURSECRET2"
|
||||
```
|
||||
|
||||
Add link for the added configuration
|
||||
```sh
|
||||
ln -s /etc/prosody/conf.avail/jitsi.example.com.cfg.lua /etc/prosody/conf.d/jitsi.example.com.cfg.lua
|
||||
```
|
||||
|
||||
Generate certs for the domain:
|
||||
```sh
|
||||
prosodyctl cert generate jitsi.example.com
|
||||
prosodyctl cert generate auth.jitsi.example.com
|
||||
```
|
||||
|
||||
Add auth.jitsi.example.com to the trusted certificates on the local machine:
|
||||
```sh
|
||||
ln -sf /var/lib/prosody/auth.jitsi.example.com.crt /usr/local/share/ca-certificates/auth.jitsi.example.com.crt
|
||||
update-ca-certificates -f
|
||||
```
|
||||
Note that the `-f` flag is necessary if there are symlinks left from a previous installation.
|
||||
|
||||
Create conference focus user:
|
||||
```sh
|
||||
prosodyctl register focus auth.jitsi.example.com YOURSECRET3
|
||||
```
|
||||
|
||||
Restart prosody XMPP server with the new config
|
||||
```sh
|
||||
prosodyctl restart
|
||||
```
|
||||
|
||||
## Install Nginx
|
||||
```sh
|
||||
apt-get install nginx
|
||||
```
|
||||
|
||||
Add a new file `jitsi.example.com` in `/etc/nginx/sites-available` (see also the example config file):
|
||||
```
|
||||
server_names_hash_bucket_size 64;
|
||||
|
||||
server {
|
||||
listen 0.0.0.0:443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
# tls configuration that is not covered in this guide
|
||||
# we recommend the use of https://certbot.eff.org/
|
||||
server_name jitsi.example.com;
|
||||
# set the root
|
||||
root /srv/jitsi-meet;
|
||||
index index.html;
|
||||
location ~ ^/([a-zA-Z0-9=\?]+)$ {
|
||||
rewrite ^/(.*)$ / break;
|
||||
}
|
||||
location / {
|
||||
ssi on;
|
||||
}
|
||||
# BOSH, Bidirectional-streams Over Synchronous HTTP
|
||||
# https://en.wikipedia.org/wiki/BOSH_(protocol)
|
||||
location /http-bind {
|
||||
proxy_pass http://localhost:5280/http-bind;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header Host $http_host;
|
||||
}
|
||||
# external_api.js must be accessible from the root of the
|
||||
# installation for the electron version of Jitsi Meet to work
|
||||
# https://github.com/jitsi/jitsi-meet-electron
|
||||
location /external_api.js {
|
||||
alias /srv/jitsi-meet/libs/external_api.min.js;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Add link for the added configuration
|
||||
```sh
|
||||
cd /etc/nginx/sites-enabled
|
||||
ln -s ../sites-available/jitsi.example.com jitsi.example.com
|
||||
```
|
||||
|
||||
## Install Jitsi Videobridge
|
||||
Visit https://download.jitsi.org/jitsi-videobridge/linux to determine the current build number, download and unzip it:
|
||||
```sh
|
||||
wget https://download.jitsi.org/jitsi-videobridge/linux/jitsi-videobridge-linux-{arch-buildnum}.zip
|
||||
unzip jitsi-videobridge-linux-{arch-buildnum}.zip
|
||||
```
|
||||
|
||||
Install JRE if missing:
|
||||
```
|
||||
apt-get install openjdk-8-jre
|
||||
```
|
||||
|
||||
_NOTE: When installing on older Debian releases keep in mind that you need JRE >= 1.7._
|
||||
|
||||
Create `~/.sip-communicator/sip-communicator.properties` in the home folder of the user that will be starting Jitsi Videobridge:
|
||||
```sh
|
||||
mkdir -p ~/.sip-communicator
|
||||
cat > ~/.sip-communicator/sip-communicator.properties << EOF
|
||||
org.jitsi.impl.neomedia.transform.srtp.SRTPCryptoContext.checkReplay=false
|
||||
# The videobridge uses 443 by default with 4443 as a fallback, but since we're already
|
||||
# running nginx on 443 in this example doc, we specify 4443 manually to avoid a race condition
|
||||
org.jitsi.videobridge.TCP_HARVESTER_PORT=4443
|
||||
EOF
|
||||
```
|
||||
|
||||
Start the videobridge with:
|
||||
```sh
|
||||
./jvb.sh --host=localhost --domain=jitsi.example.com --port=5347 --secret=YOURSECRET1 &
|
||||
```
|
||||
Or autostart it by adding the line in `/etc/rc.local`:
|
||||
```sh
|
||||
/bin/bash /root/jitsi-videobridge-linux-{arch-buildnum}/jvb.sh --host=localhost --domain=jitsi.example.com --port=5347 --secret=YOURSECRET1 </dev/null >> /var/log/jvb.log 2>&1
|
||||
```
|
||||
|
||||
## Install Jitsi Conference Focus (jicofo)
|
||||
|
||||
Install JDK and Maven if missing:
|
||||
```
|
||||
apt-get install openjdk-8-jdk maven
|
||||
```
|
||||
|
||||
_NOTE: When installing on older Debian releases keep in mind that you need JDK >= 1.7._
|
||||
|
||||
Clone source from Github repo:
|
||||
```sh
|
||||
git clone https://github.com/jitsi/jicofo.git
|
||||
```
|
||||
Build the package.
|
||||
```sh
|
||||
cd jicofo
|
||||
mvn package -DskipTests -Dassembly.skipAssembly=false
|
||||
```
|
||||
Run jicofo:
|
||||
```sh
|
||||
=======
|
||||
unzip target/jicofo-1.1-SNAPSHOT-archive.zip
|
||||
cd jicofo-1.1-SNAPSHOT-archive'
|
||||
./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
|
||||
Checkout and configure Jitsi Meet:
|
||||
```sh
|
||||
cd /srv
|
||||
git clone https://github.com/jitsi/jitsi-meet.git
|
||||
cd jitsi-meet
|
||||
npm install
|
||||
make
|
||||
```
|
||||
|
||||
_NOTE: When installing on older distributions keep in mind that you need Node.js >= 10 and npm >= 6._
|
||||
|
||||
Edit host names in `/srv/jitsi-meet/config.js` (see also the example config file):
|
||||
```
|
||||
var config = {
|
||||
hosts: {
|
||||
domain: 'jitsi.example.com',
|
||||
muc: 'conference.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
|
||||
//chromeExtensionId: 'diibjkoicjeejcmhdnailmkgecihlobk', // Id of desktop streamer Chrome extension
|
||||
//minChromeExtVersion: '0.1' // Required version of Chrome extension
|
||||
};
|
||||
```
|
||||
|
||||
Verify that nginx config is valid and reload nginx:
|
||||
```sh
|
||||
nginx -t && nginx -s reload
|
||||
```
|
||||
|
||||
## Running behind NAT
|
||||
Jitsi Videobridge can run behind a NAT, provided that both required ports are routed (forwarded) to the machine that it runs on. By default these ports are `TCP/4443` and `UDP/10000`.
|
||||
|
||||
If you do not route these two ports, Jitsi Meet will only work with video for two people, breaking upon 3 or more people trying to show video.
|
||||
|
||||
`TCP/443` is required for the webserver which can be running on another machine than the Jitsi Videobrige is running on.
|
||||
|
||||
The following extra lines need to be added to the file `~/.sip-communicator/sip-communicator.properties` (in the home directory of the user running the videobridge):
|
||||
```
|
||||
org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS=<Local.IP.Address>
|
||||
org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS=<Public.IP.Address>
|
||||
```
|
||||
|
||||
# Hold your first conference
|
||||
You are now all set and ready to have your first meet by going to http://jitsi.example.com
|
||||
|
||||
## Enabling recording
|
||||
[Jibri](https://github.com/jitsi/jibri) is a set of tools for recording and/or streaming a Jitsi Meet conference.
|
||||
@@ -1,28 +0,0 @@
|
||||
# Setting up Dropbox integration
|
||||
1. Create a Dropbox app.
|
||||
2. Add the following to ```ios/app/src/Info.plist``` by replacing `<APP_KEY>`
|
||||
with your own Dropbox app key (which can be found in the
|
||||
[App Console](https://www.dropbox.com/developers/apps)):
|
||||
```
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string></string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>db-<APP_KEY></string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>LSApplicationQueriesSchemes</key>
|
||||
<array>
|
||||
<string>dbapi-2</string>
|
||||
<string>dbapi-8-emm</string>
|
||||
</array>
|
||||
```
|
||||
|
||||
**NOTE:** Both Android and iOS builds of the apps will parse the Dropbox app key
|
||||
from ```ios/app/src/Info.plist```.
|
||||
|
||||
**NOTE:** See [Dropbox developer guide](https://www.dropbox.com/developers/reference/developer-guide) for more information
|
||||
@@ -1,22 +0,0 @@
|
||||
# Setting up Google Authentication
|
||||
|
||||
- Create a Firebase project here: https://firebase.google.com/. You'll need a
|
||||
signed Android build for that, that can be a debug self-signed build too, just
|
||||
retrieve the signing hash. The key hash of an already signed ap can be obtained
|
||||
as follows (on macOS): ```keytool -list -printcert -jarfile the-app.apk```
|
||||
- Place the generated ```google-services.json``` file in ```android/app```
|
||||
for Android and the ```GoogleService-Info.plist``` into ```ios/app``` for
|
||||
iOS (you can stop at that step, no need for the driver and the code changes they
|
||||
suggest in the wizard).
|
||||
- You may want to exclude these files in YOUR GIT config (do not exclude them in
|
||||
the ```.gitignore``` of the application itself!).
|
||||
- Your web client ID is auto generated during the Firebase project
|
||||
creation. Find them in the Google Developer console
|
||||
(https://console.developers.google.com/)
|
||||
- Make sure your config reflects this ID by setting
|
||||
```googleApiApplicationClientID``` in config.js.
|
||||
- Add your iOS client ID (the REVERSED_CLIENT_ID in the plist file) as an
|
||||
application URL schema into ```ios/app/src/Info.plist```
|
||||
(replacing placeholder).
|
||||
- Enable YouTube API access on the developer console (see above) to enable live
|
||||
streaming.
|
||||
109
doc/mobile.md
109
doc/mobile.md
@@ -1,109 +0,0 @@
|
||||
# Jitsi Meet apps for Android and iOS
|
||||
|
||||
Jitsi Meet can be built as a standalone app for Android or iOS. It uses the
|
||||
[React Native] framework.
|
||||
|
||||
**If you want to rebuild the SDK yourself look in [Android README] or [iOS README].**
|
||||
|
||||
First make sure the [React Native dependencies] are installed.
|
||||
|
||||
**NOTE**: This document assumes the app is being built on a macOS system. GNU/Linux is also
|
||||
supported for building the Android app and Windows **is not supported at alll**.
|
||||
|
||||
**NOTE**: Node 12.X and npm 6.X are recommended for building.
|
||||
|
||||
|
||||
## iOS
|
||||
|
||||
1. Install some extra dependencies
|
||||
|
||||
- Install ios-deploy globally (in case you want to use the React Native CLI
|
||||
to deploy the app to the device)
|
||||
|
||||
```bash
|
||||
npm install -g ios-deploy
|
||||
```
|
||||
|
||||
- Install main dependencies:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
- Install the required pods (CocoaPods must be installled first, it can
|
||||
be done with Homebrew: `brew install cocoapods`)
|
||||
|
||||
```bash
|
||||
cd ios
|
||||
pod install
|
||||
cd ..
|
||||
```
|
||||
|
||||
2. Build the app
|
||||
|
||||
There are 2 ways to build the app: using the CLI or using Xcode.
|
||||
|
||||
Using the CLI:
|
||||
|
||||
```bash
|
||||
react-native run-ios --device
|
||||
```
|
||||
|
||||
When the app is launched from the CLI the output can be checked with the
|
||||
following command:
|
||||
|
||||
```bash
|
||||
react-native log-ios
|
||||
```
|
||||
|
||||
Using Xcode
|
||||
|
||||
- Open **ios/jitsi-meet.xcworkspace** in Xcode. Make sure it's the workspace
|
||||
file!
|
||||
|
||||
- Select your device from the top bar and hit the "play" button.
|
||||
|
||||
When the app is launched from Xcode the Debug console will show the output
|
||||
logs the application creates.
|
||||
|
||||
|
||||
3. Other remarks
|
||||
|
||||
It's likely you'll need to change the bundle ID for deploying to a device.
|
||||
This can be changed in the "General" tab. Under "Identity" set
|
||||
"Bundle Identifier" to a different value, and adjust the "Team" in the
|
||||
"Signing" section to match your own.
|
||||
|
||||
|
||||
## Android
|
||||
|
||||
The [React Native dependencies] page has very detailed information on how to
|
||||
setup [Android Studio] and the required components for getting the necessary
|
||||
build environment. Make sure you follow it closely.
|
||||
|
||||
1. Building the app
|
||||
|
||||
The app can be built using the CLI utility as follows:
|
||||
|
||||
```bash
|
||||
react-native run-android
|
||||
```
|
||||
|
||||
It will be launched on the connected Android device.
|
||||
|
||||
## Debugging
|
||||
|
||||
The official documentation on [debugging] is quite extensive and specifies the
|
||||
preferred method for debugging.
|
||||
|
||||
**NOTE**: When using Chrome Developer Tools for debugging the JavaScript source
|
||||
code is being interpreted by Chrome's V8 engine, instead of JSCore which React
|
||||
Native uses. It's important to keep this in mind due to potential differences in
|
||||
supported JavaScript features.
|
||||
|
||||
[Android README]: https://github.com/jitsi/jitsi-meet/blob/master/android/README.md
|
||||
[iOS README]: https://github.com/jitsi/jitsi-meet/blob/master/ios/README.md
|
||||
[Android Studio]: https://developer.android.com/studio/index.html
|
||||
[debugging]: https://facebook.github.io/react-native/docs/debugging.html
|
||||
[React Native]: https://facebook.github.io/react-native/
|
||||
[React Native dependencies]: https://facebook.github.io/react-native/docs/getting-started.html#installing-dependencies
|
||||
@@ -1,162 +1,3 @@
|
||||
# Jitsi Meet quick install
|
||||
|
||||
This guide helps you ___host your own Jitsi server___. If you want to have a video conference without setting up any infrastructure, use https://meet.jit.si instead.
|
||||
|
||||
This document describes the required steps for a quick Jitsi Meet installation on a Debian based GNU/Linux system. Debian 9 (Stretch) or later, and Ubuntu 18.04 (Bionic Beaver) or later are supported out-of-the-box.
|
||||
|
||||
On Ubuntu systems, Jitsi requires dependencies from Ubuntu's `universe` package repository. To ensure this is enabled, run `apt-add-repository universe` at the command-line.
|
||||
|
||||
_Note_: Many of the installation steps require elevated privileges. If you are logged in using a regular user account, you may need to temporarily increase your permissions (for example, by using `sudo` for individual commands).
|
||||
|
||||
## Basic Jitsi Meet install
|
||||
|
||||
### Set up the Fully Qualified Domain Name (FQDN) (optional)
|
||||
|
||||
If the machine used to host the Jitsi Meet instance has a FQDN (for example `meet.example.org`) already set up in DNS, `/etc/hostname` must contain this FQDN; if this is not the case yet, [change the hostname](https://wiki.debian.org/HowTo/ChangeHostname).
|
||||
|
||||
Then add the same FQDN in the `/etc/hosts` file, associating it with the loopback address:
|
||||
|
||||
127.0.0.1 localhost meet.example.org
|
||||
|
||||
Finally on the same machine test that you can ping the FQDN with: `ping "$(hostname)"`-
|
||||
|
||||
### Add the Jitsi package repository
|
||||
```sh
|
||||
echo 'deb https://download.jitsi.org stable/' | sudo tee /etc/apt/sources.list.d/jitsi-stable.list
|
||||
wget -qO - https://download.jitsi.org/jitsi-key.gpg.key | sudo apt-key add -
|
||||
```
|
||||
### Open ports in your firewall
|
||||
|
||||
Open the following ports in your firewall, to allow traffic to the machine running jitsi:
|
||||
|
||||
- 80 TCP
|
||||
- 443 TCP
|
||||
- 10000 UDP
|
||||
|
||||
|
||||
### Install Jitsi Meet
|
||||
|
||||
_Note_: The installer will check if [Nginx](https://nginx.org/) or [Apache](https://httpd.apache.org/) is present (in that order) and configure a virtualhost within the web server it finds to serve Jitsi Meet. If none of the above is found it then defaults to Nginx.
|
||||
If you are already running Nginx on port 443 on the same machine turnserver configuration will be skipped as it will conflict with your current port 443.
|
||||
|
||||
```sh
|
||||
# Ensure support is available for apt repositories served via HTTPS
|
||||
apt-get install apt-transport-https
|
||||
|
||||
# Retrieve the latest package versions across all repositories
|
||||
apt-get update
|
||||
|
||||
# Perform jitsi-meet installation
|
||||
apt-get -y install jitsi-meet
|
||||
```
|
||||
|
||||
During the installation, you will be asked to enter the hostname of the Jitsi Meet instance. If you have a [FQDN](https://en.wikipedia.org/wiki/Fully_qualified_domain_name) for the instance already set up in DNS, enter it there. If you don't have a resolvable hostname, you can enter the IP address of the machine (if it is static or doesn't change).
|
||||
|
||||
This hostname (or IP address) will be used for virtualhost configuration inside the Jitsi Meet and also, you and your correspondents will be using it to access the web conferences.
|
||||
|
||||
### Generate a Let's Encrypt certificate (optional, recommended)
|
||||
|
||||
In order to have encrypted communications, you need a [TLS certificate](https://en.wikipedia.org/wiki/Transport_Layer_Security). The easiest way is to use [Let's Encrypt](https://letsencrypt.org/).
|
||||
|
||||
_Note_: Jitsi Meet mobile apps *require* a valid certificate signed by a trusted [Certificate Authority](https://en.wikipedia.org/wiki/Certificate_authority) (such as a Let's Encrypt certificate) and will not be able to connect to your server if you choose a self-signed certificate.
|
||||
|
||||
Simply run the following in your shell:
|
||||
|
||||
```sh
|
||||
/usr/share/jitsi-meet/scripts/install-letsencrypt-cert.sh
|
||||
```
|
||||
|
||||
Note that this script uses the [HTTP-01 challenge type](https://letsencrypt.org/docs/challenge-types/) and thus your instance needs to be accessible from the public internet. If you want to use a different challenge type, don't use this script and instead choose ___I want to use my own certificate___ during jitsi-meet installation.
|
||||
|
||||
#### Advanced configuration
|
||||
If the installation is on a machine [behind NAT](https://github.com/jitsi/jitsi-meet/blob/master/doc/faq.md) jitsi-videobridge should configure itself automatically on boot. If three way call does not work further configuration of jitsi-videobridge is needed in order for it to be accessible from outside.
|
||||
Provided that all required ports are routed (forwarded) to the machine that it runs on. By default these ports are (TCP/443 or TCP/4443 and UDP/10000).
|
||||
The following extra lines need to be added to the file `/etc/jitsi/videobridge/sip-communicator.properties`:
|
||||
```
|
||||
org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS=<Local.IP.Address>
|
||||
org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS=<Public.IP.Address>
|
||||
```
|
||||
And comment the existing `org.ice4j.ice.harvest.STUN_MAPPING_HARVESTER_ADDRESSES`.
|
||||
See [the documentation of ice4j](https://github.com/jitsi/ice4j/blob/master/doc/configuration.md)
|
||||
for details.
|
||||
|
||||
Default deployments on systems using systemd will have low default values for maximum processes and open files. If the used bridge will expect higher number of participants the default values need to be adjusted (the default values are good for less than 100 participants).
|
||||
To update the values edit `/etc/systemd/system.conf` and make sure you have the following values:
|
||||
```
|
||||
DefaultLimitNOFILE=65000
|
||||
DefaultLimitNPROC=65000
|
||||
DefaultTasksMax=65000
|
||||
```
|
||||
To load the values and check them look [here](#systemd-details) for details.
|
||||
|
||||
By default, anyone who has access to your jitsi instance will be able to start a conference: if your server is open to the world, anyone can have a chat with anyone else. If you want to limit the ability to start a conference to registered users, set up a "secure domain". Follow the instructions at https://github.com/jitsi/jicofo#secure-domain.
|
||||
|
||||
### Confirm that your installation is working
|
||||
|
||||
Launch a web browser (Chrome, Chromium or latest Opera) and enter the hostname or IP address from the previous step into the address bar.
|
||||
|
||||
If you used a self-signed certificate (as opposed to using Let's Encrypt), your web browser will ask you to confirm that you trust the certificate.
|
||||
|
||||
You should see a web page prompting you to create a new meeting. Make sure that you can successfully create a meeting and that other participants are able to join the session.
|
||||
|
||||
If this all worked, then congratulations! You have an operational Jitsi conference service.
|
||||
|
||||
## Adding sip-gateway to Jitsi Meet
|
||||
|
||||
### Install Jigasi
|
||||
|
||||
Jigasi is a server-side application acting as a gateway to Jitsi Meet conferences. It allows regular [SIP](https://en.wikipedia.org/wiki/Session_Initiation_Protocol) clients to join meetings and provides transcription capabilities.
|
||||
|
||||
```sh
|
||||
apt-get -y install jigasi
|
||||
```
|
||||
or
|
||||
|
||||
```sh
|
||||
wget https://download.jitsi.org/unstable/jigasi_1.0-107_amd64.deb
|
||||
dpkg -i jigasi_1.0-107_amd64.deb
|
||||
```
|
||||
|
||||
During the installation, you will be asked to enter your SIP account and password. This account will be used to invite the other SIP participants.
|
||||
|
||||
### Reload Jitsi Meet
|
||||
|
||||
Launch again a browser with the Jitsi Meet URL and you'll see a telephone icon on the right end of the toolbar. Use it to invite SIP accounts to join the current conference.
|
||||
|
||||
Enjoy!
|
||||
|
||||
## Uninstall
|
||||
|
||||
```sh
|
||||
apt-get purge jigasi jitsi-meet jitsi-meet-web-config jitsi-meet-prosody jitsi-meet-turnserver jitsi-meet-web jicofo jitsi-videobridge2
|
||||
```
|
||||
|
||||
Sometimes the following packages will fail to uninstall properly:
|
||||
|
||||
- jigasi
|
||||
- jitsi-videobridge
|
||||
|
||||
When this happens, just run the uninstall command a second time and it should be ok.
|
||||
|
||||
The reason for the failure is that sometimes the uninstall script is faster than the process that stops the daemons. The second run of the uninstall command fixes this, as by then the jigasi or jitsi-videobridge daemons are already stopped.
|
||||
|
||||
#### Systemd details
|
||||
To reload the systemd changes on a running system execute `systemctl daemon-reload` and `service jitsi-videobridge2 restart`.
|
||||
To check the tasks part execute `service jitsi-videobridge2 status` and you should see `Tasks: XX (limit: 65000)`.
|
||||
To check the files and process part execute ```cat /proc/`cat /var/run/jitsi-videobridge/jitsi-videobridge.pid`/limits``` and you should see:
|
||||
```
|
||||
Max processes 65000 65000 processes
|
||||
Max open files 65000 65000 files
|
||||
```
|
||||
|
||||
## Debugging problems
|
||||
|
||||
If you run into problems, one thing to try is using a different web browser. Some versions of some browsers are known to have issues with Jitsi Meet. You can also visit https://test.webrtc.org to test your browser's [WebRTC](https://en.wikipedia.org/wiki/WebRTC) support.
|
||||
|
||||
Another place to look is the various log files:
|
||||
|
||||
```
|
||||
/var/log/jitsi/jvb.log
|
||||
/var/log/jitsi/jicofo.log
|
||||
/var/log/prosody/prosody.log
|
||||
```
|
||||
This document has been moved [here](https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-quickstart).
|
||||
|
||||
@@ -1,166 +0,0 @@
|
||||
# Scalable Jitsi installation
|
||||
|
||||
A single server Jitsi installation is good for a limited size of concurrent conferences.
|
||||
The first limiting factor is the videobridge component, that handles the actual video and audio traffic.
|
||||
It is easy to scale the video bridges horizontally by adding as many as needed.
|
||||
In a cloud based environment, additionally the bridges can be scaled up or down as needed.
|
||||
|
||||
*NB*: The [Youtube Tutorial on Scaling](https://www.youtube.com/watch?v=LyGV4uW8km8) is outdated and describes an old configuration method.
|
||||
|
||||
*NB*: Building a scalable infrastructure is not a task for beginning Jitsi Administrators.
|
||||
The instructions assume that you have installed a single node version successfully, and that
|
||||
you are comfortable installing, configuring and debugging Linux software.
|
||||
This is not a step-by-step guide, but will show you, which packages to install and which
|
||||
configurations to change. Use the [manual install](https://github.com/jitsi/jitsi-meet/blob/master/doc/manual-install.md) for
|
||||
details on how to setup Jitsi on a single host.
|
||||
It is highly recommended to use configuration management tools like Ansible or Puppet to manage the
|
||||
installation and configuration.
|
||||
|
||||
## Architecture (Single Jitsi-Meet, multiple videobridges)
|
||||
|
||||
A first step is to split the functions of the central jitsi-meet instance (with nginx, prosody and jicofo) and
|
||||
videobridges.
|
||||
|
||||
A simplified diagram (with open network ports) of an installation with one Jitsi-Meet instance and three
|
||||
videobridges that are load balanced looks as follows. Each box is a server/VM.
|
||||
|
||||
```
|
||||
+ +
|
||||
| |
|
||||
| |
|
||||
v v
|
||||
80, 443 TCP 443 TCP, 10000 UDP
|
||||
+--------------+ +---------------------+
|
||||
| nginx | 5222, 5347 TCP | |
|
||||
| jitsi-meet |<-------------------+| jitsi-videobridge |
|
||||
| prosody | | | |
|
||||
| jicofo | | +---------------------+
|
||||
+--------------+ |
|
||||
| +---------------------+
|
||||
| | |
|
||||
+----------+| jitsi-videobridge |
|
||||
| | |
|
||||
| +---------------------+
|
||||
|
|
||||
| +---------------------+
|
||||
| | |
|
||||
+----------+| jitsi-videobridge |
|
||||
| |
|
||||
+---------------------+
|
||||
```
|
||||
|
||||
## Machine Sizing
|
||||
|
||||
The Jitsi-Meet server will generally not have that much load (unless you have many) conferences
|
||||
going at the same time. A 4 CPU, 8 GB machine will probably be fine.
|
||||
|
||||
The videobridges will have more load. 4 or 8 CPU with 8 GB RAM seems to be a good configuration.
|
||||
|
||||
|
||||
### Installation of Jitsi-Meet
|
||||
|
||||
Assuming that the installation will run under the following FQDN: `meet.example.com` and you have
|
||||
SSL cert and key in `/etc/ssl/meet.example.com.{crt,key}`
|
||||
|
||||
Set the following DebConf variables prior to installing the packages.
|
||||
(We are not installing the `jitsi-meet` package which would handle that for us)
|
||||
|
||||
Install the `debconf-utils` package
|
||||
|
||||
```
|
||||
$ cat << EOF | sudo debconf-set-selections
|
||||
jitsi-videobridge jitsi-videobridge/jvb-hostname string meet.example.com
|
||||
jitsi-meet jitsi-meet/jvb-serve boolean false
|
||||
jitsi-meet-prosody jitsi-videobridge/jvb-hostname string meet.example.com
|
||||
jitsi-meet-web-config jitsi-meet/cert-choice select I want to use my own certificate
|
||||
jitsi-meet-web-config jitsi-meet/cert-path-crt string /etc/ssl/meet.example.com.crt
|
||||
jitsi-meet-web-config jitsi-meet/cert-path-key string /etc/ssl/meet.example.com.key
|
||||
EOF
|
||||
```
|
||||
|
||||
On the jitsi-meet server, install the following packages:
|
||||
|
||||
* `nginx`
|
||||
* `prosody`
|
||||
* `jicofo`
|
||||
* `jitsi-meet-web`
|
||||
* `jitsi-meet-prosody`
|
||||
* `jitsi-meet-web-config`
|
||||
|
||||
### Installation of Videobridge(s)
|
||||
|
||||
For simplicities sake, set the same `debconf` variables as above and install
|
||||
|
||||
* `jitsi-videobridge2`
|
||||
|
||||
### Configuration of jitsi-meet
|
||||
|
||||
#### Firewall
|
||||
|
||||
Open the following ports:
|
||||
|
||||
Open to world:
|
||||
|
||||
* 80 TCP
|
||||
* 443 TCP
|
||||
|
||||
Open to the videobridges only
|
||||
|
||||
* 5222 TCP (for Prosody)
|
||||
* 5347 TCP (for Jicofo)
|
||||
|
||||
|
||||
#### NGINX
|
||||
|
||||
Create the `/etc/nginx/sites-available/meet.example.com.conf` as usual
|
||||
|
||||
#### Prosody
|
||||
|
||||
Follow the steps in the [manual install](https://github.com/jitsi/jitsi-meet/blob/master/doc/manual-install.md) for setup tasks
|
||||
|
||||
You will need to adapt the following files (see the files in `example-config-files/scalable`)
|
||||
|
||||
* `/etc/prosody/prosody.cfg.lua`
|
||||
* `/etc/prosody/conf.avail/meet.example.com.cfg.lua`
|
||||
|
||||
#### Jitsi-Meet
|
||||
|
||||
Adapt `/usr/share/jitsi-meet/config.js` and `/usr/share/jitsi-meet/interface-config.js` to your specific needs
|
||||
|
||||
#### Jicofo
|
||||
|
||||
You will need to adapt the following files (see the files in `example-config-files/scalable`)
|
||||
|
||||
* `/etc/jitsi/jicofo/config` (hostname, jicofo_secret, jicofo_password)
|
||||
* `/etc/jitsi/jicofo/sip-communicator.properties` (hostname)
|
||||
|
||||
### Configuration of the Videobridge
|
||||
|
||||
#### Firewall
|
||||
|
||||
Open the following ports:
|
||||
|
||||
Open to world:
|
||||
|
||||
* 443 TCP
|
||||
* 10000 UDP
|
||||
|
||||
#### jitsi-videobridge2
|
||||
|
||||
You will need to adapt the following files (see the files in `example-config-files/scalable`)
|
||||
|
||||
Each videobridge will have to have it's own, unique nickname
|
||||
|
||||
* `/etc/jitsi/videobridge/config` (hostname, password)
|
||||
* `/etc/jitsi/jicofo/sip-communicator.properties` (hostname of jitsi-meet, nickname of videobridge, vb_password)
|
||||
|
||||
With the latest stable (April 2020) videobridge, it is no longer necessary to set public and private IP
|
||||
adresses in the `sip-communicator.properties` as the bridge will figure out the correct configuration by itself.
|
||||
|
||||
## Testing
|
||||
|
||||
After restarting all services (`prosody`, `jicofo` and all the `jitsi-videobridge2`) you can see in
|
||||
`/var/log/prosody/prosody.log` and
|
||||
`/var/log/jitsi/jicofo.log` that the videobridges connect to Prososy and that Jicofo picks them up.
|
||||
|
||||
When a new conference starts, Jicofo picks a videobridge and schedules the conference on it.
|
||||
@@ -1,53 +0,0 @@
|
||||
# Configuring sipgw jibri with jitsi-meet
|
||||
|
||||
This document describes how you can configure jitsi-meet to use sipgw jibri and enable rooms in 'Add people dialog'
|
||||
You will need a working deployment of jibri configured to use a regular sip video device, for more info check out the [jibri documentation](https://github.com/jitsi/jibri/blob/master/README.md).
|
||||
|
||||
This feature is available for non-guests of the system, so this relies on setting in config.js ``enableUserRolesBasedOnToken: true`` and providing a jwt token when accessing the conference.
|
||||
|
||||
* Jicofo configuration:
|
||||
edit /etc/jitsi/jicofo/sip-communicator.properties (or similar), set the appropriate MUC to look for the Jibri Controllers. This should be the same MUC as is referenced in jibri's config.json file. Restart Jicofo after setting this property.
|
||||
|
||||
```
|
||||
org.jitsi.jicofo.jibri.SIP_BREWERY=TheSipBrewery@conference.yourdomain.com
|
||||
```
|
||||
|
||||
* Jitsi Meet configuration:
|
||||
- config.js: add
|
||||
```
|
||||
enableUserRolesBasedOnToken: true,
|
||||
peopleSearchQueryTypes: ['conferenceRooms'],
|
||||
peopleSearchUrl: 'https://api.yourdomain.com/testpath/searchpeople',
|
||||
```
|
||||
|
||||
The combination of the above settings and providing a jwt token will enable a button under invite option which will show the dialog 'Add people'.
|
||||
|
||||
## People search service
|
||||
|
||||
When searching in the dialog, a request for results is made to the `peopleSearchUrl` service.
|
||||
|
||||
The request is in the following format:
|
||||
```
|
||||
https://api.yourdomain.com/testpath/searchpeople?query=testroomname&queryTypes=[%22conferenceRooms%22]&jwt=somejwt
|
||||
```
|
||||
The parameters are:
|
||||
- query - The text entered by the user.
|
||||
- queryTypes - What type of results we want people, rooms, conferenceRooms. This is the value from config.js `peopleSearchQueryTypes`
|
||||
- jwt - The token used by the user to access the conference.
|
||||
|
||||
The response of the service is a json in the following format:
|
||||
```
|
||||
[
|
||||
{
|
||||
"id": "address@sip.domain.com",
|
||||
"name": "Some room name",
|
||||
"type": "videosipgw"
|
||||
},
|
||||
{
|
||||
"id": "address2@sip.domain.com",
|
||||
"name": "Some room name2",
|
||||
"type": "videosipgw"
|
||||
}
|
||||
]
|
||||
```
|
||||
Type should be `videosipgw`, `name` is the name shown to the user and `id` is the sip address to be called by the sipgw jibri.
|
||||
@@ -1,22 +0,0 @@
|
||||
# Enabling speakerstats prosody module
|
||||
|
||||
To enable the speaker stats we need to enable speakerstats module under the main
|
||||
virtual host, this is to enable the advertising the speaker stats component,
|
||||
which address needs to be specified in `speakerstats_component` option.
|
||||
|
||||
We need to also enable the component with the address specified in `speakerstats_component`.
|
||||
The component needs also to have the option with the muc component address in
|
||||
`muc_component` option.
|
||||
|
||||
```lua
|
||||
VirtualHost "jitsi.example.com"
|
||||
speakerstats_component = "speakerstats.jitsi.example.com"
|
||||
modules_enabled = {
|
||||
"speakerstats";
|
||||
}
|
||||
|
||||
Component "speakerstats.jitsi.example.com" "speakerstats_component"
|
||||
muc_component = "conference.jitsi.example.com"
|
||||
|
||||
Component "conference.jitsi.example.com" "muc"
|
||||
```
|
||||
15
doc/turn.md
15
doc/turn.md
@@ -1,15 +0,0 @@
|
||||
One-to-one calls should avoid going throught the JVB for optimal performance and for optimal resource usage. This is why we've added the peer-to-peer mode where the two participants connect directly to each other. Unfortunately, a direct connection is not always possible between the participants. In those cases you can use a TURN server to relay the traffic (n.b. the JVB does much more than just relay the traffic, so this is not the same as using the JVB to "relay" the traffic).
|
||||
|
||||
This document describes how to enable TURN server support in one-to-one calls in Jitsi Meet, even though it gives some hints how to configure [prosody](prosody.im) and [coTURN](https://github.com/coturn/coturn), it assumes a properly configured TURN server and a proprely configured XMPP server.
|
||||
|
||||
One way to configure TURN support in meet with a static configuration. You can simply fill out the `p2p.stunServers` option with appropriate values, e.g.:
|
||||
|
||||
[
|
||||
{ urls: 'turn:turn.example.com1', credential: 'user', password: 'pass' },
|
||||
]
|
||||
|
||||
This technique doesn't require any special configuration on the XMPP server, but it exposes the credentials to your TURN server and other people can use your bandwidth freely, so while it's simple to implement, it's not recommended.
|
||||
|
||||
This [draft](https://tools.ietf.org/html/draft-uberti-behave-turn-rest-00) escribes a proposed standard REST API for obtaining access to TURN services via ephemeral (i.e. time-limited) credentials. These credentials are vended by a web service over HTTP, and then supplied to and checked by a TURN server using the standard TURN protocol. The usage of ephemeral credentials ensures that access to the TURN server can be controlled even if the credentials can be discovered by the user.
|
||||
|
||||
Jitsi Meet can fetch the TURN credentials from the XMPP server via [XEP-0215](https://xmpp.org/extensions/xep-0215.html). You can enable this functionality by setting `p2p.useStunTurn: true` in config.js. By properly configuring a common shared secret on your TURN server and your XMPP server, the XMPP server can deliver appropriate credentials and TURN urls to Jitsi Meet. coTURN natively supports shared secret authentication (--use-auth-secret-) and in prosody, you can use the [mod_turncredentials](https://modules.prosody.im/mod_turncredentials.html) module.
|
||||
@@ -48,11 +48,11 @@ var interfaceConfig = {
|
||||
*/
|
||||
TOOLBAR_BUTTONS: [
|
||||
'microphone', 'camera', 'closedcaptions', 'desktop', 'fullscreen',
|
||||
'fodeviceselection', 'hangup', 'profile', 'info', 'chat', 'recording',
|
||||
'fodeviceselection', 'hangup', 'profile', 'chat', 'recording',
|
||||
'livestreaming', 'etherpad', 'sharedvideo', 'settings', 'raisehand',
|
||||
'videoquality', 'filmstrip', 'invite', 'feedback', 'stats', 'shortcuts',
|
||||
'tileview', 'videobackgroundblur', 'download', 'help', 'mute-everyone',
|
||||
'e2ee'
|
||||
'e2ee', 'security'
|
||||
],
|
||||
|
||||
SETTINGS_SECTIONS: [ 'devices', 'language', 'moderator', 'profile', 'calendar' ],
|
||||
@@ -176,7 +176,7 @@ var interfaceConfig = {
|
||||
// has a suboptimal experience. Browsers which are not listed as optimal or
|
||||
// unsupported are considered suboptimal. Valid values are:
|
||||
// chrome, chromium, edge, electron, firefox, nwjs, opera, safari
|
||||
OPTIMAL_BROWSERS: [ 'chrome', 'chromium', 'firefox', 'nwjs', 'electron' ],
|
||||
OPTIMAL_BROWSERS: [ 'chrome', 'chromium', 'firefox', 'nwjs', 'electron', 'safari' ],
|
||||
|
||||
// Browsers, in addition to those which do not fully support WebRTC, that
|
||||
// are not supported and should show the unsupported browser page.
|
||||
@@ -230,6 +230,17 @@ var interfaceConfig = {
|
||||
*/
|
||||
// MOBILE_DOWNLOAD_LINK_IOS: 'https://itunes.apple.com/us/app/jitsi-meet/id1165103905',
|
||||
|
||||
/**
|
||||
* Specify Firebase dynamic link properties for the mobile apps.
|
||||
*/
|
||||
// MOBILE_DYNAMIC_LINK: {
|
||||
// APN: 'org.jitsi.meet',
|
||||
// APP_CODE: 'w2atb',
|
||||
// CUSTOM_DOMAIN: undefined,
|
||||
// IBI: 'com.atlassian.JitsiMeet.ios',
|
||||
// ISI: '1165103905'
|
||||
// },
|
||||
|
||||
/**
|
||||
* Specify mobile app scheme for opening the app from the mobile browser.
|
||||
*/
|
||||
|
||||
@@ -66,6 +66,7 @@ target 'JitsiMeet' do
|
||||
pod 'RNSound', :path => '../node_modules/react-native-sound'
|
||||
pod 'RNSVG', :path => '../node_modules/react-native-svg'
|
||||
pod 'RNWatch', :path => '../node_modules/react-native-watch-connectivity'
|
||||
pod 'RNDefaultPreference', :path => '../node_modules/react-native-default-preference'
|
||||
|
||||
# Native pod dependencies
|
||||
#
|
||||
|
||||
@@ -287,7 +287,7 @@ PODS:
|
||||
- React-jsinspector (0.61.5-jitsi.1)
|
||||
- react-native-background-timer (2.1.1):
|
||||
- React
|
||||
- react-native-calendar-events (1.7.3):
|
||||
- react-native-calendar-events (2.0.0):
|
||||
- React
|
||||
- react-native-keep-awake (4.0.0):
|
||||
- React
|
||||
@@ -353,6 +353,8 @@ PODS:
|
||||
- ReactCommon/turbomodule/core (= 0.61.5-jitsi.1)
|
||||
- RNCAsyncStorage (1.3.4):
|
||||
- React
|
||||
- RNDefaultPreference (1.4.2):
|
||||
- React
|
||||
- RNGoogleSignin (3.0.1):
|
||||
- GoogleSignIn (~> 5.0.0)
|
||||
- React
|
||||
@@ -363,7 +365,7 @@ PODS:
|
||||
- React
|
||||
- RNSVG (9.7.1):
|
||||
- React
|
||||
- RNWatch (0.2.0):
|
||||
- RNWatch (0.4.3):
|
||||
- React
|
||||
- Yoga (1.14.0)
|
||||
|
||||
@@ -409,6 +411,7 @@ DEPENDENCIES:
|
||||
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
|
||||
- ReactCommon/turbomodule (from `../node_modules/react-native/ReactCommon`)
|
||||
- "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)"
|
||||
- RNDefaultPreference (from `../node_modules/react-native-default-preference`)
|
||||
- "RNGoogleSignin (from `../node_modules/@react-native-community/google-signin`)"
|
||||
- RNSound (from `../node_modules/react-native-sound`)
|
||||
- RNSVG (from `../node_modules/react-native-svg`)
|
||||
@@ -416,13 +419,11 @@ DEPENDENCIES:
|
||||
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/CocoaPods/Specs.git:
|
||||
trunk:
|
||||
- Amplitude-iOS
|
||||
- AppAuth
|
||||
- boost-for-react-native
|
||||
- CocoaLumberjack
|
||||
- ObjectiveDropboxOfficial
|
||||
trunk:
|
||||
- AppAuth
|
||||
- Crashlytics
|
||||
- Fabric
|
||||
- Firebase
|
||||
@@ -442,6 +443,7 @@ SPEC REPOS:
|
||||
- GTMAppAuth
|
||||
- GTMSessionFetcher
|
||||
- nanopb
|
||||
- ObjectiveDropboxOfficial
|
||||
- PromisesObjC
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
@@ -509,6 +511,8 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/ReactCommon"
|
||||
RNCAsyncStorage:
|
||||
:path: "../node_modules/@react-native-community/async-storage"
|
||||
RNDefaultPreference:
|
||||
:path: "../node_modules/react-native-default-preference"
|
||||
RNGoogleSignin:
|
||||
:path: "../node_modules/@react-native-community/google-signin"
|
||||
RNSound:
|
||||
@@ -562,7 +566,7 @@ SPEC CHECKSUMS:
|
||||
React-jsiexecutor: de1c37cf59ae9adcbf2be82eea0e090dc3f3205e
|
||||
React-jsinspector: b76c4e84a7833bb4c90549d59ed53ec299ff912b
|
||||
react-native-background-timer: 0d34748e53a972507c66963490c775321a88f6f2
|
||||
react-native-calendar-events: 2fe35a9294af05de0ed819d3a1b5dac048d2c010
|
||||
react-native-calendar-events: 1442fad71a00388f933cfa25512588fec300fcf8
|
||||
react-native-keep-awake: eba3137546b10003361b37c761f6c429b59814ae
|
||||
react-native-netinfo: 8d8db463bcc5db66a8ac5c48a7d86beb3b92f61a
|
||||
react-native-webrtc: 86d841823e66d68cc1f86712db1c2956056bf0c2
|
||||
@@ -578,12 +582,13 @@ SPEC CHECKSUMS:
|
||||
React-RCTVibration: a1bcfcdc0b5a73a1b0829a34cee22bd0e95bacba
|
||||
ReactCommon: 675681aba4fecff5acbc0e440530cc422103c610
|
||||
RNCAsyncStorage: 8e31405a9f12fbf42c2bb330e4560bfd79c18323
|
||||
RNDefaultPreference: 56a405ce61033ac77b95004dccd7ac54c2eb50d1
|
||||
RNGoogleSignin: 39336070b35fc4cea6a98cf111e00480317be0ae
|
||||
RNSound: c980916b596cc15c8dcd2f6ecd3b13c4881dbe20
|
||||
RNSVG: aac12785382e8fd4f28d072fe640612e34914631
|
||||
RNWatch: 09738b339eceb66e4d80a2371633ca5fb380fa42
|
||||
RNWatch: a5320c959c75e72845c07985f3e935e58998f1d3
|
||||
Yoga: 7b4209fda2441f99d54dd6cf4c82b094409bb68f
|
||||
|
||||
PODFILE CHECKSUM: f615794fb9184757b00cd16e534824ba6ee2fc98
|
||||
PODFILE CHECKSUM: 082858daebbe170e7a490de433e7f2a99e0c3701
|
||||
|
||||
COCOAPODS: 1.9.1
|
||||
|
||||
205
ios/README.md
205
ios/README.md
@@ -1,206 +1,3 @@
|
||||
# Jitsi Meet SDK for iOS
|
||||
|
||||
The Jitsi Meet iOS SDK provides the same user experience as the Jitsi Meet app,
|
||||
in a customizable way which you can embed in your apps.
|
||||
|
||||
## Sample applications using the SDK
|
||||
|
||||
If you want to see how easy integrating the Jitsi Meet SDK into a native application is, take a look at the
|
||||
[sample applications repository](https://github.com/jitsi/jitsi-meet-sdk-samples).
|
||||
|
||||
## Usage
|
||||
|
||||
There are 2 ways to integrate the SDK into your project:
|
||||
|
||||
- Using CocoaPods
|
||||
- Building it yourself
|
||||
|
||||
### Using CocoaPods
|
||||
|
||||
Follow the instructions [here](https://github.com/jitsi/jitsi-meet-ios-sdk-releases/blob/master/README.md).
|
||||
|
||||
### Building it yourself
|
||||
|
||||
1. Install all required [dependencies](https://github.com/jitsi/jitsi-meet/blob/master/doc/mobile.md).
|
||||
|
||||
2. `xcodebuild -workspace ios/jitsi-meet.xcworkspace -scheme JitsiMeet -destination='generic/platform=iOS' -configuration Release archive`
|
||||
|
||||
After successfully building Jitsi Meet SDK for iOS, copy
|
||||
`ios/sdk/JitsiMeet.framework` (if the path points to a symbolic link, follow the
|
||||
symbolic link) and
|
||||
`node_modules/react-native-webrtc/ios/WebRTC.framework` into your project.
|
||||
|
||||
## API
|
||||
|
||||
JitsiMeet is an iOS framework which embodies the whole Jitsi Meet experience and
|
||||
makes it reusable by third-party apps.
|
||||
|
||||
To get started:
|
||||
|
||||
1. Add a `JitsiMeetView` to your app using a Storyboard or Interface Builder,
|
||||
for example.
|
||||
|
||||
2. Then, once the view has loaded, set the delegate in your controller and load
|
||||
the desired URL:
|
||||
|
||||
```objc
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
||||
JitsiMeetView *jitsiMeetView = (JitsiMeetView *) self.view;
|
||||
jitsiMeetView.delegate = self;
|
||||
|
||||
JitsiMeetConferenceOptions *options = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
|
||||
builder.serverURL = [NSURL URLWithString:@"https://meet.jit.si"];
|
||||
builder.room = @"test123";
|
||||
builder.audioOnly = YES;
|
||||
}];
|
||||
|
||||
[jitsiMeetView join:options];
|
||||
}
|
||||
```
|
||||
|
||||
### JitsiMeetView class
|
||||
|
||||
The `JitsiMeetView` class is the entry point to the SDK. It a subclass of
|
||||
`UIView` which renders a full conference in the designated area.
|
||||
|
||||
#### delegate
|
||||
|
||||
Property to get/set the `JitsiMeetViewDelegate` on `JitsiMeetView`.
|
||||
|
||||
#### join:JitsiMeetConferenceOptions
|
||||
|
||||
Joins the conference specified by the given options.
|
||||
|
||||
```objc
|
||||
JitsiMeetConferenceOptions *options = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
|
||||
builder.serverURL = [NSURL URLWithString:@"https://meet.jit.si"];
|
||||
builder.room = @"test123";
|
||||
builder.audioOnly = NO;
|
||||
builder.audioMuted = NO;
|
||||
builder.videoMuted = NO;
|
||||
builder.welcomePageEnabled = NO;
|
||||
}];
|
||||
|
||||
[jitsiMeetView join:options];
|
||||
```
|
||||
|
||||
#### leave
|
||||
|
||||
Leaves the currently active conference.
|
||||
|
||||
#### Universal / deep linking
|
||||
|
||||
In order to support Universal / deep linking, `JitsiMeet` offers 2 class
|
||||
methods that you app's delegate should call in order for the app to follow those
|
||||
links.
|
||||
|
||||
If these functions return NO it means the URL wasn't handled by the SDK. This
|
||||
is useful when the host application uses other SDKs which also use linking.
|
||||
|
||||
```objc
|
||||
- (BOOL)application:(UIApplication *)application
|
||||
continueUserActivity:(NSUserActivity *)userActivity
|
||||
restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler
|
||||
{
|
||||
return [[JitsiMeet sharedInstance] application:application
|
||||
continueUserActivity:userActivity
|
||||
restorationHandler:restorationHandler];
|
||||
}
|
||||
```
|
||||
|
||||
And also one of the following:
|
||||
|
||||
```objc
|
||||
// See https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623073-application?language=objc
|
||||
- (BOOL)application:(UIApplication *)app
|
||||
openURL:(NSURL *)url
|
||||
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
|
||||
return [[JitsiMeet sharedInstance] application:app
|
||||
openURL:url
|
||||
options: options];
|
||||
}
|
||||
```
|
||||
|
||||
### JitsiMeetViewDelegate
|
||||
|
||||
This delegate is optional, and can be set on the `JitsiMeetView` instance using
|
||||
the `delegate` property.
|
||||
|
||||
It provides information about the conference state: was it joined, left, did it
|
||||
fail?
|
||||
|
||||
All methods in this delegate are optional.
|
||||
|
||||
#### conferenceJoined
|
||||
|
||||
Called when a conference was joined.
|
||||
|
||||
The `data` dictionary contains a "url" key with the conference URL.
|
||||
|
||||
#### conferenceTerminated
|
||||
|
||||
Called when a conference was terminated either by user choice or due to a
|
||||
failure.
|
||||
|
||||
The `data` dictionary contains an "error" key with the error and a "url" key
|
||||
with the conference URL. If the conference finished gracefully no `error`
|
||||
key will be present.
|
||||
|
||||
#### conferenceWillJoin
|
||||
|
||||
Called before a conference is joined.
|
||||
|
||||
The `data` dictionary contains a "url" key with the conference URL.
|
||||
|
||||
#### enterPictureInPicture
|
||||
|
||||
Called when entering Picture-in-Picture is requested by the user. The app should
|
||||
now activate its Picture-in-Picture implementation (and resize the associated
|
||||
`JitsiMeetView`. The latter will automatically detect its new size and adjust
|
||||
its user interface to a variant appropriate for the small size ordinarily
|
||||
associated with Picture-in-Picture.)
|
||||
|
||||
The `data` dictionary is empty.
|
||||
|
||||
### Picture-in-Picture
|
||||
|
||||
`JitsiMeetView` will automatically adjust its UI when presented in a
|
||||
Picture-in-Picture style scenario, in a rectangle too small to accommodate its
|
||||
"full" UI.
|
||||
|
||||
Jitsi Meet SDK does not currently implement native Picture-in-Picture on iOS. If
|
||||
desired, apps need to implement non-native Picture-in-Picture themselves and
|
||||
resize `JitsiMeetView`.
|
||||
|
||||
If `delegate` implements `enterPictureInPicture:`, the in-call toolbar will
|
||||
render a button to afford the user to request entering Picture-in-Picture.
|
||||
|
||||
## Dropbox integration
|
||||
|
||||
To setup the Dropbox integration, follow these steps:
|
||||
|
||||
1. Add the following to the app's Info.plist and change `<APP_KEY>` to your
|
||||
Dropbox app key:
|
||||
```
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string></string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>db-<APP_KEY></string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>LSApplicationQueriesSchemes</key>
|
||||
<array>
|
||||
<string>dbapi-2</string>
|
||||
<string>dbapi-8-emm</string>
|
||||
</array>
|
||||
```
|
||||
|
||||
2. Make sure your app calls the Jitsi Meet SDK universal / deep linking delegate
|
||||
methods.
|
||||
This document has been moved to [The Handbook](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-ios-sdk).
|
||||
|
||||
@@ -18,25 +18,17 @@
|
||||
#import "AppDelegate.h"
|
||||
#import "FIRUtilities.h"
|
||||
#import "Types.h"
|
||||
#import "ViewController.h"
|
||||
|
||||
@import Crashlytics;
|
||||
@import Fabric;
|
||||
@import Firebase;
|
||||
@import JitsiMeet;
|
||||
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application
|
||||
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
|
||||
// Initialize Crashlytics and Firebase if a valid GoogleService-Info.plist file was provided.
|
||||
if ([FIRUtilities appContainsRealServiceInfoPlist]) {
|
||||
NSLog(@"Enablign Crashlytics and Firebase");
|
||||
[FIRApp configure];
|
||||
[Fabric with:@[[Crashlytics class]]];
|
||||
}
|
||||
|
||||
JitsiMeet *jitsiMeet = [JitsiMeet sharedInstance];
|
||||
|
||||
jitsiMeet.conferenceActivityType = JitsiMeetConferenceActivityType;
|
||||
@@ -54,11 +46,25 @@
|
||||
#endif
|
||||
}];
|
||||
|
||||
// Initialize Crashlytics and Firebase if a valid GoogleService-Info.plist file was provided.
|
||||
if ([FIRUtilities appContainsRealServiceInfoPlist] && ![jitsiMeet isCrashReportingDisabled]) {
|
||||
NSLog(@"Enabling Crashlytics and Firebase");
|
||||
[FIRApp configure];
|
||||
[Fabric with:@[[Crashlytics class]]];
|
||||
}
|
||||
|
||||
[jitsiMeet application:application didFinishLaunchingWithOptions:launchOptions];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void) applicationWillTerminate:(UIApplication *)application {
|
||||
NSLog(@"Application will terminate!");
|
||||
// Try to leave the current meeting graceefully.
|
||||
ViewController *rootController = (ViewController *)self.window.rootViewController;
|
||||
[rootController terminate];
|
||||
}
|
||||
|
||||
#pragma mark Linking delegate methods
|
||||
|
||||
- (BOOL)application:(UIApplication *)application
|
||||
|
||||
@@ -16,12 +16,7 @@
|
||||
|
||||
#import "FIRUtilities.h"
|
||||
|
||||
// Plist file name.
|
||||
NSString *const kGoogleServiceInfoFileName = @"GoogleService-Info";
|
||||
// Plist file type.
|
||||
NSString *const kGoogleServiceInfoFileType = @"plist";
|
||||
NSString *const kGoogleAppIDPlistKey = @"GOOGLE_APP_ID";
|
||||
|
||||
@import JitsiMeet;
|
||||
|
||||
@implementation FIRUtilities
|
||||
|
||||
@@ -30,37 +25,11 @@ NSString *const kGoogleAppIDPlistKey = @"GOOGLE_APP_ID";
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSBundle *bundle = [NSBundle mainBundle];
|
||||
containsRealServiceInfoPlist = [self containsRealServiceInfoPlistInBundle:bundle];
|
||||
containsRealServiceInfoPlist = [InfoPlistUtil containsRealServiceInfoPlistInBundle:bundle];
|
||||
});
|
||||
return containsRealServiceInfoPlist;
|
||||
}
|
||||
|
||||
+ (BOOL)containsRealServiceInfoPlistInBundle:(NSBundle *)bundle {
|
||||
NSString *bundlePath = bundle.bundlePath;
|
||||
if (!bundlePath.length) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSString *plistFilePath = [bundle pathForResource:kGoogleServiceInfoFileName
|
||||
ofType:kGoogleServiceInfoFileType];
|
||||
if (!plistFilePath.length) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile:plistFilePath];
|
||||
if (!plist) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Perform a very naive validation by checking to see if the plist has the dummy google app id
|
||||
NSString *googleAppID = plist[kGoogleAppIDPlistKey];
|
||||
if (!googleAppID.length) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (NSURL *)extractURL: (FIRDynamicLink*)dynamicLink {
|
||||
NSURL *url = nil;
|
||||
if (dynamicLink != nil) {
|
||||
|
||||
@@ -20,4 +20,6 @@
|
||||
|
||||
@interface ViewController : UIViewController<JitsiMeetViewDelegate>
|
||||
|
||||
- (void)terminate;
|
||||
|
||||
@end
|
||||
|
||||
@@ -102,4 +102,11 @@
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma mark - Helpers
|
||||
|
||||
- (void)terminate {
|
||||
JitsiMeetView *view = (JitsiMeetView *) self.view;
|
||||
[view leave];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
C69EFA0E209A0F660027712B /* JMCallKitListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = C69EFA0B209A0F660027712B /* JMCallKitListener.swift */; };
|
||||
C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3425E204EF76800E062DD /* DragGestureController.swift */; };
|
||||
C6CC49AF207412CF000DFA42 /* PiPViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6CC49AE207412CF000DFA42 /* PiPViewCoordinator.swift */; };
|
||||
C8AFD27F2462C613000293D2 /* InfoPlistUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = C8AFD27D2462C613000293D2 /* InfoPlistUtil.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C8AFD2802462C613000293D2 /* InfoPlistUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = C8AFD27E2462C613000293D2 /* InfoPlistUtil.m */; };
|
||||
DE438CDA2350934700DD541D /* JavaScriptSandbox.m in Sources */ = {isa = PBXBuildFile; fileRef = DE438CD82350934700DD541D /* JavaScriptSandbox.m */; };
|
||||
DE65AACA2317FFCD00290BEC /* LogUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AAC92317FFCD00290BEC /* LogUtils.h */; };
|
||||
DE65AACC2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */; };
|
||||
@@ -105,6 +107,8 @@
|
||||
C6A3425E204EF76800E062DD /* DragGestureController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DragGestureController.swift; sourceTree = "<group>"; };
|
||||
C6CC49AE207412CF000DFA42 /* PiPViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PiPViewCoordinator.swift; sourceTree = "<group>"; };
|
||||
C6F99C13204DB63D0001F710 /* JitsiMeetView+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetView+Private.h"; sourceTree = "<group>"; };
|
||||
C8AFD27D2462C613000293D2 /* InfoPlistUtil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InfoPlistUtil.h; sourceTree = "<group>"; };
|
||||
C8AFD27E2462C613000293D2 /* InfoPlistUtil.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InfoPlistUtil.m; sourceTree = "<group>"; };
|
||||
DE438CD82350934700DD541D /* JavaScriptSandbox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JavaScriptSandbox.m; sourceTree = "<group>"; };
|
||||
DE65AAC92317FFCD00290BEC /* LogUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LogUtils.h; sourceTree = "<group>"; };
|
||||
DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetBaseLogHandler+Private.h"; sourceTree = "<group>"; };
|
||||
@@ -223,6 +227,8 @@
|
||||
DEFE535521FB2E8300011A3A /* ReactUtils.m */,
|
||||
0B93EF7C1EC9DDCD0030D24D /* RCTBridgeWrapper.h */,
|
||||
0B93EF7D1EC9DDCD0030D24D /* RCTBridgeWrapper.m */,
|
||||
C8AFD27D2462C613000293D2 /* InfoPlistUtil.h */,
|
||||
C8AFD27E2462C613000293D2 /* InfoPlistUtil.m */,
|
||||
);
|
||||
path = src;
|
||||
sourceTree = "<group>";
|
||||
@@ -303,6 +309,7 @@
|
||||
DE81A2D42316AC4D00AE1940 /* JitsiMeetLogger.h in Headers */,
|
||||
DE65AACA2317FFCD00290BEC /* LogUtils.h in Headers */,
|
||||
DEAD3226220C497000E93636 /* JitsiMeetConferenceOptions.h in Headers */,
|
||||
C8AFD27F2462C613000293D2 /* InfoPlistUtil.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -482,6 +489,7 @@
|
||||
0B93EF7F1EC9DDCD0030D24D /* RCTBridgeWrapper.m in Sources */,
|
||||
0BA13D311EE83FF8007BEF7F /* ExternalAPI.m in Sources */,
|
||||
0BCA49601EC4B6C600B793EE /* POSIX.m in Sources */,
|
||||
C8AFD2802462C613000293D2 /* InfoPlistUtil.m in Sources */,
|
||||
C6CC49AF207412CF000DFA42 /* PiPViewCoordinator.swift in Sources */,
|
||||
DEFC743F21B178FA00E4DD96 /* LocaleDetector.m in Sources */,
|
||||
0BCA495F1EC4B6C600B793EE /* AudioMode.m in Sources */,
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTLog.h>
|
||||
|
||||
#import "InfoPlistUtil.h"
|
||||
|
||||
@interface AppInfo : NSObject<RCTBridgeModule>
|
||||
@end
|
||||
|
||||
@@ -67,13 +69,15 @@ RCT_EXPORT_MODULE();
|
||||
buildNumber = @"";
|
||||
}
|
||||
|
||||
BOOL isGoogleServiceEnabled = [InfoPlistUtil containsRealServiceInfoPlistInBundle:[NSBundle mainBundle]];
|
||||
|
||||
return @{
|
||||
@"calendarEnabled": [NSNumber numberWithBool:calendarEnabled],
|
||||
@"buildNumber": buildNumber,
|
||||
@"name": name,
|
||||
@"sdkBundlePath": sdkBundlePath,
|
||||
@"version": version
|
||||
@"version": version,
|
||||
@"GOOGLE_SERVICES_ENABLED": [NSNumber numberWithBool:isGoogleServiceEnabled]
|
||||
};
|
||||
};
|
||||
|
||||
@end
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.8.1</string>
|
||||
<string>2.9.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
23
ios/sdk/src/InfoPlistUtil.h
Normal file
23
ios/sdk/src/InfoPlistUtil.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright @ 2019-present 8x8, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface InfoPlistUtil : NSObject
|
||||
|
||||
+ (BOOL)containsRealServiceInfoPlistInBundle:(NSBundle *)bundle;
|
||||
|
||||
@end
|
||||
52
ios/sdk/src/InfoPlistUtil.m
Normal file
52
ios/sdk/src/InfoPlistUtil.m
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright @ 2019-present 8x8, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "InfoPlistUtil.h"
|
||||
|
||||
// Plist file name.
|
||||
NSString *const kGoogleServiceInfoFileName = @"GoogleService-Info";
|
||||
// Plist file type.
|
||||
NSString *const kGoogleServiceInfoFileType = @"plist";
|
||||
NSString *const kGoogleAppIDPlistKey = @"GOOGLE_APP_ID";
|
||||
|
||||
@implementation InfoPlistUtil
|
||||
|
||||
+ (BOOL)containsRealServiceInfoPlistInBundle:(NSBundle *)bundle {
|
||||
NSString *bundlePath = bundle.bundlePath;
|
||||
if (!bundlePath.length) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSString *plistFilePath = [bundle pathForResource:kGoogleServiceInfoFileName
|
||||
ofType:kGoogleServiceInfoFileType];
|
||||
if (!plistFilePath.length) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile:plistFilePath];
|
||||
if (!plist) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Perform a very naive validation by checking to see if the plist has the dummy google app id
|
||||
NSString *googleAppID = plist[kGoogleAppIDPlistKey];
|
||||
if (!googleAppID.length) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
@end
|
||||
@@ -20,6 +20,7 @@
|
||||
#import <JitsiMeet/JitsiMeetConferenceOptions.h>
|
||||
#import <JitsiMeet/JitsiMeetLogger.h>
|
||||
#import <JitsiMeet/JitsiMeetBaseLogHandler.h>
|
||||
#import <JitsiMeet/InfoPlistUtil.h>
|
||||
|
||||
|
||||
@interface JitsiMeet : NSObject
|
||||
@@ -64,4 +65,6 @@
|
||||
|
||||
- (JitsiMeetConferenceOptions *_Nonnull)getInitialConferenceOptions;
|
||||
|
||||
- (BOOL)isCrashReportingDisabled;
|
||||
|
||||
@end
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
JitsiMeetConferenceOptions *conferenceOptions = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
|
||||
builder.room = [url absoluteString];
|
||||
}];
|
||||
|
||||
|
||||
return [JitsiMeetView setPropsInViews:[conferenceOptions asProps]];
|
||||
}
|
||||
|
||||
@@ -132,6 +132,11 @@
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)isCrashReportingDisabled {
|
||||
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"jitsi-default-preferences"];
|
||||
return [userDefaults stringForKey:@"isCrashReportingDisabled"];
|
||||
}
|
||||
|
||||
- (JitsiMeetConferenceOptions *)optionsFromUserActivity:(NSUserActivity *)userActivity {
|
||||
NSString *activityType = userActivity.activityType;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright @ 2017-present Atlassian Pty Ltd
|
||||
* Copyright @ 2017-present 8x8, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,18 +46,9 @@ public class PiPViewCoordinator {
|
||||
|
||||
public var initialPositionInSuperview = Position.lowerRightCorner
|
||||
|
||||
/// The size ratio of the view when in PiP mode
|
||||
public var pipSizeRatio: CGFloat = {
|
||||
let deviceIdiom = UIScreen.main.traitCollection.userInterfaceIdiom
|
||||
switch deviceIdiom {
|
||||
case .pad:
|
||||
return 0.25
|
||||
case .phone:
|
||||
return 0.33
|
||||
default:
|
||||
return 0.25
|
||||
}
|
||||
}()
|
||||
// Unused. Remove on the next major release.
|
||||
@available(*, deprecated, message: "The PiP window size is now fixed to 150px.")
|
||||
public var c: CGFloat = 0.0
|
||||
|
||||
public weak var delegate: PiPViewCoordinatorDelegate?
|
||||
|
||||
@@ -212,8 +203,7 @@ public class PiPViewCoordinator {
|
||||
|
||||
// resize to suggested ratio and position to the bottom right
|
||||
let adjustedBounds = bounds.inset(by: dragBoundInsets)
|
||||
let size = CGSize(width: bounds.size.width * pipSizeRatio,
|
||||
height: bounds.size.height * pipSizeRatio)
|
||||
let size = CGSize(width: 150, height: 150)
|
||||
let origin = initialPositionFor(pipSize: size, bounds: adjustedBounds)
|
||||
return CGRect(x: origin.x, y: origin.y, width: size.width, height: size.height)
|
||||
}
|
||||
|
||||
@@ -1,34 +1,42 @@
|
||||
{
|
||||
"en": "",
|
||||
"af": "",
|
||||
"bg": "",
|
||||
"ca": "",
|
||||
"cs": "",
|
||||
"da": "",
|
||||
"de": "",
|
||||
"el": "",
|
||||
"enGB": "",
|
||||
"eo": "",
|
||||
"es": "",
|
||||
"esUS": "",
|
||||
"et": "",
|
||||
"fi": "",
|
||||
"fr": "",
|
||||
"frCA": "",
|
||||
"hr": "",
|
||||
"hu": "",
|
||||
"hy": "",
|
||||
"it": "",
|
||||
"ja": "",
|
||||
"ko": "",
|
||||
"nl": "",
|
||||
"oc": "",
|
||||
"pl": "",
|
||||
"ptBR": "",
|
||||
"ru": "",
|
||||
"sv": "",
|
||||
"tr": "",
|
||||
"vi": "",
|
||||
"zhCN": "",
|
||||
"zhTW": ""
|
||||
"en": "الإنجليزية",
|
||||
"af": "الأفريكانية",
|
||||
"bg": "البلغارية",
|
||||
"ca": "الكاتالانية",
|
||||
"cs": "التشيكية",
|
||||
"da": "الدنماركية",
|
||||
"de": "الألمانية",
|
||||
"el": "اليونانية",
|
||||
"enGB": "الإنجليزية (المملكة المتحدة)",
|
||||
"eo": "الإسبرانتو",
|
||||
"es": "الإسبانية",
|
||||
"esUS": "الإسبانية (أمريكا اللاتينية)",
|
||||
"et": "الإستونية",
|
||||
"fi": "الفنلندية",
|
||||
"fr": "الفرنسية",
|
||||
"frCA": "الفرنسية (الكندية)",
|
||||
"hr": "الكرواتية",
|
||||
"hu": "الهنغارية",
|
||||
"hy": "الأرمنية",
|
||||
"it": "الإيطالية",
|
||||
"ja": "اليابانية",
|
||||
"ko": "الكورية",
|
||||
"nl": "الهولندية",
|
||||
"oc": "القسطانية",
|
||||
"pl": "البولندية",
|
||||
"ptBR": "البرتغالية (البرازيل)",
|
||||
"ru": "الروسية",
|
||||
"sv": "السويدية",
|
||||
"tr": "التركية",
|
||||
"vi": "الفيتنامية",
|
||||
"zhCN": "الصينية (الصين)",
|
||||
"zhTW": "الصينية (تايوان)",
|
||||
"th": "التايلندية",
|
||||
"sc": "السردينية",
|
||||
"eu": "الباسكية",
|
||||
"uk": "الأوكرانية",
|
||||
"sk": "السلوفاكية",
|
||||
"lt": "الليتوانية",
|
||||
"id": "الإندونيسية",
|
||||
"he": "العبرية"
|
||||
}
|
||||
|
||||
42
lang/languages-el.json
Normal file
42
lang/languages-el.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"en": "Αγγλικά",
|
||||
"af": "Αφρικανικά",
|
||||
"bg": "Βουλγάρικα",
|
||||
"ca": "Καταλανικά",
|
||||
"cs": "Τσέχικα",
|
||||
"da": "Δανέζικα",
|
||||
"de": "Γερμανικά",
|
||||
"el": "Ελληνικά",
|
||||
"enGB": "Αγγλικά (Ηνωμένου Βασιλείου)",
|
||||
"eo": "Εσπεράντο",
|
||||
"es": "Ισπανικά",
|
||||
"esUS": "Ισπανικά (Λατινικής Αμερικής)",
|
||||
"et": "Εσθονικά",
|
||||
"eu": "Βάσκικα",
|
||||
"fi": "Φινλανδικά",
|
||||
"fr": "Γαλλικά",
|
||||
"frCA": "Γαλλικά (Καναδικά)",
|
||||
"he": "Εβραϊκά",
|
||||
"hr": "Κροατικά",
|
||||
"hu": "Ουγγρικά",
|
||||
"hy": "Αρμένικα",
|
||||
"id": "Ινδονησιακά",
|
||||
"it": "Ιταλικά",
|
||||
"ja": "Ιαπωνικά",
|
||||
"ko": "Κορεάτικα",
|
||||
"lt": "Λιθουανικά",
|
||||
"nl": "Ολλανδικά",
|
||||
"oc": "Οξιτανικά",
|
||||
"pl": "Πολωνικά",
|
||||
"ptBR": "Πορτογαλικά (Βραζιλίας)",
|
||||
"ru": "Ρωσικά",
|
||||
"sc": "Σαρδηνικά",
|
||||
"sk": "Σλοβακικά",
|
||||
"sv": "Σουηδικά",
|
||||
"th": "Ταϊλανδικά",
|
||||
"tr": "Τουρκικά",
|
||||
"uk": "Ουκρανικά",
|
||||
"vi": "Βιετναμέζικα",
|
||||
"zhCN": "Κινέζικα (Κίνας)",
|
||||
"zhTW": "Κινέζικα (Ταϊβάν)"
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
"ptBR": "Portuguese (Brazil)",
|
||||
"ru": "Russian",
|
||||
"sk": "",
|
||||
"sl": "",
|
||||
"sl": "Slovenian",
|
||||
"sv": "Swedish",
|
||||
"tr": "Turkish",
|
||||
"vi": "Vietnamese",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"bg": "Bulgara",
|
||||
"cs": "Ĉeĥa",
|
||||
"de": "Germana",
|
||||
"el": "Hispana",
|
||||
"el": "Greka",
|
||||
"eo": "Esperanto",
|
||||
"es": "Hispana",
|
||||
"fr": "Franca",
|
||||
|
||||
37
lang/languages-he.json
Normal file
37
lang/languages-he.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"en": "אנגלית",
|
||||
"af": "אפריקאית",
|
||||
"bg": "בולגרית",
|
||||
"ca": "קטלנית",
|
||||
"cs": "קזחית",
|
||||
"da": "דנית",
|
||||
"de": "גרמנית",
|
||||
"el": "יוונית",
|
||||
"enGB": "אנגלית (בריטניה)",
|
||||
"eo": "אספרנטו",
|
||||
"es": "ספרדית",
|
||||
"esUS": "ספרדית (אמריקה הלטינית)",
|
||||
"et": "אסטונית",
|
||||
"fi": "פינית",
|
||||
"fr": "צרפתית",
|
||||
"frCA": "צרפתית (קנדה)",
|
||||
"he": "עברית",
|
||||
"hr": "קראוטית",
|
||||
"hu": "הונגרית",
|
||||
"hy": "ארמנית",
|
||||
"it": "איטלקית",
|
||||
"ja": "יפנית",
|
||||
"ko": "קוראנית",
|
||||
"nl": "הולנדית",
|
||||
"oc": "אוקיאנית",
|
||||
"pl": "פולנית",
|
||||
"ptBR": "פורטוגזית (ברזיל)",
|
||||
"ru": "רוסית",
|
||||
"sc": "סרבית",
|
||||
"sk": "סלובקית",
|
||||
"sv": "שוודית",
|
||||
"tr": "טורקית",
|
||||
"vi": "ויטנאמית",
|
||||
"zhCN": "סינית (סין)",
|
||||
"zhTW": "סינית (טיוואן)"
|
||||
}
|
||||
39
lang/languages-id.json
Normal file
39
lang/languages-id.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"en": "Bahasa Inggris - US",
|
||||
"af": "Bahasa Afrika",
|
||||
"bg": "Bahasa Bulgaria",
|
||||
"ca": "Bahasa Katalan",
|
||||
"cs": "Bahasa Ceko",
|
||||
"da": "Bahasa Denmark",
|
||||
"de": "Bahasa Jerman",
|
||||
"el": "Bahasa Yunani",
|
||||
"enGB": "Bahasa Inggris - UK",
|
||||
"eo": "Esperanto",
|
||||
"es": "Bahasa Spanyol",
|
||||
"esUS": "Bahasa Spanyol - Latin",
|
||||
"et": "Bahasa Estonia",
|
||||
"fi": "Bahasa Finlandia",
|
||||
"fr": "Bahasa Prancis",
|
||||
"frCA": "Bahasa Prancis - Kanada",
|
||||
"he": "Bahasa Hebrew",
|
||||
"hr": "Bahasa Kroasia",
|
||||
"hu": "Bahasa Hongaria",
|
||||
"hy": "Bahasa Armenia",
|
||||
"id": "Bahasa Indonesia",
|
||||
"it": "Bahasa Italia",
|
||||
"ja": "Bahasa Jepang",
|
||||
"ko": "Bahasa Korea",
|
||||
"lt": "Bahasa Lituania",
|
||||
"nl": "Bahasa Belanda",
|
||||
"oc": "Bahasa Oceania",
|
||||
"pl": "Bahasa Polandia",
|
||||
"ptBR": "Bahasa Portugis - Brazil",
|
||||
"ru": "Bahasa Rusia",
|
||||
"sc": "Bahasa Sardinia",
|
||||
"sk": "Bahasa Slovakia",
|
||||
"sv": "Bahasa Swedia",
|
||||
"tr": "Bahasa Turki",
|
||||
"vi": "Bahasa Vietnam",
|
||||
"zhCN": "Bahasa Mandarin",
|
||||
"zhTW": "Bahasa Mandarin - Taiwan"
|
||||
}
|
||||
34
lang/languages-lv.json
Normal file
34
lang/languages-lv.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"en": "angļu",
|
||||
"af": "āfrikāņu",
|
||||
"bg": "bulgāru",
|
||||
"ca": "kataloniešu",
|
||||
"cs": "čehu",
|
||||
"de": "vācu",
|
||||
"el": "grieķu",
|
||||
"enGB": "angļu (Lielbritānija)",
|
||||
"eo": "esperanto",
|
||||
"es": "spāņu",
|
||||
"esUS": "spāņu (Dienvidamerika)",
|
||||
"et": "igauņu",
|
||||
"fi": "somu",
|
||||
"fr": "franču",
|
||||
"frCA": "franču (Kanāda)",
|
||||
"hr": "horvātu",
|
||||
"hu": "ungāru",
|
||||
"hy": "armēņu",
|
||||
"it": "itāļu",
|
||||
"ja": "japānu",
|
||||
"ko": "korejiešu",
|
||||
"lv": "laviešu",
|
||||
"nl": "holandiešu",
|
||||
"oc": "oksitāņu",
|
||||
"pl": "poļu",
|
||||
"ptBR": "portugāļu (Brazīlija)",
|
||||
"ru": "krievu",
|
||||
"sv": "zviedru",
|
||||
"tr": "turku",
|
||||
"vi": "vjetnamiešu",
|
||||
"zhCN": "ķīniešu (Ķīna)",
|
||||
"zhTW": "ķīniešu (Taivana)"
|
||||
}
|
||||
@@ -30,5 +30,13 @@
|
||||
"zhCN": "Chinés (China)",
|
||||
"zhTW": "Chinés (Taiwan)",
|
||||
"et": "Estonian",
|
||||
"da": "Danés"
|
||||
"da": "Danés",
|
||||
"uk": "Ucraïnian",
|
||||
"th": "Tai",
|
||||
"sk": "Eslovac",
|
||||
"sc": "Sarde",
|
||||
"lt": "Lituanian",
|
||||
"id": "Indonesian",
|
||||
"he": "Ebrèu",
|
||||
"eu": "Basc"
|
||||
}
|
||||
|
||||
38
lang/languages-ro.json
Normal file
38
lang/languages-ro.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"en": "Engleză",
|
||||
"af": "Afrikaans",
|
||||
"az": "",
|
||||
"bg": "Bulgară",
|
||||
"cs": "Cehă",
|
||||
"de": "Germană",
|
||||
"el": "Greacă",
|
||||
"eo": "Esperanto",
|
||||
"es": "Spaniolă",
|
||||
"fr": "Franceză",
|
||||
"hy": "Armeniana",
|
||||
"it": "Italiană",
|
||||
"ja": "Japoneză",
|
||||
"ko": "Koreană",
|
||||
"nb": "",
|
||||
"oc": "Occitan",
|
||||
"pl": "Poloneză",
|
||||
"ptBR": "Portugheză (Brazilia)",
|
||||
"ru": "Rusă",
|
||||
"sk": "Slovacă",
|
||||
"sl": "Slovenă",
|
||||
"sv": "Suedeză",
|
||||
"tr": "Turcă",
|
||||
"vi": "Vietnameză",
|
||||
"zhCN": "Chineză (China)",
|
||||
"zhTW": "Chineză (Taiwan)",
|
||||
"nl": "Olandeză",
|
||||
"hu": "Maghiară",
|
||||
"hr": "Croată",
|
||||
"frCA": "Franceză (Canadia)",
|
||||
"fi": "Finlandeză",
|
||||
"et": "Estoniană",
|
||||
"esUS": "Spaniolă (America Latină)",
|
||||
"enGB": "Engleză (Regatul Unit)",
|
||||
"da": "Daneză",
|
||||
"că": "Catalană"
|
||||
}
|
||||
@@ -1,27 +1,27 @@
|
||||
{
|
||||
"en": "Angleščina",
|
||||
"af": "",
|
||||
"az": "",
|
||||
"af": "Afrikanščina",
|
||||
"az": "Azerbajdanščina",
|
||||
"bg": "Bolgarščina",
|
||||
"cs": "",
|
||||
"cs": "Češčina",
|
||||
"de": "Nemščina",
|
||||
"el": "",
|
||||
"eo": "",
|
||||
"es": "",
|
||||
"el": "Grščina",
|
||||
"eo": "Esperanto",
|
||||
"es": "Španščina",
|
||||
"fr": "Francoščina",
|
||||
"hy": "",
|
||||
"hy": "Armenščina",
|
||||
"it": "Italjanščina",
|
||||
"ja": "",
|
||||
"ko": "",
|
||||
"nb": "",
|
||||
"oc": "",
|
||||
"pl": "",
|
||||
"ptBR": "",
|
||||
"ru": "",
|
||||
"sk": "",
|
||||
"ja": "Japonščina",
|
||||
"ko": "Korejščina",
|
||||
"nb": "Norveščina (Bokmål)",
|
||||
"oc": "Okcitanščina",
|
||||
"pl": "Poljščina",
|
||||
"ptBR": "Portugalščina (Brazilija)",
|
||||
"ru": "Ruščina",
|
||||
"sk": "Slovaščina",
|
||||
"sl": "Slovenščina",
|
||||
"sv": "",
|
||||
"sv": "Švedščina",
|
||||
"tr": "Turščina",
|
||||
"vi": "",
|
||||
"zhCN": ""
|
||||
"vi": "Vietnamščina",
|
||||
"zhCN": "kitajščina (poenostavljena)"
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"en": "English",
|
||||
"af": "Afrikaans",
|
||||
"ar": "Arabic",
|
||||
"bg": "Bulgarian",
|
||||
"ca": "Catalan",
|
||||
"cs": "Czech",
|
||||
@@ -12,6 +13,7 @@
|
||||
"es": "Spanish",
|
||||
"esUS": "Spanish (Latin America)",
|
||||
"et": "Estonian",
|
||||
"eu": "Basque",
|
||||
"fi": "Finnish",
|
||||
"fr": "French",
|
||||
"frCA": "French (Canadian)",
|
||||
@@ -19,6 +21,7 @@
|
||||
"hr": "Croatian",
|
||||
"hu": "Hungarian",
|
||||
"hy": "Armenian",
|
||||
"id": "Indonesian",
|
||||
"it": "Italian",
|
||||
"ja": "Japanese",
|
||||
"ko": "Korean",
|
||||
@@ -28,11 +31,14 @@
|
||||
"pl": "Polish",
|
||||
"ptBR": "Portuguese (Brazil)",
|
||||
"ru": "Russian",
|
||||
"ro": "Romanian",
|
||||
"sc": "Sardinian",
|
||||
"sk": "Slovak",
|
||||
"sl": "Slovenian",
|
||||
"sv": "Swedish",
|
||||
"th": "Thailand",
|
||||
"tr": "Turkish",
|
||||
"uk": "Ukrainian",
|
||||
"vi": "Vietnamese",
|
||||
"zhCN": "Chinese (China)",
|
||||
"zhTW": "Chinese (Taiwan)"
|
||||
|
||||
@@ -421,7 +421,7 @@
|
||||
"somebody": "Iemand",
|
||||
"startSilentTitle": "",
|
||||
"startSilentDescription": "",
|
||||
"suboptimalExperienceDescription": "Gits... ons is bevrees u ervaring met {{appName}} gaan nie so goed wees hier nie. Ons soek maniere om dit die hoof te bied, maar probeer intussen een van die <a href='static/recommendedBrowsers.html' target='_blank'>volledig ondersteunde blaaiers</a>.",
|
||||
"suboptimalExperienceDescription": "Gits... ons is bevrees u ervaring met {{appName}} gaan nie so goed wees hier nie. Ons soek maniere om dit die hoof te bied, maar probeer intussen een van die <a href='{{recommendedBrowserPageLink}}' target='_blank'>volledig ondersteunde blaaiers</a>.",
|
||||
"suboptimalExperienceTitle": "Blaaierwaarskuwing",
|
||||
"unmute": "",
|
||||
"newDeviceCameraTitle": "",
|
||||
@@ -664,9 +664,6 @@
|
||||
"lowDefinition": "Laedefinisie",
|
||||
"onlyAudioAvailable": "Net klank is beskikbaar",
|
||||
"onlyAudioSupported": "Op dié blaaier ondersteun ons slegs klank.",
|
||||
"p2pEnabled": "",
|
||||
"p2pVideoQualityDescription": "",
|
||||
"recHighDefinitionOnly": "",
|
||||
"sd": "SD",
|
||||
"standardDefinition": "Standaarddefinisie"
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -460,7 +460,7 @@
|
||||
"somebody": "Хтосьці",
|
||||
"startSilentTitle": "У вас адсутнічае гук!",
|
||||
"startSilentDescription": "Перазайдзiце ў канферэнцыю, каб уключыць гук",
|
||||
"suboptimalBrowserWarning": "На жаль, ваш браўзэр не цалкам падтрымлівае дадзеную сістэму вэб-канференцый. Мы працуем над праблемай, аднак, пакуль рэкамендуем вам скарыстацца <a href='static/recommendedBrowsers.html' target='_blank'> наступнымі браўзэрамі</a >.",
|
||||
"suboptimalBrowserWarning": "На жаль, ваш браўзэр не цалкам падтрымлівае дадзеную сістэму вэб-канференцый. Мы працуем над праблемай, аднак, пакуль рэкамендуем вам скарыстацца <a href='{{recommendedBrowserPageLink}}' target='_blank'> наступнымі браўзэрамі</a >.",
|
||||
"suboptimalExperienceTitle": "Папярэджанне браўзэра",
|
||||
"unmute": "Уключыць мікрафон",
|
||||
"newDeviceCameraTitle": "Выяўлена новая камера",
|
||||
@@ -732,9 +732,6 @@
|
||||
"lowDefinition": "Нізкая якасць",
|
||||
"onlyAudioAvailable": "Толькі гук",
|
||||
"onlyAudioSupported": "У гэтым браўзэры дазволены толькі гук.",
|
||||
"p2pEnabled": "Уключаны рэжым \" кропка-да-кропцы \"",
|
||||
"p2pVideoQualityDescription": "У рэжыме прамога канала сувязі паміж абанентамі можна перамыкацца толькі паміж рэжымамі \" толькі гук \"і \" высокае якасць \". Астатнія налады стануць даступнымі, калі скончыцца гэты рэжым.",
|
||||
"recHighDefinitionOnly": "Пераважна высокую якасць.",
|
||||
"sd": "SD",
|
||||
"sdTooltip": "Відэа стандартнага якасці",
|
||||
"standardDefinition": "Стандартнае якасць (SD)"
|
||||
|
||||
@@ -450,7 +450,7 @@
|
||||
"somebody": "Някой",
|
||||
"startSilentTitle": "Влязохте с опция да не чувате аудио!",
|
||||
"startSilentDescription": "Влезте повторно за да пуснете звука",
|
||||
"suboptimalBrowserWarning": "Опасяваме се, че няма да можете да се насладите на срещата. Работим по въпроса, междувременно използвайте някой от <a href='static/recommendedBrowsers.html' target='_blank'>напълно поддържаните браузъри</a>.",
|
||||
"suboptimalBrowserWarning": "Опасяваме се, че няма да можете да се насладите на срещата. Работим по въпроса, междувременно използвайте някой от <a href='{{recommendedBrowserPageLink}}' target='_blank'>напълно поддържаните браузъри</a>.",
|
||||
"suboptimalExperienceTitle": "Внимание",
|
||||
"unmute": "Пускане на микрофона",
|
||||
"newDeviceCameraTitle": "Засечена е нова камера",
|
||||
@@ -722,9 +722,6 @@
|
||||
"lowDefinition": "Ниско качество",
|
||||
"onlyAudioAvailable": "Само аудио е налично",
|
||||
"onlyAudioSupported": "Този браузър поддържа само аудио.",
|
||||
"p2pEnabled": "Вкл. директно свързване",
|
||||
"p2pVideoQualityDescription": "В директна връзка, получаваното качество може да се сменя между високо и само аудио. Останалите настройки ще са достъпни когато връзката не е директна.",
|
||||
"recHighDefinitionOnly": "Ще се предпочита високо качество.",
|
||||
"sd": "СК",
|
||||
"sdTooltip": "Гледате стандартно качество на видеото",
|
||||
"standardDefinition": "Стандартно качество"
|
||||
|
||||
@@ -455,7 +455,7 @@
|
||||
"somebody": "Algú",
|
||||
"startSilentTitle": "Us hi heu unit sense cap sortida d'àudio!",
|
||||
"startSilentDescription": "Torneu a entrar per a activar l'àudio",
|
||||
"suboptimalBrowserWarning": "Ens sap greu que la vostra experiència de reunió aquí no serà gaire bona. Cerquem maneres per a millorar-la, però fins aleshores, proveu de fer servir algun dels <a href='static/recommendedBrowsers.html' target='_blank'>navegadors completament compatibles</a>.",
|
||||
"suboptimalBrowserWarning": "Ens sap greu que la vostra experiència de reunió aquí no serà gaire bona. Cerquem maneres per a millorar-la, però fins aleshores, proveu de fer servir algun dels <a href='{{recommendedBrowserPageLink}}' target='_blank'>navegadors completament compatibles</a>.",
|
||||
"suboptimalExperienceTitle": "Avís del navegador",
|
||||
"unmute": "Activa el so",
|
||||
"newDeviceCameraTitle": "S'ha detectat una càmera nova",
|
||||
@@ -727,9 +727,6 @@
|
||||
"lowDefinition": "Baixa definició",
|
||||
"onlyAudioAvailable": "Només hi ha disponible l'àudio",
|
||||
"onlyAudioSupported": "Només es permet àudio en aquest navegador.",
|
||||
"p2pEnabled": "Mode d'igual a igual activat",
|
||||
"p2pVideoQualityDescription": "En el mode d'igual a igual, la qualitat del vídeo rebut només es pot canviar entre alta i només àudio. La resta de configuracions no es compliran fins sortir del mode d'igual a igual.",
|
||||
"recHighDefinitionOnly": "L'alta definició serà preferent.",
|
||||
"sd": "SD",
|
||||
"sdTooltip": "Vídeo en definició estàndard",
|
||||
"standardDefinition": "Definició estàndard"
|
||||
|
||||
@@ -456,7 +456,7 @@
|
||||
"somebody": "Někdo",
|
||||
"startSilentTitle": "",
|
||||
"startSilentDescription": "",
|
||||
"suboptimalExperienceDescription": "Sakra... všimli jsme si, že vaše zkušenost s {{appName}} není úplně skvělá. Hledáme cesty, jak bychom to mohli zlepšit. Než se tak stane, vyzkoušejte některý z <a href='static/recommendedBrowsers.html' target='_blank'>plně podporovaných prohlížečů</a>.",
|
||||
"suboptimalExperienceDescription": "Sakra... všimli jsme si, že vaše zkušenost s {{appName}} není úplně skvělá. Hledáme cesty, jak bychom to mohli zlepšit. Než se tak stane, vyzkoušejte některý z <a href='{{recommendedBrowserPageLink}}' target='_blank'>plně podporovaných prohlížečů</a>.",
|
||||
"suboptimalExperienceTitle": "Varování prohlížeče",
|
||||
"unmute": "",
|
||||
"newDeviceCameraTitle": "Detekována nová kamera",
|
||||
@@ -705,9 +705,6 @@
|
||||
"lowDefinition": "Nizká kvalita",
|
||||
"onlyAudioAvailable": "Je k dispozici jen zvuk",
|
||||
"onlyAudioSupported": "V tomto prohlížeči podporujeme jen zvuk.",
|
||||
"p2pEnabled": "Zapnut režim peer to peer",
|
||||
"p2pVideoQualityDescription": "V režimu peer to peer lze kvalitu videa přepínat jen mezi vysokou a pouhým zvukem. Ostatní nastavení se ignorují, dokud tento režim neopustíte.",
|
||||
"recHighDefinitionOnly": "Bude preferována vysoká kvalita.",
|
||||
"sd": "SD",
|
||||
"sdTooltip": "Sledujete obraz v běžné kvalitě",
|
||||
"standardDefinition": "Běžná kvalita"
|
||||
|
||||
@@ -453,7 +453,7 @@
|
||||
"somebody": "Nogen",
|
||||
"startSilentTitle": "",
|
||||
"startSilentDescription": "",
|
||||
"suboptimalExperienceDescription": "Hmmm... vi er bange for at din oplevelse med {{appName}} ikke vil være optimal. Vi arbejder på at forbedre dette, men indtil da så forsøg venligst at bruge en af følgende <a href='static/recommendedBrowsers.html' target='_blank'>fuldt understøttede internet browsere</a>.",
|
||||
"suboptimalExperienceDescription": "Hmmm... vi er bange for at din oplevelse med {{appName}} ikke vil være optimal. Vi arbejder på at forbedre dette, men indtil da så forsøg venligst at bruge en af følgende <a href='{{recommendedBrowserPageLink}}' target='_blank'>fuldt understøttede internet browsere</a>.",
|
||||
"suboptimalExperienceTitle": "Browser Advarsel",
|
||||
"unmute": "",
|
||||
"newDeviceCameraTitle": "Nyt kamerat fundet",
|
||||
@@ -722,9 +722,6 @@
|
||||
"lowDefinition": "Lav opløsning",
|
||||
"onlyAudioAvailable": "Kun-lyd er tilgængelig",
|
||||
"onlyAudioSupported": "Vi understøtter kun-lyd i denne browser.",
|
||||
"p2pEnabled": "Peer to Peer slået til",
|
||||
"p2pVideoQualityDescription": "I peer-to-peer tilstand kan den modtagne opkaldskvalitet kun skiftes mellem høj og kun-lyd. Andre indstillinger vil ikke virke, før peer to peer er afsluttet.",
|
||||
"recHighDefinitionOnly": "Foretrækker høj opløsning.",
|
||||
"sd": "SD",
|
||||
"sdTooltip": "Vider normal opløsnings video",
|
||||
"standardDefinition": "Standard opløsning"
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
{
|
||||
"addPeople": {
|
||||
"add": "Einladen",
|
||||
"addContacts": "Laden Sie Ihre Kontakte ein",
|
||||
"copyInvite": "Sitzungseinladung kopieren",
|
||||
"copyLink": "Meeting-Link kopieren",
|
||||
"copyStream": "Live-Streaming-Link kopieren",
|
||||
"countryNotSupported": "Wir unterstützen dieses Land noch nicht.",
|
||||
"countryReminder": "Telefonnummer nicht in den USA? Bitte sicherstellen, dass die Telefonnummer mit dem Ländercode beginnt.",
|
||||
"defaultEmail": "Ihre Standard-E-Mail",
|
||||
"disabled": "Sie können keine Teilnehmer einladen.",
|
||||
"failedToAdd": "Fehler beim Hinzufügen von Teilnehmern",
|
||||
"footerText": "Abgehender Ruf ist deaktiviert.",
|
||||
"inviteMoreHeader": "Sie sind alleine in der Sitzung",
|
||||
"inviteMoreMailSubject": "An {{appName}} Meeting teilnehmen",
|
||||
"inviteMorePrompt": "Mehr Leute einladen",
|
||||
"linkCopied": "Link in die Zwischenablage kopiert",
|
||||
"loading": "Suche nach Teilnehmern und Telefonnummern",
|
||||
"loadingNumber": "Telefonnummer wird überprüft",
|
||||
"loadingPeople": "Suche nach einzuladenden Teilnehmern",
|
||||
@@ -14,6 +23,9 @@
|
||||
"searchNumbers": "Telefonnummern hinzufügen",
|
||||
"searchPeople": "Nach Teilnehmern suchen",
|
||||
"searchPeopleAndNumbers": "Nach Teilnehmen suchen oder deren Telefonnummern hinzufügen",
|
||||
"shareInvite": "Einladung zur Versammlung teilen",
|
||||
"shareLink": "Teilen Sie den Meeting-Link, um andere einzuladen",
|
||||
"shareStream": "Den Live-Streaming-Link freigeben",
|
||||
"telephone": "Telefon: {{number}}",
|
||||
"title": "Teilnehmer zu dieser Konferenz einladen"
|
||||
},
|
||||
@@ -123,8 +135,10 @@
|
||||
"description": "Nichts passiert? Wir haben versucht, die Konferenz in {{app}} zu öffnen. Versuchen Sie es erneut oder treten Sie der Konferenz in {{app}} im Web bei.",
|
||||
"descriptionWithoutWeb": "Ist nichts passiert? Wir haben versucht, Ihre Besprechung in der „{{app}}“-Desktop-App zu starten.",
|
||||
"downloadApp": "App herunterladen",
|
||||
"ifDoNotHaveApp": "Wenn Sie die App noch nicht haben:",
|
||||
"ifHaveApp": "Wenn Sie die App bereits haben:",
|
||||
"joinInApp": "An dem Meeting teilnehmen mit der App",
|
||||
"launchWebButton": "Im Web öffnen",
|
||||
"openApp": "In der App fortfahren",
|
||||
"title": "Die Konferenz wird in {{app}} geöffnet...",
|
||||
"tryAgainButton": "Erneut mit der nativen Applikation versuchen"
|
||||
},
|
||||
@@ -155,7 +169,7 @@
|
||||
"cameraNotFoundError": "Kamera nicht gefunden.",
|
||||
"cameraNotSendingData": "Die Kamera ist nicht verfügbar. Bitte prüfen, ob eine andere Applikation die Kamera verwendet, eine andere Kamera vom Einstellungs-Menü auswählen oder die Applikation neu laden.",
|
||||
"cameraNotSendingDataTitle": "Zugriff auf Kamera nicht möglich",
|
||||
"cameraPermissionDeniedError": "Die Berechtigung zur Verwendung der Kamera wurde nicht erteilt. Sie können trotzdem an der Konferenz teilnehmen, aber die anderen Teilnehmer können Sie nicht sehen. Verwenden Sie die Kamera-Schaltfläche in der Adressleiste um die Berechtigungen zu erteilen.",
|
||||
"cameraPermissionDeniedError": "Die Berechtigung zur Verwendung der Kamera wurde nicht erteilt. Sie können trotzdem an der Konferenz teilnehmen, aber die anderen Teilnehmer können Sie nicht sehen. Verwenden Sie die Kamera-Schaltfläche in der Adressleiste, um die Berechtigungen zu erteilen.",
|
||||
"cameraUnknownError": "Die Kamera kann aus einem unbekannten Grund nicht verwendet werden.",
|
||||
"cameraUnsupportedResolutionError": "Die Kamera unterstützt die erforderliche Auflösung nicht.",
|
||||
"Cancel": "Abbrechen",
|
||||
@@ -207,7 +221,7 @@
|
||||
"micNotFoundError": "Mikrofon nicht gefunden.",
|
||||
"micNotSendingData": "Gehen Sie zu den Einstellungen Ihres Computers, um die Stummschaltung Ihres Mikrofons aufzuheben und seinen Pegel einzustellen",
|
||||
"micNotSendingDataTitle": "Ihr Mikrofon ist durch Ihre Systemeinstellungen stumm geschaltet",
|
||||
"micPermissionDeniedError": "Die Berechtigung zur Verwendung des Mikrofons wurde nicht erteilt. Sie können trotzdem an der Konferenz teilnehmen, aber die anderen Teilnehmer können Sie nicht hören. Verwenden Sie die Kamera-Schaltfläche in der Adressleiste um die Berechtigungen zu erteilen.",
|
||||
"micPermissionDeniedError": "Die Berechtigung zur Verwendung des Mikrofons wurde nicht erteilt. Sie können trotzdem an der Konferenz teilnehmen, aber die anderen Teilnehmer können Sie nicht hören. Verwenden Sie die Kamera-Schaltfläche in der Adressleiste, um die Berechtigungen zu erteilen.",
|
||||
"micUnknownError": "Das Mikrofon kann aus einem unbekannten Grund nicht verwendet werden.",
|
||||
"muteEveryoneElseDialog": "Einmal stummgeschaltet, können Sie deren Stummschaltung nicht mehr beenden, aber sie können ihre Stummschaltung jederzeit selbst beenden.",
|
||||
"muteEveryoneElseTitle": "Alle außer {{whom}} stummschaten?",
|
||||
@@ -220,7 +234,7 @@
|
||||
"muteParticipantDialog": "Wollen Sie diesen Teilnehmer wirklich stummschalten? Sie können die Stummschaltung nicht wieder aufheben, der Teilnehmer kann dies aber jederzeit selbst tun.",
|
||||
"muteParticipantTitle": "Teilnehmer stummschalten?",
|
||||
"Ok": "OK",
|
||||
"passwordLabel": "Das Treffen wurde von einem Teilnehmer geslerrt. Bitte geben Sie die $t(lockRoomPassword) zu verbinden.",
|
||||
"passwordLabel": "Dieses Meeting wurde von einem Teilnehmer gesichert. Bitte geben Sie das $t(lockRoomPassword) ein, um dem Meeting beizutreten.",
|
||||
"passwordNotSupported": "Das Festlegen von einem $t(lockRoomPassword) für das Meeting wird nicht unterstützt.",
|
||||
"passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) nicht unterstützt",
|
||||
"passwordRequired": "$t(lockRoomPasswordUppercase) erforderlich",
|
||||
@@ -319,18 +333,18 @@
|
||||
"dialInSummaryError": "Fehler beim Abrufen der Einwahlinformationen. Versuchen Sie es später erneut.",
|
||||
"dialInTollFree": "Gebührenfrei",
|
||||
"genericError": "Es ist leider etwas schiefgegangen.",
|
||||
"inviteLiveStream": "Klicken Sie auf {{url}} um den Livestream dieser Konferenz zu öffnen",
|
||||
"invitePhone": "Wenn Sie stattdessen per Telefon beitreten möchten, tippen Sie hier: {{number}},,{{conferenceID}}#\n",
|
||||
"invitePhoneAlternatives": "Suche nach einer anderen Einwahlnummer?\nMeetings-Einwahlnummern sehen: {{url}}\n\n\nWenn Sie sich auch über ein Raumtelefon einwählen, nehmen Sie teil, ohne sich mit dem Ton zu verbinden: {{silentUrl}}",
|
||||
"inviteLiveStream": "Klicken Sie auf {{url}}, um den Livestream dieser Konferenz zu öffnen",
|
||||
"invitePhone": "Wenn Sie stattdessen per Telefon beitreten möchten, wählen sie: {{number}},,{{conferenceID}}#\n",
|
||||
"invitePhoneAlternatives": "Suchen Sie nach einer anderen Einwahlnummer ?\nMeeting-Einwahlnummern anzeigen: {{url}}\n\n\nWenn Sie sich auch über ein Raumtelefon einwählen, nehmen Sie teil, ohne sich mit dem Ton zu verbinden: {{silentUrl}}",
|
||||
"inviteURLFirstPartGeneral": "Sie wurden zur Teilnahme an einem Meeting eingeladen.",
|
||||
"inviteURLFirstPartPersonal": "{{name}} lädt Sie zu einem Meeting ein.\n",
|
||||
"inviteURLSecondPart": "\nAm Meeting teilnehmen:\n{{url}}\n",
|
||||
"liveStreamURL": "Livestream:",
|
||||
"moreNumbers": "Weitere Telefonnummern",
|
||||
"noNumbers": "Keine Telefonnummern verfügbar.",
|
||||
"noPassword": "Kein",
|
||||
"noPassword": "Kein Passwort benötigt",
|
||||
"noRoom": "Keine Konferenz für die Einwahlinformationen angegeben.",
|
||||
"numbers": "Einwählnummern",
|
||||
"numbers": "Einwahlnummern",
|
||||
"password": "$t(lockRoomPasswordUppercase):",
|
||||
"title": "Teilen",
|
||||
"tooltip": "Freigabe-Link und Einwahlinformationen für dieses Meeting",
|
||||
@@ -359,7 +373,7 @@
|
||||
"mute": "Stummschaltung aktivieren oder deaktivieren",
|
||||
"pushToTalk": "Push-to-Talk (Sprechtaste)",
|
||||
"raiseHand": "Hand erheben",
|
||||
"showSpeakerStats": "Statistiken für Sprecher anzeigen",
|
||||
"showSpeakerStats": "Sprecherstatistik anzeigen",
|
||||
"toggleChat": "Chat öffnen oder schließen",
|
||||
"toggleFilmstrip": "Video-Miniaturansichten ein- oder ausblenden",
|
||||
"toggleScreensharing": "Zwischen Kamera und Bildschirmfreigabe wechseln",
|
||||
@@ -448,14 +462,14 @@
|
||||
"muted": "Der Konferenz wurde stumm beigetreten.",
|
||||
"mutedTitle": "Stummschaltung aktiv!",
|
||||
"mutedRemotelyTitle": "Sie wurden von {{participantDisplayName}} stummgeschaltet!",
|
||||
"mutedRemotelyDescription": "Sie können jederzeit die Stummschaltung aufheben, wenn Sie bereit sind zu sprechen. Wenn Sie fertig sind, können sich wieder stummschalten, um Geräusche vom Meeting fernzuhalten.",
|
||||
"mutedRemotelyDescription": "Sie können jederzeit die Stummschaltung aufheben, wenn Sie bereit sind zu sprechen. Wenn Sie fertig sind, können Sie sich wieder stummschalten, um Geräusche vom Meeting fernzuhalten.",
|
||||
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) von einem anderen Teilnehmer entfernt",
|
||||
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) von einem anderen Teilnehmer gesetzt",
|
||||
"raisedHand": "{{name}} möchte sprechen.",
|
||||
"somebody": "Jemand",
|
||||
"startSilentTitle": "Sie sind ohne Audioausgabe beigetreten!",
|
||||
"startSilentDescription": "Treten Sie dem Meeting noch einmal bei, um Ihr Audio zu aktivieren",
|
||||
"suboptimalBrowserWarning": "Tut uns leid, aber die Konferenz wird mit {{appName}} kein großartiges Erlebnis. Wir versuchen immer die Situation zu verbessern, bis dahin empfehlen wir aber die Verwendung einer der <a href=\"static/recommendedBrowsers.html\" target=\"_blank\">vollständig unterstützen Browser</a>.",
|
||||
"suboptimalBrowserWarning": "Tut uns leid, aber die Konferenz wird mit {{appName}} kein großartiges Erlebnis. Wir versuchen immer die Situation zu verbessern, bis dahin empfehlen wir aber die Verwendung einer der <a href=\"{{recommendedBrowserPageLink}}\" target=\"_blank\">vollständig unterstützen Browser</a>.",
|
||||
"suboptimalExperienceTitle": "Browserwarnung",
|
||||
"unmute": "Stummschaltung aufheben",
|
||||
"newDeviceCameraTitle": "Neue Kamera erkannt",
|
||||
@@ -516,6 +530,11 @@
|
||||
"sectionList": {
|
||||
"pullToRefresh": "Ziehen, um zu aktualisieren"
|
||||
},
|
||||
"security": {
|
||||
"about": "Sie können einen Passwort zu Ihrer Sitzung hinzufügen. Die Teilnehmer müssen dieses ebenfalls eingeben, bevor sie an der Sitzung teilnehmen dürfen",
|
||||
"insecureRoomNameWarning": "Der Raumname ist unsicher. Unerwünschte Teilnehmer könnten Ihrer Konferenz beitreten",
|
||||
"securityOptions": "Sicherheitsoptionen"
|
||||
},
|
||||
"settings": {
|
||||
"calendar": {
|
||||
"about": "Die Kalenderintegration von {{appName}} wird verwendet, um ein sicheres Zugreifen auf Ihren Kalender und Auslesen der bevorstehenden Termine zu ermöglichen.",
|
||||
@@ -570,8 +589,8 @@
|
||||
"minutes": "{{count}}m",
|
||||
"name": "Name",
|
||||
"seconds": "{{count}}s",
|
||||
"speakerStats": "Sprecher-Statistiken",
|
||||
"speakerTime": "Sprecher-Zeit"
|
||||
"speakerStats": "Sprecherstatistik",
|
||||
"speakerTime": "Sprecherzeit"
|
||||
},
|
||||
"startupoverlay": {
|
||||
"policyText": " ",
|
||||
@@ -610,6 +629,7 @@
|
||||
"raiseHand": "„Melden“ ein-/ausschalten",
|
||||
"recording": "Aufzeichnung ein-/ausschalten",
|
||||
"remoteMute": "Teilnehmer stummschalten",
|
||||
"security": "Sicherheitsoptionen",
|
||||
"Settings": "Einstellungen ein-/ausschalten",
|
||||
"sharedvideo": "YouTube-Videofreigabe ein-/ausschalten",
|
||||
"shareRoom": "Person einladen",
|
||||
@@ -661,11 +681,12 @@
|
||||
"profile": "Profil bearbeiten",
|
||||
"raiseHand": "Hand erheben",
|
||||
"raiseYourHand": "Melden",
|
||||
"security": "Sicherheitsoptionen",
|
||||
"Settings": "Einstellungen",
|
||||
"sharedvideo": "YouTube-Video teilen",
|
||||
"shareRoom": "Person einladen",
|
||||
"shortcuts": "Tastenkürzel anzeigen",
|
||||
"speakerStats": "Sprecher-Statistiken",
|
||||
"speakerStats": "Sprecherstatistik",
|
||||
"startScreenSharing": "Bildschirmfreigabe starten",
|
||||
"startSubtitles": "Untertitel einschalten",
|
||||
"stopScreenSharing": "Bildschirmfreigabe stoppen",
|
||||
@@ -726,9 +747,6 @@
|
||||
"lowDefinition": "Niedrige Auflösung",
|
||||
"onlyAudioAvailable": "Nur Ton",
|
||||
"onlyAudioSupported": "In diesem Browser wird nur Audio unterstützt.",
|
||||
"p2pEnabled": "Ende-zu-Ende aktiviert",
|
||||
"p2pVideoQualityDescription": "Im Ende-zu-Ende-Modus kann die empfangene Videoqualität nur zwischen „Hoch“ und „Nur Audio“ umgeschaltet werden. Andere Einstellungen werden erst beim Verlassen des Ende-zu-Ende-Modus berücksichtigt.",
|
||||
"recHighDefinitionOnly": "Hohe Qualität wird bevorzugt.",
|
||||
"sd": "SD",
|
||||
"sdTooltip": "Video wird in Standardauflösung angezeigt",
|
||||
"standardDefinition": "Standardauflösung"
|
||||
|
||||
831
lang/main-el.json
Normal file
831
lang/main-el.json
Normal file
@@ -0,0 +1,831 @@
|
||||
{
|
||||
"addPeople": {
|
||||
"add": "Προσκάλεσε",
|
||||
"countryNotSupported": "Δεν υποστηρίζουμε αυτόν τον προορισμό ακόμα.",
|
||||
"countryReminder": "Κλήση εκτός ΗΠΑ; Παρακαλώ βεβαιωθείτε ότι ξεκινάτε με τον κωδικό της χώρας!",
|
||||
"disabled": "Δεν μπορείτε να προσκαλέσετε άτομα.",
|
||||
"failedToAdd": "Αποτυχία προσθήκης συμμετεχόντων",
|
||||
"footerText": "Η κλήση είναι απενεργοποιημένη.",
|
||||
"loading": "Αναζήτηση για ανθρώπους και αριθμούς τηλεφώνου",
|
||||
"loadingNumber": "Ο αριθμός τηλεφώνου επικυρώνεται",
|
||||
"loadingPeople": "Γίνεται αναζήτηση για ανθρώπους που θα καλεστούν",
|
||||
"noResults": "Δε βρέθηκαν αποτελέσματα αναζήτησης",
|
||||
"noValidNumbers": "Παρακαλώ εισάγετε έναν αριθμό τηλεφώνου",
|
||||
"searchNumbers": "Προσθέστε αριθμούς τηλεφώνου",
|
||||
"searchPeople": "Αναζήτηση για ανθρώπους",
|
||||
"searchPeopleAndNumbers": "Αναζήτηση για ανθρώπους ή προσθήκη των αριθμών τηλεφώνου τους",
|
||||
"telephone": "Τηλέφωνο: {{number}}",
|
||||
"title": "Καλέστε ανθρώπους σε αυτή τη συνάντηση"
|
||||
},
|
||||
"audioDevices": {
|
||||
"bluetooth": "Bluetooth",
|
||||
"headphones": "Ακουστικά",
|
||||
"phone": "Τηλέφωνο",
|
||||
"speaker": "Ομιλητής",
|
||||
"none": "Δεν υπάρχουν διαθέσιμες συσκευές ήχου"
|
||||
},
|
||||
"audioOnly": {
|
||||
"audioOnly": "Χαμηλό εύρος ζώνης"
|
||||
},
|
||||
"calendarSync": {
|
||||
"addMeetingURL": "Προσθέστε έναν σύνδεσμο συνάντησης",
|
||||
"confirmAddLink": "Θέλετε να προσθέσετε έναν σύνδεσμο Jitsi σε αυτό το γεγονός;",
|
||||
"error": {
|
||||
"appConfiguration": "Η ενσωμάτωση ημερολόγιου δεν έχει ρυθμιστεί σωστά.",
|
||||
"generic": "Παρουσιάστηκε ένα σφάλμα. Παρακαλείστε να ελέγξετε τις ρυθμίσεις ημερολογίου σας ή να δοκιμάσετε να ανανεώσετε το ημερολόγιο.",
|
||||
"notSignedIn": "Παρουσιάστηκε ένα σφάλμα κατά τον έλεγχο ταυτότητας προβολής ημερολογίου εκδηλώσεων. Παρακαλείστε να ελέγξετε τις ρυθμίσεις ημερολογίου και να δοκιμάσετε να συνδεθείτε ξανά."
|
||||
},
|
||||
"join": "Συμμετοχή",
|
||||
"joinTooltip": "Συμμετοχή στη σύσκεψη",
|
||||
"nextMeeting": "επόμενη συνάντηση",
|
||||
"noEvents": "Δεν υπάρχουν προγραμματισμένες προσεχείς εκδηλώσεις.",
|
||||
"ongoingMeeting": "συνάντηση σε εξέλιξη",
|
||||
"permissionButton": "Άνοιγμα ρυθμίσεων",
|
||||
"permissionMessage": "Η άδεια ημερολόγιου άδεια απαιτείται για να δείτε τις συναντήσεις σας στην εφαρμογή.",
|
||||
"refresh": "Ανανεώστε το ημερολόγιο",
|
||||
"today": "Σήμερα"
|
||||
},
|
||||
"chat": {
|
||||
"error": "Σφάλμα: το μήνυμα δεν εστάλη. Λόγος: {{reason}}",
|
||||
"fieldPlaceHolder": "Πληκτρολογήστε το μήνυμά σας εδώ",
|
||||
"messagebox": "Πληκτρολογήστε ένα μήνυμα",
|
||||
"messageTo": "Ιδιωτικό μήνυμα στον / στην {{recipient}}",
|
||||
"noMessagesMessage": "Δεν υπάρχουν μηνύματα στη συνάντηση ακόμα. Ξεκινήστε μια συζήτηση εδώ!",
|
||||
"nickname": {
|
||||
"popover": "Επιλέξτε ένα ψευδώνυμο",
|
||||
"title": "Εισάγετε ένα ψευδώνυμο για τη χρήση της συνομιλίας"
|
||||
},
|
||||
"privateNotice": "Ιδιωτικό μηνύμα στον / στην {recipient}}",
|
||||
"title": "Συνομιλία",
|
||||
"you": "Εσείς"
|
||||
},
|
||||
"chromeExtensionBanner": {
|
||||
"installExtensionText": "Εγκαταστήσετε την επέκταση για την ενοποίηση του Google Calendar και του Office 365 ",
|
||||
"buttonText": "Εγκαταστήστε την επέκταση του Chrome",
|
||||
"dontShowAgain": "Μην μου το δείξεις αυτό ξανά"
|
||||
},
|
||||
"connectingOverlay": {
|
||||
"joiningRoom": "Σας συνδέουμε για τη συνάντησή σας"
|
||||
},
|
||||
"connection": {
|
||||
"ATTACHED": "Συνημμένο",
|
||||
"AUTHENTICATING": "Έλεγχος ταυτότητας",
|
||||
"AUTHFAIL": "Ο έλεγχος ταυτότητας απέτυχε",
|
||||
"CONNECTED": "Συνδεδεμένος",
|
||||
"CONNECTING": "Γίνεται σύνδεση",
|
||||
"CONNFAIL": "Η σύνδεση απέτυχε",
|
||||
"DISCONNECTED": "Αποσυνδεδεμένος",
|
||||
"DISCONNECTING": "Γίνεται αποσύνδεση",
|
||||
"ERROR": "Σφάλμα",
|
||||
"FETCH_SESSION_ID": "Απόκτηση session-id...",
|
||||
"GET_SESSION_ID_ERROR": "Λήψη session-id σφάλματος: {{code}}",
|
||||
"GOT_SESSION_ID": "Απόκτηση session-id... Κάνει",
|
||||
"LOW_BANDWIDTH": "Το βίντεο για το {{displayName}} έχει απενεργοποιηθεί για να εξοικονομήσετε εύρος ζώνης"
|
||||
},
|
||||
"connectionindicator": {
|
||||
"address": "Διεύθυνση:",
|
||||
"bandwidth": "Εκτιμώμενο εύρος ζώνης:",
|
||||
"bitrate": "Ρυθμός μετάδοσης:",
|
||||
"bridgeCount": "Αριθμός server: ",
|
||||
"connectedTo": "Συνδεδεμένος με:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Ρυθμός ανανέωσης:",
|
||||
"less": "Δείξε λιγότερα",
|
||||
"localaddress": "Τοπική διεύθυνση:",
|
||||
"localaddress_plural": "Τοπικές διευθύνσεις:",
|
||||
"localport": "Τοπική θύρα:",
|
||||
"localport_plural": "Τοπικές θύρες:",
|
||||
"more": "Εμφάνιση περισσότερων",
|
||||
"packetloss": "Απώλεια πακέτων:",
|
||||
"quality": {
|
||||
"good": "Καλά",
|
||||
"inactive": "Ανενεργά",
|
||||
"lost": "Χαμένα",
|
||||
"nonoptimal": "Μέτρια",
|
||||
"poor": "Κακή"
|
||||
},
|
||||
"remoteaddress": "Απομακρυσμένη διεύθυνση:",
|
||||
"remoteaddress_plural": "Απομακρυσμένες διευθύνσεις:",
|
||||
"remoteport": "Απομακρυσμένη θύρα:",
|
||||
"remoteport_plural": "Απομακρυσμένες θύρες:",
|
||||
"resolution": "Ανάλυση:",
|
||||
"status": "Σύνδεση:",
|
||||
"transport": "Μεταφορά:",
|
||||
"transport_plural": "Μεταφορές:"
|
||||
},
|
||||
"dateUtils": {
|
||||
"earlier": "Νωρίτερα",
|
||||
"today": "Σήμερα",
|
||||
"yesterday": "Χθες"
|
||||
},
|
||||
"deepLinking": {
|
||||
"appNotInstalled": "Θα πρέπει να έχετε την εφαρμογή {{app}} για το κινητό σας για να συμμετάσχετε σε αυτήν την διάσκεψη στο τηλέφωνό σας.",
|
||||
"description": "Δεν έγινε τίποτα; Προσπαθήσαμε να κάνουμε έναρξη σύσκεψης στο {{app}} desktop app. Προσπαθήστε ξανά ή ξεκινήστε το {{app}} web app.",
|
||||
"descriptionWithoutWeb": "Δεν έγινε τίποτα; Προσπαθήσαμε να κάνουμε έναρξη σύσκεψης στο {{app}} desktop app.",
|
||||
"downloadApp": "Κατεβάστε την εφαρμογή",
|
||||
"launchWebButton": "Έναρξη στο web",
|
||||
"openApp": "Συνεχίστε στην εφαρμογή",
|
||||
"title": "Γίνεται έναρξη της συνάντησής σας στο {{app}}...",
|
||||
"tryAgainButton": "Προσπαθήστε ξανά στην επιφάνεια εργασίας"
|
||||
},
|
||||
"defaultLink": "π.χ. {{url}}",
|
||||
"defaultNickname": "π.χ. Η Τζέιν Ρόουζ",
|
||||
"deviceError": {
|
||||
"cameraError": "Απέτυχε η πρόσβαση στη φωτογραφική μηχανή σας",
|
||||
"cameraPermission": "Παρουσιάστηκε σφάλμα κατά τη λήψη άδειας χρήσης της κάμερας",
|
||||
"microphoneError": "Αποτυχία πρόσβασης στο μικρόφωνο",
|
||||
"microphonePermission": "Παρουσιάστηκε σφάλμα κατά τη λήψη άδειας χρήσης του μικρόφωνου"
|
||||
},
|
||||
"deviceSelection": {
|
||||
"noPermission": "Δεν χορηγήθηκε άδεια χρήσης",
|
||||
"previewUnavailable": "Προεπισκόπηση μη διαθέσιμη",
|
||||
"selectADevice": "Επιλέξτε μια συσκευή",
|
||||
"testAudio": "Παίξτε έναν δοκιμαστικό ήχο"
|
||||
},
|
||||
"dialog": {
|
||||
"accessibilityLabel": {
|
||||
"liveStreaming": "Ζωντανή ροή"
|
||||
},
|
||||
"allow": "Επίτρεψε",
|
||||
"alreadySharedVideoMsg": "Ένας άλλος συμμετέχων κάνει ήδη κοινή προβολή βίντεο. Η διάσκεψη αυτή επιτρέπει μόνο ένα κοινόχρηστο βίντεο τη φορά.",
|
||||
"alreadySharedVideoTitle": "Μόνο ένα κοινόχρηστο βίντεο επιτρέπεται τη φορά",
|
||||
"applicationWindow": "Παράθυρο εφαρμογής",
|
||||
"Back": "Πίσω",
|
||||
"cameraConstraintFailedError": "Η κάμερα σας δεν πληρεί ορισμένους από τους απαιτούμενους περιορισμούς.",
|
||||
"cameraNotFoundError": "Η κάμερα δε βρέθηκε.",
|
||||
"cameraNotSendingData": "Δεν είμαστε σε θέση να έχουμε πρόσβαση στην κάμερα σας. Παρακαλώ ελέγξτε αν κάποια άλλη εφαρμογή τη χρησιμοποιεί, επιλέξτε μια άλλη συσκευή από το μενού ρυθμίσεων ή δοκιμάστε να φορτώσετε ξανά την εφαρμογή.",
|
||||
"cameraNotSendingDataTitle": "Αδυναμία πρόσβασης στην κάμερα",
|
||||
"cameraPermissionDeniedError": "Δεν έχετε δώσει άδεια χρήσης της κάμεράς σας. Μπορείτε ακόμα να συμμετάσχετε στη διάσκεψη, αλλά οι άλλοι δεν θα σας βλέπουν. Χρησιμοποιήστε το κουμπί με την κάμερα στη γραμμή διευθύνσεων για διορθώσετε αυτό το θέμα.",
|
||||
"cameraUnknownError": "Δεν μπορείτε να χρησιμοποιήσετε την κάμερα για άγνωστο λόγο.",
|
||||
"cameraUnsupportedResolutionError": "Η κάμερα σας δεν υποστηρίζει την απαιτούμενη ανάλυση του βίντεο.",
|
||||
"Cancel": "Ακύρωση",
|
||||
"close": "Κλείσιμο",
|
||||
"conferenceDisconnectMsg": "Παρακαλώ ελέγξτε τη σύνδεση δικτύου σας. Επανασύνδεση σε {{seconds}} δευτερόλεπτα...",
|
||||
"conferenceDisconnectTitle": "Έχετε αποσυνδεθεί.",
|
||||
"conferenceReloadMsg": "Προσπαθούμε να το διορθώσουμε αυτό. Επανασύνδεση σε {{seconds}} δευτερόλεπτα...",
|
||||
"conferenceReloadTitle": "Δυστυχώς, κάτι πήγε στραβά.",
|
||||
"confirm": "Επιβεβαίωση",
|
||||
"confirmNo": "Όχι",
|
||||
"confirmYes": "Ναι",
|
||||
"connectError": "Ουπς! Κάτι πήγε στραβά και δεν μπορούσαμε να συνδεθούμε με τη διάσκεψη.",
|
||||
"connectErrorWithMsg": "Ουπς! Κάτι πήγε στραβά και δεν μπορούσαμε να συνδεθούμε με τη διάσκεψη: {{msg}}",
|
||||
"connecting": "Γίνεται σύνδεση",
|
||||
"contactSupport": "Επικοινωνήστε με την υποστήριξη",
|
||||
"copy": "Αντιγραφή",
|
||||
"dismiss": "Απόρριψη",
|
||||
"displayNameRequired": "Γεια σου! Ποιο είναι το όνομα σου;",
|
||||
"done": "Κάνει",
|
||||
"e2eeDescription": "<p>Η από άκρη σε άκρη κρυπτογράφηση είναι σήμερα <strong>σε ΠΕΙΡΑΜΑΤΙΚΟ στάδιο</strong>. Παρακαλώ δείτε <a href='https://jitsi.org/blog/e2ee/' target='_blank'>αυτήν την ανάρτηση</a> για λεπτομέρειες.</p><br/><p>Παρακαλώ να έχετε κατά νου ότι η ενεργοποίηση της από άκρη σε άκρη κρυπτογράφησης θα απενεργοποιήσει από την πλευρά του διακομιστή υπηρεσίες όπως: καταγραφή, live streaming και συμμετοχή μέσω τηλεφώνου. Επίσης, να έχετε κατά νου ότι η συνάντηση θα λειτουργήσει μόνο για τους ανθρώπους που συνδέονται από φυλλομετρητές με υποστήριξη για insertable streams.</p>",
|
||||
"e2eeLabel": "Κλειδί",
|
||||
"e2eeTitle": "Από άκρη σε άκρη κρυπτογράφηση",
|
||||
"e2eeWarning": "<br /><p><strong>ΠΡΟΕΙΔΟΠΟΊΗΣΗ:</strong> Δε φαίνεται να έχουν όλοι οι συμμετέχοντες στη συνάντηση αυτή υποστήριξη για από άκρη σε άκρη κρυπτογράφηση. Αν την ενεργοποιήσετε, δεν θα μπορέσουν να σας δουν ούτε να σας ακούσουν.</p>",
|
||||
"enterDisplayName": "Παρακαλώ εισάγετε το όνομά σας εδώ",
|
||||
"error": "Σφάλμα",
|
||||
"externalInstallationMsg": "Θα πρέπει να εγκαταστήσετε την επέκτασή μας για διαμοιρασμό επιφάνειας εργασίας.",
|
||||
"externalInstallationTitle": "Απαιτείται επέκταση",
|
||||
"goToStore": "Μετάβαση στο webstore",
|
||||
"gracefulShutdown": "Μας υπηρεσία είναι προς το παρόν εκτός λειτουργίας για συντήρηση. Παρακαλώ προσπαθήστε ξανά αργότερα.",
|
||||
"IamHost": "Είμαι ο οικοδεσπότης",
|
||||
"incorrectRoomLockPassword": "Εσφαλμένος κωδικός πρόσβασης",
|
||||
"incorrectPassword": "Λανθασμένο όνομα χρήστη ή κωδικός πρόσβασης",
|
||||
"inlineInstallationMsg": "Θα πρέπει να εγκαταστήσετε την επέκτασή μας για διαμοιρασμό επιφάνειας εργασίας.",
|
||||
"inlineInstallExtension": "Εγκαταστήστε τώρα",
|
||||
"internalError": "Ουπς! Κάτι πήγε στραβά. Παρουσιάστηκε το παρακάτω σφάλμα: {{error}}",
|
||||
"internalErrorTitle": "Εσωτερικό σφάλμα",
|
||||
"kickMessage": "Μπορείτε να επικοινωνήσετε με το {{participantDisplayName}} για περισσότερες λεπτομέρειες.",
|
||||
"kickParticipantButton": "Αποβολή",
|
||||
"kickParticipantDialog": "Είστε σίγουρος ότι θέλετε να αποβάλετε αυτόν τον συμμετέχοντα;",
|
||||
"kickParticipantTitle": "Θέλετε να αποβάλετε αυτόν τον συμμετέχοντα;",
|
||||
"kickTitle": "Ωχ! Ο/Η {{participantDisplayName}} σας απέβαλε από τη διάσκεψη",
|
||||
"liveStreaming": "Ζωντανή ροή",
|
||||
"liveStreamingDisabledForGuestTooltip": "Οι επισκέπτες δεν μπορούν να ξεκινήσουν τη ζωντανή ροή",
|
||||
"liveStreamingDisabledTooltip": "Έναρξη ζωντανής ροής απενεργοποιημένη",
|
||||
"lockMessage": "Αποτυχία κλειδώματος της διάσκεψης.",
|
||||
"lockRoom": "Προσθέστε συνάντηση $t(lockRoomPasswordUppercase)",
|
||||
"lockTitle": "Το κλείδωμα απέτυχε",
|
||||
"logoutQuestion": "Είστε σίγουρος ότι θέλετε να αποσυνδεθείτε και να σταματήσει η διάσκεψη;",
|
||||
"logoutTitle": "Αποσύνδεση",
|
||||
"maxUsersLimitReached": "Το όριο για τον μέγιστο αριθμό συμμετεχόντων έχει επιτευχθεί. Η διάσκεψη είναι πλήρης. Παρακαλείστε να επικοινωνήσετε με τον ιδιοκτήτη ή να δοκιμάστε ξανά αργότερα!",
|
||||
"maxUsersLimitReachedTitle": "Ο αριθμός συμμετεχόντων έφτασε στο μέγιστο",
|
||||
"micConstraintFailedError": "Το μικρόφωνο σας δεν πληρεί ορισμένους από τους απαιτούμενους περιορισμούς.",
|
||||
"micNotFoundError": "Το μικρόφωνο δεν βρέθηκε.",
|
||||
"micNotSendingData": "Πηγαίνετε στο ρυθμίσεις του υπολογιστή για να καταργήσετε τη σίγαση μικροφώνου σας και να ρυθμίσετε το επίπεδό του",
|
||||
"micNotSendingDataTitle": "Το μικρόφωνο είναι σε σίγαση από τις ρυθμίσεις του συστήματός σας",
|
||||
"micPermissionDeniedError": "Δεν έχετε την άδεια να χρησιμοποιήσετε το μικρόφωνο. Μπορείτε ακόμα να συμμετάσχετε στη διάσκεψη, αλλά οι άλλοι δεν θα μπορούν να σας ακούσουν. Χρησιμοποιήστε το κουμπί της κάμερας στη γραμμή διευθύνσεων για να το διορθώσετε αυτό.",
|
||||
"micUnknownError": "Δεν μπορείτε να χρησιμοποιήσετε το μικρόφωνο για άγνωστο λόγο.",
|
||||
"muteEveryoneElseDialog": "Όταν είναι σε σίγαση, δεν θα είστε σε θέση να καταργήσετε τη σίγαση τους, αλλά θα μπορούν να το κάνουν μόνοι τους ανά πάσα στιγμή.",
|
||||
"muteEveryoneElseTitle": "Σίγαση όλων εκτός από {{whom}};",
|
||||
"muteEveryoneDialog": "Είστε σίγουρος ότι θέλετε να θέσετε σε σίγαση τον καθένα; Δεν θα είστε σε θέση να καταργήσετε τη σίγαση, αλλά μπορούν να το κάνουν ανά πάσα στιγμή.",
|
||||
"muteEveryoneTitle": "Σίγαση όλων;",
|
||||
"muteEveryoneSelf": "τον εαυτό σας",
|
||||
"muteEveryoneStartMuted": "Όλοι αρχίζουν με ενεργοποιημένη τη σίγαση από τώρα και στο εξής",
|
||||
"muteParticipantBody": "Δεν θα είστε σε θέση να καταργήσετε τη σίγαση, αλλά μπορούν να το κάνουν ανά πάσα στιγμή.",
|
||||
"muteParticipantButton": "Σίγαση",
|
||||
"muteParticipantDialog": "Είστε σίγουρος ότι θέλετε να απενεργοποιήσετε αυτό το συμμετέχοντα; Δεν θα είστε σε θέση να καταργήσετε τη σίγαση, αλλά μπορούν να κάνουν ανά πάσα στιγμή.",
|
||||
"muteParticipantTitle": "Σίγαση αυτού του συμμετέχοντα;",
|
||||
"Ok": "Ok",
|
||||
"passwordLabel": "Η συνάντηση έχει κλειδωθεί από έναν συμμετέχοντα. Παρακαλώ εισάγετε το $t(lockRoomPassword) για να κάνετε είσοδο.",
|
||||
"passwordNotSupported": "Δεν υποστηρίζεται η ρύθμιση του $t(lockRoomPassword) της συνάντησης.",
|
||||
"passwordNotSupportedTitle": "Δεν υποστηρίζεται $t(lockRoomPasswordUppercase)",
|
||||
"passwordRequired": "Απαιτείται $t(lockRoomPasswordUppercase)",
|
||||
"popupError": "Ο φυλλομετρητής σας μπλοκάρει τα pop-up windows από αυτό το site. Παρακαλούμε ενεργοποιήστε τα pop-ups στις ρυθμίσεις ασφαλείας του προγράμματος περιήγησής σας και προσπαθήστε ξανά.",
|
||||
"popupErrorTitle": "Pop-up μπλοκαρίστηκε",
|
||||
"recording": "Γίνεται εγγραφή",
|
||||
"recordingDisabledForGuestTooltip": "Οι επισκέπτες δεν μπορούν να ξεκινήσουν τις ηχογραφήσεις.",
|
||||
"recordingDisabledTooltip": "Έναρξη εγγραφής απενεργοποιημένη.",
|
||||
"rejoinNow": "Επανασύνδεση τώρα",
|
||||
"remoteControlAllowedMessage": "O/H {{user}} έκανε αποδεκτό το αίτημα απομακρυσμένου ελέγχου!",
|
||||
"remoteControlDeniedMessage": "O/H {{user}} απέρριψε το αίτημα απομακρυσμένου ελέγχου!",
|
||||
"remoteControlErrorMessage": "Παρουσιάστηκε σφάλμα κατά την προσπάθεια να αιτήματος δικαιωμάτων απομακρυσμένου ελέγχου από {{user}}!",
|
||||
"remoteControlRequestMessage": "Θέλετα να επιτρέψετε στον/ην {{user}} να έχει απομακρυσμένο έλεγχο του υπολογιστή σας;",
|
||||
"remoteControlShareScreenWarning": "Σημειώστε ότι εάν πατήσετε το πλήκτρο \"Αποδοχή\" θα μοιραστείτε την οθόνη σας!",
|
||||
"remoteControlStopMessage": "Η περίοδος λειτουργίας απομακρυσμένου ελέγχου έληξε!",
|
||||
"remoteControlTitle": "Απομακρυσμένος έλεγχος επιφάνειας εργασίας",
|
||||
"Remove": "Αφαίρεση",
|
||||
"removePassword": "Αφαίρεση $t(lockRoomPassword)",
|
||||
"removeSharedVideoMsg": "Είστε σίγουρος ότι θέλετε να καταργήσετε το κοινόχρηστο βίντεο σας;",
|
||||
"removeSharedVideoTitle": "Αφαιρέστε κοινόχρηστο βίντεο",
|
||||
"reservationError": "Σφάλμα συστήματος κρατήσεων",
|
||||
"reservationErrorMsg": "Κωδικός σφάλματος: {{code}}, μήνυμα: {{msg}}",
|
||||
"retry": "Επανάληψη",
|
||||
"screenSharingAudio": "Διαμοιρασμός ήχου",
|
||||
"screenSharingFailedToInstall": "Ουπς! Η εγκατάσταση της επέκταση κοινής χρήσης οθόνης απέτυχε.",
|
||||
"screenSharingFailedToInstallTitle": "Η εγκατάσταση της επέκταση κοινής χρήσης οθόνης απέτυχε",
|
||||
"screenSharingFirefoxPermissionDeniedError": "Κάτι πήγε στραβά ενώ προσπαθούσατε να μοιραστείτε την οθόνη σας. Παρακαλούμε βεβαιωθείτε ότι μας έχετε δώσει την άδεια να το πράξουμε.",
|
||||
"screenSharingFirefoxPermissionDeniedTitle": "Ουπς! Δεν ήμασταν σε θέση να ξεκινήσουμε την κοινή χρήση οθόνης!",
|
||||
"screenSharingPermissionDeniedError": "Ουπς! Κάτι πήγε στραβά με τα δικαιώματα της επέκτασης κοινής χρήσης οθόνης. Παρακαλώ ξαναφορτώστε και προσπαθήστε ξανά.",
|
||||
"sendPrivateMessage": "Πρόσφατα λάβατε ένα προσωπικό μήνυμα. Σκοπεύετε να απαντήσετε σε αυτό ιδιωτικά ή θέλετε να στείλετε το μήνυμά σας στην ομάδα;",
|
||||
"sendPrivateMessageCancel": "Στείλτε στην ομάδα",
|
||||
"sendPrivateMessageOk": "Στείλτε ιδιωτικά",
|
||||
"sendPrivateMessageTitle": "Θέλετε να στείλετε ιδιωτικά;",
|
||||
"serviceUnavailable": "Η υπηρεσία δεν είναι διαθέσιμη",
|
||||
"sessTerminated": "Η κλήση τερματίστηκε",
|
||||
"Share": "Μοιραστείτε",
|
||||
"shareVideoLinkError": "Παρακαλώ δώστε έναν σωστό σύνδεσμο youtube.",
|
||||
"shareVideoTitle": "Μοιραστείτε ένα βίντεο",
|
||||
"shareYourScreen": "Μοιραστείτε την οθόνη σας",
|
||||
"shareYourScreenDisabled": "Η κοινή χρήση οθόνης απενεργοποιήθηκε.",
|
||||
"shareYourScreenDisabledForGuest": "Οι επισκέπτες δεν μπορούν να μοιραστούν την οθόνη τους.",
|
||||
"startLiveStreaming": "Έναρξη ζωντανής ροής",
|
||||
"startRecording": "Ξεκινήστε την εγγραφή",
|
||||
"startRemoteControlErrorMessage": "Παρουσιάστηκε σφάλμα κατά την προσπάθεια να ξεκινήσει η λειτουργία απομακρυσμένου ελέγχου!",
|
||||
"stopLiveStreaming": "Τερματισμός ζωντανής ροής",
|
||||
"stopRecording": "Τερματισμός εγγραφής",
|
||||
"stopRecordingWarning": "Είστε σίγουρος ότι θέλετε να διακόψετε την εγγραφή;",
|
||||
"stopStreamingWarning": "Είστε σίγουρος ότι θέλετε να διακόψετε τη ζωντανή ροή;",
|
||||
"streamKey": "Κλειδί ζωντανής ροής",
|
||||
"Submit": "Υποβολή",
|
||||
"thankYou": "Σας ευχαριστούμε για τη χρήση του {{appName}}!",
|
||||
"token": "token",
|
||||
"tokenAuthFailed": "Συγνώμη, δεν επιτρέπεται να συμμετάσχετε σε αυτήν την κλήση.",
|
||||
"tokenAuthFailedTitle": "Ο έλεγχος ταυτότητας απέτυχε",
|
||||
"transcribing": "Γίνεται μεταγραφή",
|
||||
"unlockRoom": "Αφαιρέστε το $t(lockRoomPassword) της συνάντησης",
|
||||
"userPassword": "κωδικός πρόσβασης χρήστη",
|
||||
"WaitForHostMsg": "Η διάσκεψη <b>{{room}}</b> δεν έχει ακόμη αρχίσει. Αν είστε ο οικοδεσπότης, τότε παρακαλούμε να πιστοποιήσετε τον εαυτό σας. Διαφορετικά, σας παρακαλώ να περιμένετε να συνδεθεί ο οικοδεσπότης.",
|
||||
"WaitForHostMsgWOk": "Η διάσκεψη <b>{{room}}</b> δεν έχει ακόμη αρχίσει. Αν είστε ο οικοδεσπότης, τότε παρακαλούμε πατήστε ΟΚ για να πιστοποιήσετε τον εαυτό σας. Διαφορετικά, σας παρακαλώ να περιμένετε να συνδεθεί ο οικοδεσπότης.",
|
||||
"WaitingForHost": "Αναμονή για τον οικοδεσπότη ...",
|
||||
"Yes": "Ναι",
|
||||
"yourEntireScreen": "Ολόκληρη την οθόνη σας"
|
||||
},
|
||||
"dialOut": {
|
||||
"statusMessage": "είναι τώρα {{status}}"
|
||||
},
|
||||
"documentSharing": {
|
||||
"title": "Κοινόχρηστο Έγγραφο"
|
||||
},
|
||||
"e2ee": {
|
||||
"labelToolTip": "Όλοι οι συμμετέχοντες στη συνάντηση αυτή έχουν ενεργοποιήσει την από άκρη σε άκρη κρυπτογράφηση"
|
||||
},
|
||||
"feedback": {
|
||||
"average": "Μέτριο",
|
||||
"bad": "Κακό",
|
||||
"detailsLabel": "Πείτε μου περισσότερα γι ' αυτό.",
|
||||
"good": "Καλό",
|
||||
"rateExperience": "Αξιολογήστε την εμπειρία της συνάντησης σας",
|
||||
"veryBad": "Πολύ κακό",
|
||||
"veryGood": "Πολύ καλό"
|
||||
},
|
||||
"incomingCall": {
|
||||
"answer": "Απάντηση",
|
||||
"audioCallTitle": "Εισερχόμενη κλήση",
|
||||
"decline": "Απόρριψη",
|
||||
"productLabel": "από το Jitsi Meet",
|
||||
"videoCallTitle": "Εισερχόμενη κλήση βίντεο"
|
||||
},
|
||||
"info": {
|
||||
"accessibilityLabel": "Εμφάνιση πληροφοριών",
|
||||
"addPassword": "Προσθέστε $t(lockRoomPassword)",
|
||||
"cancelPassword": "Ακύρωση $t(lockRoomPassword)",
|
||||
"conferenceURL": "Σύνδεσμος:",
|
||||
"country": "Χώρα",
|
||||
"dialANumber": "Για να συνδεθείτε στη συνάντησή σας, καλέστε έναν από αυτούς τους αριθμούς και στη συνέχεια πληκτρολογήστε το pin.",
|
||||
"dialInConferenceID": "PIN:",
|
||||
"dialInNotSupported": "Συγγνώμη, η εισερχόμενη κλήση προς το παρόν δεν υποστηρίζεται.",
|
||||
"dialInNumber": "Εισερχόμενη κλήση:",
|
||||
"dialInSummaryError": "Σφάλμα ανάκτησης πληροφοριών εισερχόμενης κλήσης. Παρακαλώ προσπαθήστε ξανά αργότερα.",
|
||||
"dialInTollFree": "Δωρεάν",
|
||||
"genericError": "Ουπς, κάτι πήγε στραβά.",
|
||||
"inviteLiveStream": "Για να δείτε τη ζωντανή ροή αυτής της συνάντησης, κάντε κλικ σε αυτό το σύνδεσμο: {{url}}",
|
||||
"invitePhone": "Για να συμμετάσχετε με τηλέφωνο, πληκτρολογήστε: {{number}},,{{conferenceID}}#\n",
|
||||
"invitePhoneAlternatives": "Ψάχνετε για ένα διαφορετικό εισερχόμενο αριθμό;\nΔείτε τους εισερχόμενους αριθμούς αυτής της συνάντησης : {{url}}\n\n\nΑν επίσης καλείτε μέσω τηλεφώνου δωματίου, συμμετάσχετε χωρίς σύνδεση ήχου: {{silentUrl}}",
|
||||
"inviteURLFirstPartGeneral": "Σας προσκαλούμε να συμμετάσχετε σε μια σύσκεψη.",
|
||||
"inviteURLFirstPartPersonal": "{{name}} σας προσκαλεί σε μια συνάντηση.\n",
|
||||
"inviteURLSecondPart": "\nΣυμμετάσχετε στη σύσκεψη:\n{{url}}\n",
|
||||
"liveStreamURL": "Ζωντανή ροή:",
|
||||
"moreNumbers": "Περισσότερα νούμερα",
|
||||
"noNumbers": "Δεν υπάρχουν εισερχόμενοι αριθμοί.",
|
||||
"noPassword": "Κανένα",
|
||||
"noRoom": "Δεν ορίστηκε δωμάτιο για εισερχόμενη κλήση.",
|
||||
"numbers": "Εισερχόμενοι αριθμοί",
|
||||
"password": "$t(lockRoomPasswordUppercase):",
|
||||
"title": "Μοιραστείτε",
|
||||
"tooltip": "Μοιραστείτε το σύνδεσμο και πληροφορίες εισερχόμενης κλήσης για τη συνάντηση αυτή",
|
||||
"label": "Πληροφορίες συνάντησης"
|
||||
},
|
||||
"inviteDialog": {
|
||||
"alertText": "Η εφαρμογή απέτυχε να καλέσει μερικούς συμμετέχοντες.",
|
||||
"header": "Προσκάλεσε",
|
||||
"searchCallOnlyPlaceholder": "Εισάγετε τον αριθμό τηλεφώνου",
|
||||
"searchPeopleOnlyPlaceholder": "Αναζήτηση συμμετεχόντων",
|
||||
"searchPlaceholder": "Συμμετέχοντας ή αριθμός τηλεφώνου",
|
||||
"send": "Στείλτε"
|
||||
},
|
||||
"inlineDialogFailure": {
|
||||
"msg": "Πέσαμε λίγο.",
|
||||
"retry": "Προσπαθήστε ξανά",
|
||||
"support": "Υποστήριξη",
|
||||
"supportMsg": "Εάν αυτό συνεχίζει να συμβαίνει, επικοινωνήστε με"
|
||||
},
|
||||
"keyboardShortcuts": {
|
||||
"focusLocal": "Εστίαση στο βίντεο σας",
|
||||
"focusRemote": "Εστίαση στο βίντεο ενός άλλου προσώπου",
|
||||
"fullScreen": "Είσοδος ή έξοδος από πλήρη οθόνη",
|
||||
"keyboardShortcuts": "Συντομεύσεις πληκτρολογίου",
|
||||
"localRecording": "Εμφάνιση ή απόκρυψη χειριστηρίων καταγραφής",
|
||||
"mute": "Σίγαση ή κατάργηση της σίγασης του μικροφώνου σας",
|
||||
"pushToTalk": "Πιέστε για να μιλήσετε",
|
||||
"raiseHand": "Σηκώστε ή χαμηλώστε το χέρι σας",
|
||||
"showSpeakerStats": "Εμφάνιση στατιστικών ομιλητή",
|
||||
"toggleChat": "Ανοίξτε ή κλείστε τη συνομιλία",
|
||||
"toggleFilmstrip": "Εμφάνιση ή απόκρυψη μικρογραφιών βίντεο",
|
||||
"toggleScreensharing": "Εναλλαγή μεταξύ κάμερας και κοινής χρήσης οθόνης",
|
||||
"toggleShortcuts": "Εμφάνιση ή απόκρυψη των συντομεύσεων πληκτρολογίου",
|
||||
"videoMute": "Άνοιγμα ή κλείσιμο κάμερας",
|
||||
"videoQuality": "Διαχειριστείτε την ποιότητα της κλήσης"
|
||||
},
|
||||
"liveStreaming": {
|
||||
"busy": "Δουλεύουμε για την απελευθέρωση πόρων streaming. Παρακαλώ δοκιμάστε ξανά σε λίγα λεπτά.",
|
||||
"busyTitle": "Όλες οι streamers είναι απασχολημένοι",
|
||||
"changeSignIn": "Εναλλαγή λογαριασμών.",
|
||||
"choose": "Επιλέξτε μία ζωντανή ροή",
|
||||
"chooseCTA": "Επιλέξτε μία streaming επιλογή. Αυτή την στιγμή είστε συνδεδεμένοι ως {{email}}.",
|
||||
"enterStreamKey": "Εισάγετε το κλειδί της ζωντανής ροής του YouTube εδώ.",
|
||||
"error": "Η ζωντανή ροή απέτυχε. Παρακαλώ δοκιμάστε ξανά.",
|
||||
"errorAPI": "Παρουσιάστηκε ένα σφάλμα κατά την πρόσβαση στίς μεταδόσεις YouTube. Παρακαλώ δοκιμάστε να συνδεθείτε ξανά.",
|
||||
"errorLiveStreamNotEnabled": "Η ζωντανή ροή δεν είναι ενεργοποιημένη στο {{email}}. Παρακαλούμε να ενεργοποιήσετε τη ζωντανή ροή ή να συνδεθείτε σε ένα λογαριασμό με ενεργοποιημένη τη ζωντανή ροή.",
|
||||
"expandedOff": "Η ζωντανή ροή έχει σταματήσει",
|
||||
"expandedOn": "Η συνάντηση αυτή τη στιγμή μεταδίδεται στο YouTube.",
|
||||
"expandedPending": "Η ζωντανή ροή πρόκειται να ξεκινήσει...",
|
||||
"failedToStart": "Η ζωντανή ροή απέτυχε να ξεκινήσει",
|
||||
"getStreamKeyManually": "Δεν ήμασταν σε θέση να φέρουμε κάποια ζωντανή ροή. Προσπαθήστε να πάρετε το κλειδί της ζωντανής ροής από το YouTube.",
|
||||
"invalidStreamKey": "Το κλειδί της ζωντανής ροής μπορεί να είναι εσφαλμένο.",
|
||||
"off": "Η ζωντανή ροή σταμάτησε",
|
||||
"offBy": "Ο/Η {{name}} σταμάτησε τη ζωντανή ροή",
|
||||
"on": "Ζωντανή ροή",
|
||||
"onBy": "Ο/Η {{name}} ξεκίνησε τη ζωντανή ροή",
|
||||
"pending": "Η ζωντανή ροή ξεκινά...",
|
||||
"serviceName": "Υπηρεσία ζωντανής ροής",
|
||||
"signedInAs": "Είστε συνδεδεμένοι ως:",
|
||||
"signIn": "Συνδεθείτε με το Google",
|
||||
"signInCTA": "Συνδεθείτε ή εισάγετε το το κλειδί της ζωντανής ροής από το YouTube.",
|
||||
"signOut": "Έξοδος",
|
||||
"start": "Ξεκινήστε μια ζωντανή ροή",
|
||||
"streamIdHelp": "Τι είναι αυτό;",
|
||||
"unavailableTitle": "Ζωντανή ροή μη διαθέσιμη",
|
||||
"youtubeTerms": "Όροι υπηρεσιών YouTube",
|
||||
"googlePrivacyPolicy": "Πολιτική Απορρήτου της Google"
|
||||
},
|
||||
"localRecording": {
|
||||
"clientState": {
|
||||
"off": "Κλειστό",
|
||||
"on": "Ανοικτό",
|
||||
"unknown": "Άγνωστο"
|
||||
},
|
||||
"dialogTitle": "Κοντρόλ τοπικής καταγραφής",
|
||||
"duration": "Διάρκεια",
|
||||
"durationNA": "Δ/Υ",
|
||||
"encoding": "Κωδικοποίηση",
|
||||
"label": "LOR",
|
||||
"labelToolTip": "Η τοπική καταγραφή είναι απασχολημένη",
|
||||
"localRecording": "Τοπική Καταγραφή",
|
||||
"me": "Εγώ",
|
||||
"messages": {
|
||||
"engaged": "Η Τοπική καταγραφή είναι απασχολημένη.",
|
||||
"finished": "Η καταγραφή {{token}} τελείωσε. Παρακαλούμε να στείλετε το αρχείο καταγραφής στο συντονιστή.",
|
||||
"finishedModerator": "Η καταγραφή {{token}} τελείωσε. Η καταγραφή της τοπικής ροής έχει αποθηκευθεί. Παρακαλώ ζητήστε από τους άλλους συμμετέχοντες να υποβάλουν τις καταγραφές τους.",
|
||||
"notModerator": "Δεν είστε ο συντονιστής. Δεν μπορείτε να ξεκινήσετε ή να σταματήσετε την τοπική καταγραφή."
|
||||
},
|
||||
"moderator": "Συντονιστής",
|
||||
"no": "Όχι",
|
||||
"participant": "Συμμετέχων",
|
||||
"participantStats": "Στατιστικά συμμετεχόντων",
|
||||
"sessionToken": "Token Συνεδρίας",
|
||||
"start": "Ξεκινήστε την καταγραφή",
|
||||
"stop": "Σταματήστε την καταγραφή",
|
||||
"yes": "Ναι"
|
||||
},
|
||||
"lockRoomPassword": "κωδικός πρόσβασης",
|
||||
"lockRoomPasswordUppercase": "Κωδικός πρόσβασης",
|
||||
"me": "Εγώ",
|
||||
"notify": {
|
||||
"connectedOneMember": "{{name}} μπήκε στην συνάντηση",
|
||||
"connectedThreePlusMembers": "Ο/Η {{name}} και {{count}} άλλοι μπήκαν στην συνάντηση",
|
||||
"connectedTwoMembers": "Ο {{first}} και ο {{second}} μπήκαν στην συνάντηση",
|
||||
"disconnected": "αποσυνδεμένος",
|
||||
"focus": "Εστίαση στη διάσκεψη",
|
||||
"focusFail": "Το {{component}} δεν είναι διαθέσιμο - επανάληψη σε {{ms}} sec",
|
||||
"grantedTo": "Χορηγήθηκαν δικαιώματα συντονιστή στον/ην {{to}}!",
|
||||
"invitedOneMember": "Ο/Η {{name}} έχει προσκληθεί",
|
||||
"invitedThreePlusMembers": "Ο/Η {{name}} και {{count}} άλλοι έχουν προσκληθεί",
|
||||
"invitedTwoMembers": "Ο {{first}} και ο {{second}} έχουν προσκληθεί",
|
||||
"kickParticipant": "Ο/Η {{kicked}} απλοβλήθηκε από τον/ην {{kicker}}",
|
||||
"me": "Εγώ",
|
||||
"moderator": "Χορηγήθηκαν δικαιώματα συντονιστή!",
|
||||
"muted": "Έχετε ξεκινήσει τη συζήτηση σε σίγαση.",
|
||||
"mutedTitle": "Είσαι σε σίγαση!",
|
||||
"mutedRemotelyTitle": "Έχετε μπει σε σίγαση από τον/ην {{participantDisplayName}}!",
|
||||
"mutedRemotelyDescription": "Μπορείτε πάντα να καταργήσετε τη σίγαση, όταν είστε έτοιμος να μιλήσετε. Ενεργοποιήστε ξανά τη σίγαση όταν τελειώσετε, για να κρατήσετε μακριά τον θόρυβο από τη διάσκεψη.",
|
||||
"passwordRemovedRemotely": "Το $t(lockRoomPasswordUppercase) αφαιρέθηκε από έναν άλλον συμμετέχοντα",
|
||||
"passwordSetRemotely": "Το $t(lockRoomPasswordUppercase) ορίστηκε από άλλον συμμετέχοντα",
|
||||
"raisedHand": "Ο/Η {{name}} θα ήθελε να μιλήσει.",
|
||||
"somebody": "Κάποιος",
|
||||
"startSilentTitle": "Μπήκες χωρίς συσκευή εξόδου ήχου!",
|
||||
"startSilentDescription": "Ξαναμπείτε στη συνάντηση για να ενεργοποιήσετε τον ήχο",
|
||||
"suboptimalBrowserWarning": "Φοβόμαστε ότι η εμπειρία σας στη συνάντηση δεν θα είναι καλή εδώ. Ψάχνουμε για τρόπους για να το βελτιώσουμε αυτό, αλλά μέχρι τότε παρακαλώ δοκιμάστε να χρησιμοποιήσετε ένα από τα <a href='static/recommendedBrowsers.html' target='_blank'>πλήρως υποστηριζόμενα προγράμματα περιήγησης</a>.",
|
||||
"suboptimalExperienceTitle": "Προειδοποίηση πρόγραμματος περιήγησης",
|
||||
"unmute": "Κατάργηση σίγασης",
|
||||
"newDeviceCameraTitle": "Εντοπίστηκε νέα κάμερα",
|
||||
"newDeviceAudioTitle": "Εντοπίστηκε νέα συσκευή ήχου",
|
||||
"newDeviceAction": "Χρήση",
|
||||
"OldElectronAPPTitle": "Θέμα ευπάθειας ασφαλείας!",
|
||||
"oldElectronClientDescription1": "Φαίνεται ότι χρησιμοποιείτε μια παλιά έκδοση του πελάτη Jitsi Meet που έχει γνωστά θέματα ευπάθειας ασφαλείας. Παρακαλώ βεβαιωθείτε ότι έχετε την ενημερωμένη έκδοση για ",
|
||||
"oldElectronClientDescription2": "πρόσφατη έκδοση μας",
|
||||
"oldElectronClientDescription3": " τώρα!"
|
||||
},
|
||||
"passwordSetRemotely": "ορίστηκε από άλλον συμμετέχοντα",
|
||||
"passwordDigitsOnly": "Έως {{number}} ψηφία",
|
||||
"poweredby": "με τη δύναμη του",
|
||||
"presenceStatus": {
|
||||
"busy": "Απασχολημένος",
|
||||
"calling": "Γίνεται κλήση...",
|
||||
"connected": "Συνδεδεμένος",
|
||||
"connecting": "Γίνεται σύνδεση...",
|
||||
"connecting2": "Γίνεται σύνδεση*...",
|
||||
"disconnected": "Αποσυνδεθηκε",
|
||||
"expired": "Έληξε",
|
||||
"ignored": "Αγνοούνται",
|
||||
"initializingCall": "Προετοιμασία Κλήσης...",
|
||||
"invited": "Προσκλήθηκε",
|
||||
"rejected": "Απορρίφθηκε",
|
||||
"ringing": "Χτυπάει..."
|
||||
},
|
||||
"profile": {
|
||||
"setDisplayNameLabel": "Ρυθμίστε το όνομα εμφάνισής σας",
|
||||
"setEmailInput": "Εισάγετε το e-mail",
|
||||
"setEmailLabel": "Ρυθμίστε το gravatar email",
|
||||
"title": "Προφίλ"
|
||||
},
|
||||
"raisedHand": "Θα ήθελα να μιλήσω",
|
||||
"recording": {
|
||||
"authDropboxText": "Ανεβάστε στο Dropbox",
|
||||
"availableSpace": "Διαθέσιμος χώρος: {{spaceLeft}} MB (περίπου {{duration}} λεπτά εγγραφής)",
|
||||
"beta": "BETA",
|
||||
"busy": "Δουλεύουμε για την απελευθέρωση καταγραφής πόρων. Παρακαλώ δοκιμάστε ξανά σε λίγα λεπτά.",
|
||||
"busyTitle": "Όλοι οι καταγραφείς είναι απασχολημένοι",
|
||||
"error": "Η καταγραφή απέτυχε. Παρακαλώ δοκιμάστε ξανά.",
|
||||
"expandedOff": "Η καταγραφή έχει διακοπεί",
|
||||
"expandedOn": "Η συνάντηση καταγράφεται.",
|
||||
"expandedPending": "Η καταγραφή τίθεται σε λειτουργία...",
|
||||
"failedToStart": "Η καταγραφή απέτυχε να ξεκινήσει",
|
||||
"fileSharingdescription": "Μοιραστείτε την καταγραφή με τους συμμετέχοντες της συνάντησης",
|
||||
"live": "ΖΩΝΤΑΝΑ",
|
||||
"loggedIn": "Συνδεδεμένοι ως {{userName}}",
|
||||
"off": "Η καταγραφή σταμάτησε",
|
||||
"offBy": "Ο/Η {{name}} σταματήσε την καταγραφή",
|
||||
"on": "Καταγραφή",
|
||||
"onBy": "Ο/Η {{name}} ξεκίνησε την καταγραφή",
|
||||
"pending": "Προετοιμασία για την καταγραφή της σύσκεψης...",
|
||||
"rec": "ΚΑΤΑΓΡΑΦΗ",
|
||||
"serviceDescription": "Η καταγραφή σας θα αποθηκευτεί από την υπηρεσία καταγραφής",
|
||||
"serviceName": "Υπηρεσία καταγραφής",
|
||||
"signIn": "Σύνδεση",
|
||||
"signOut": "Αποσύνδεση",
|
||||
"unavailable": "Ουπς! Το {{serviceName}} δεν είναι διαθέσιμο προς το παρόν. Δουλεύουμε για την επίλυση του ζητήματος. Παρακαλώ προσπαθήστε ξανά αργότερα.",
|
||||
"unavailableTitle": "Η καταγραφή δεν είναι διαθέσιμη"
|
||||
},
|
||||
"sectionList": {
|
||||
"pullToRefresh": "Τραβήξτε για να ανανεώσετε"
|
||||
},
|
||||
"settings": {
|
||||
"calendar": {
|
||||
"about": "H σύνδεση ημερολογίου του {{appName}} χρησιμοποιείται για την ασφαλή πρόσβαση του ημερολογίου σας, ώστε να μπορεί να διαβάσει τις επερχόμενες εκδηλώσεις.",
|
||||
"disconnect": "Αποσύνδεση",
|
||||
"microsoftSignIn": "Σύνδεση με τη Microsoft",
|
||||
"signedIn": "Πραγματοποιείται πρόσβαση σε ημερολόγιο εκδηλώσεων για το {{email}}. Κάντε κλικ στο κουμπί Αποσύνδεση παρακάτω, για να σταματήσει η πρόσβαση σε συμβάντα ημερολογίου.",
|
||||
"title": "Ημερολόγιο"
|
||||
},
|
||||
"devices": "Συσκευές",
|
||||
"followMe": "Όλοι με ακολουθούν",
|
||||
"language": "Γλώσσα",
|
||||
"loggedIn": "Συνδεδεμένος ως {{name}}",
|
||||
"microphones": "Μικρόφωνα",
|
||||
"moderator": "Συντονιστής",
|
||||
"more": "Περισσότερα",
|
||||
"name": "Όνομα",
|
||||
"noDevice": "Κανένα",
|
||||
"selectAudioOutput": "Έξοδος ήχου",
|
||||
"selectCamera": "Κάμερα",
|
||||
"selectMic": "Μικρόφωνο",
|
||||
"speakers": "Ηχεία",
|
||||
"startAudioMuted": "Όλοι ξεκινούν σε σίγαση",
|
||||
"startVideoMuted": "Όλοι ξεκινούν σε απόκρυψη",
|
||||
"title": "Ρυθμίσεις"
|
||||
},
|
||||
"settingsView": {
|
||||
"advanced": "Για προχωρημένους",
|
||||
"alertOk": "OK",
|
||||
"alertTitle": "Προειδοποίηση",
|
||||
"alertURLText": "Η διεύθυνση URL του διακομοστή που εισάγατε δεν είναι έγκυρη",
|
||||
"buildInfoSection": "Πληροφορίες έκδοσης",
|
||||
"conferenceSection": "Συνέδριο",
|
||||
"disableCallIntegration": "Απενεργοποίηση ολοκλήρωσης εγγενούς κλήσης",
|
||||
"disableP2P": "Απενεργοποίηση λειτουργίας Peer-to-Peer",
|
||||
"displayName": "Εμφανιζόμενο όνομα",
|
||||
"email": "E-mail",
|
||||
"header": "Ρυθμίσεις",
|
||||
"profileSection": "Προφίλ",
|
||||
"serverURL": "Διεύθυνση URL του διακομιστή",
|
||||
"showAdvanced": "Εμφάνιση ρυθμίσεων για προχωρημένους",
|
||||
"startWithAudioMuted": "Ξεκινήστε με σίγαση ήχου",
|
||||
"startWithVideoMuted": "Ξεκινήστε με το βίντεο σε σίγαση",
|
||||
"version": "Έκδοση",
|
||||
"alertCancel": "Ακύρωση",
|
||||
"disableCrashReporting": "Απενεργοποίηση αναφοράς σφαλμάτων",
|
||||
"disableCrashReportingWarning": "Είστε βέβαιοι ότι θέλετε να απενεργοποιήσετε την αναφορά σφαλμάτων; Η ρύθμιση θα εφαρμοστεί μετά την επανεκκίνηση της εφαρμογής."
|
||||
},
|
||||
"share": {
|
||||
"dialInfoText": "\n\n=====\n\nΘέλω απλά να καλέσετε με το τηλέφωνό σας;\n\n{{defaultDialInNumber}}κάντε Κλικ σε αυτό το σύνδεσμο για να δείτε τους τηλεφωνικούς αριθμούς κλήσης για αυτή τη συνάντηση\n{{dialInfoPageUrl}}",
|
||||
"mainText": "Κάντε κλικ στον παρακάτω σύνδεσμο για να συμμετάσχετε στη σύσκεψη:\n{{roomUrl}}"
|
||||
},
|
||||
"speaker": "Ομιλητής",
|
||||
"speakerStats": {
|
||||
"hours": "{{count}}ω",
|
||||
"minutes": "{{count}}λ",
|
||||
"name": "Όνομα",
|
||||
"seconds": "{{count}}δ",
|
||||
"speakerStats": "Στατιστικά ομιλητή",
|
||||
"speakerTime": "Ώρα ομιλητή"
|
||||
},
|
||||
"startupoverlay": {
|
||||
"policyText": " ",
|
||||
"title": "Το {{app}} πρέπει να χρησιμοποιήσει το μικρόφωνο και την κάμερά σας."
|
||||
},
|
||||
"suspendedoverlay": {
|
||||
"rejoinKeyTitle": "Επανασύνδεση",
|
||||
"text": "Πατήστε το <i>Επανασύνδεση</i> για να επανασυνδεθείτε.",
|
||||
"title": "Η Βίντεο κλήση διακόπηκε, επειδή ο υπολογιστής αυτός μπήκε σε κατάσταση αναστολής."
|
||||
},
|
||||
"toolbar": {
|
||||
"accessibilityLabel": {
|
||||
"audioOnly": "Εναλλαγή ήχου μόνο",
|
||||
"audioRoute": "Επιλέξτε τη συσκευή ήχου",
|
||||
"callQuality": "Διαχειριστείτε την ποιότητα του βίντεο",
|
||||
"cc": "Εναλλαγή υποτίτλων",
|
||||
"chat": "Εναλλαγή παραθύρου συνομιλίας",
|
||||
"document": "Εναλλαγή κοινοχρήστου εγγράφου",
|
||||
"download": "Κατεβάστε τις εφαρμογές μας",
|
||||
"e2ee": "End-to-End Κρυπτογράφηση",
|
||||
"feedback": "Αφήστε σχόλια",
|
||||
"fullScreen": "Εναλλαγή σε πλήρη οθόνη",
|
||||
"hangup": "Απόχώρηση από την κλήση",
|
||||
"help": "Βοήθεια",
|
||||
"invite": "Πρόσκληση συμμετεχόντων",
|
||||
"kick": "Αποβολή συμμετέχοντα",
|
||||
"localRecording": "Εναλλαγή ελέγχων τοπικής καταγραφής",
|
||||
"lockRoom": "Εναλλαγή κωδικού πρόσβασης συνάντησης",
|
||||
"moreActions": "Εναλλαγή μενού περισσότερων ενεργειών",
|
||||
"moreActionsMenu": "Μενού περισσότερων ενεργειών",
|
||||
"moreOptions": "Εμφάνιση περισσότερων επιλογών",
|
||||
"mute": "Εναλλαγή σίγασης ήχου",
|
||||
"muteEveryone": "Σίγαση όλων",
|
||||
"pip": "Εναλλαγή λειτουργίας Picture-in-Picture",
|
||||
"privateMessage": "Αποστολή ιδιωτικού μηνύματος",
|
||||
"profile": "Επεξεργαστείτε το προφίλ σας",
|
||||
"raiseHand": "Εναλλαγή σηκώματος χεριού",
|
||||
"recording": "Εναλλαγή καταγραφής",
|
||||
"remoteMute": "Σίγαση συμμετέχοντα",
|
||||
"Settings": "Εναλλαγή ρυθμίσεων",
|
||||
"sharedvideo": "Εναλλαγή κοινής χρήσης βίντεο στο Youtube",
|
||||
"shareRoom": "Προσκαλέστε κάποιον",
|
||||
"shareYourScreen": "Εναλλαγή κοινής χρήσης οθόνης",
|
||||
"shortcuts": "Εναλλαγή συντομεύσεων",
|
||||
"show": "Εμφάνιση στη σκηνή",
|
||||
"speakerStats": "Εναλλαγή στατιστικών ομιλητών",
|
||||
"tileView": "Εναλλαγή άποψης εικονιδίων",
|
||||
"toggleCamera": "Εναλλαγή κάμερας",
|
||||
"toggleFilmstrip": "Εναλλαγή filmstrip",
|
||||
"videomute": "Εναλλαγή σίγασης βίντεο",
|
||||
"videoblur": "Εναλλαγή θολούρας βίντεο"
|
||||
},
|
||||
"addPeople": "Προσθήκη ατόμων στην κλήση σας",
|
||||
"audioOnlyOff": "Απενεργοποίηση λειτουργίας χαμηλού εύρους ζώνης",
|
||||
"audioOnlyOn": "Ενεργοποίηση λειτουργίας χαμηλού εύρους ζώνης",
|
||||
"audioRoute": "Επιλέξτε τη συσκευή ήχου",
|
||||
"authenticate": "Έλεγχος ταυτότητας",
|
||||
"callQuality": "Διαχειριστείτε την ποιότητα του βίντεο",
|
||||
"chat": "Άνοιγμα / κλείσιμο chat",
|
||||
"closeChat": "Κλείσιμο chat",
|
||||
"documentClose": "Κλείσιμο κοινόχρηστου εγγράφου",
|
||||
"documentOpen": "Άνοιγμα κοινόχρηστο εγγράφου",
|
||||
"download": "Κατεβάστε τις εφαρμογές μας",
|
||||
"e2ee": "End-to-End Κρυπτογράφηση",
|
||||
"enterFullScreen": "Δείτε σε πλήρη οθόνη",
|
||||
"enterTileView": "Είσοδος σε προβολή εικονιδίων",
|
||||
"exitFullScreen": "Έξοδος από πλήρη οθόνη",
|
||||
"exitTileView": "Έξοδος από προβολή εικονιδίων",
|
||||
"feedback": "Αφήστε σχόλια",
|
||||
"hangup": "Αποσύνδεση",
|
||||
"help": "Βοήθεια",
|
||||
"invite": "Πρόσκληση συμμετεχόντων",
|
||||
"login": "Είσοδος",
|
||||
"logout": "Αποσύνδεση",
|
||||
"lowerYourHand": "Κατεβάστε το χέρι σας",
|
||||
"moreActions": "Περισσότερες ενέργειες",
|
||||
"moreOptions": "Περισσότερες επιλογές",
|
||||
"mute": "Σίγαση / Κατάργηση Σίγασης",
|
||||
"muteEveryone": "Σίγαση όλων",
|
||||
"noAudioSignalTitle": "Δεν υπάρχει ήχος από το μικρόφωνο σας!",
|
||||
"noAudioSignalDesc": "Αν δεν του κάνατε σίγαση ηθελημένα από τις ρυθμίσεις του συστήματος ή του υλικού, εξετάστε την αντικατάσταση της συσκευής.",
|
||||
"noAudioSignalDescSuggestion": "Αν δεν του κάνατε σίγαση ηθελημένα από τις ρυθμίσεις του συστήματος ή του υλικού, εξετάστε τη χρήση της προτεινόμενης συσκευής.",
|
||||
"noAudioSignalDialInDesc": "Μπορείτε επίσης να καλέσετε χρησιμοποιώντας:",
|
||||
"noAudioSignalDialInLinkDesc": "Αριθμοί κλήσης",
|
||||
"noisyAudioInputTitle": "Το μικρόφωνο φαίνεται να είναι θορυβώδες!",
|
||||
"noisyAudioInputDesc": "Το μικρόφωνό σας πιθανόν να κάνει θόρυβο, παρακαλούμε χρησιμοποιήστε τη σίγαση ή την αντικατάσταση της συσκευής.",
|
||||
"openChat": "Ανοικτή συνομιλία",
|
||||
"pip": "Είσοδος σε λειτουργία Picture-in-Picture",
|
||||
"privateMessage": "Αποστολή ιδιωτικού μηνύματος",
|
||||
"profile": "Επεξεργαστείτε το προφίλ σας",
|
||||
"raiseHand": "Σηκώστε / κατεβάστε το χέρι σας",
|
||||
"raiseYourHand": "Σηκώστε το χέρι σας",
|
||||
"Settings": "Ρυθμίσεις",
|
||||
"sharedvideo": "Μοιραστείτε βίντεο στο YouTube",
|
||||
"shareRoom": "Προσκαλέστε κάποιον",
|
||||
"shortcuts": "Δείτε τις συντομεύσεις",
|
||||
"speakerStats": "Στατιστικά ομιλητών",
|
||||
"startScreenSharing": "Ξεκινήστε την κοινή χρήση οθόνης",
|
||||
"startSubtitles": "Έναρξη υποτίτλων",
|
||||
"stopScreenSharing": "Διακόψτε την κοινή χρήση οθόνης",
|
||||
"stopSubtitles": "Σταμάτημα υποτίτλων",
|
||||
"stopSharedVideo": "Σταμάτημα του βίντεο YouTube",
|
||||
"talkWhileMutedPopup": "Προσπαθείτε να μιλήσετε; Είστε σε σίγαση.",
|
||||
"tileViewToggle": "Εναλλαγή προβολής εικονιδίων",
|
||||
"toggleCamera": "Εναλλαγή κάμερας",
|
||||
"videomute": "Άνοιγμα / κλείσιμο κάμερας",
|
||||
"startvideoblur": "Θόλωσε το φόντο μου",
|
||||
"stopvideoblur": "Απενεργοποίηση θόλωσης του φόντου"
|
||||
},
|
||||
"transcribing": {
|
||||
"ccButtonTooltip": "Άνοιγμα / κλείσιμο υποτίτλων",
|
||||
"error": "Η μεταγραφή απέτυχε. Παρακαλώ δοκιμάστε ξανά.",
|
||||
"expandedLabel": "Η Μεταγραφή είναι ενεργοποιημένη",
|
||||
"failedToStart": "Η Μεταγραφή απέτυχε να ξεκινήσει",
|
||||
"labelToolTip": "Η συνάντηση μεταγράφεται",
|
||||
"off": "Η Μεταγραφή σταμάτησε",
|
||||
"pending": "Προετοιμασία για μεταγραφή της συνάντησης...",
|
||||
"start": "Εμφάνιση υποτίτλων",
|
||||
"stop": "Απόκρυψη υποτίτλων",
|
||||
"tr": "TR"
|
||||
},
|
||||
"userMedia": {
|
||||
"androidGrantPermissions": "Επιλέξτε <b><i>Αποδοχή</i></b> όταν το πρόγραμμα περιήγησης ζητά δικαιώματα.",
|
||||
"chromeGrantPermissions": "Επιλέξτε <b><i>Αποδοχή</i></b> όταν το πρόγραμμα περιήγησης ζητά δικαιώματα.",
|
||||
"edgeGrantPermissions": "Επιλέξτε <b><i>Ναι</i></b> όταν το πρόγραμμα περιήγησης ζητά δικαιώματα.",
|
||||
"electronGrantPermissions": "Παρακαλούμε να παραχωρήσετε δικαιώματα για να χρησιμοποιήσετε την κάμερα και το μικρόφωνο",
|
||||
"firefoxGrantPermissions": "Επιλέξτε <b><i>Μοιραστείτε Επιλεγμένη Συσκευή</i></b> όταν το πρόγραμμα περιήγησης ζητά δικαιώματα.",
|
||||
"iexplorerGrantPermissions": "Επιλέξτε <b><i>OK</i></b> όταν το πρόγραμμα περιήγησης ζητά δικαιώματα.",
|
||||
"nwjsGrantPermissions": "Παρακαλούμε να παραχωρήσετε δικαιώματα για να χρησιμοποιήσετε την κάμερα και το μικρόφωνο",
|
||||
"operaGrantPermissions": "Επιλέξτε <b><i>Αποδοχή</i></b> όταν το πρόγραμμα περιήγησης ζητά δικαιώματα.",
|
||||
"react-nativeGrantPermissions": "Επιλέξτε <b><i>Αποδοχή</i></b> όταν το πρόγραμμα περιήγησης ζητά δικαιώματα.",
|
||||
"safariGrantPermissions": "Επιλέξτε <b><i>OK</i></b> όταν το πρόγραμμα περιήγησης ζητά δικαιώματα."
|
||||
},
|
||||
"videoSIPGW": {
|
||||
"busy": "Γίνεται προσπάθεια για την απελευθέρωση πόρων. Παρακαλώ δοκιμάστε ξανά σε λίγα λεπτά.",
|
||||
"busyTitle": "Η υπηρεσία Δωματίου είναι απασχολημένη",
|
||||
"errorAlreadyInvited": "{{displayName}} έχει ήδη προσκληθεί",
|
||||
"errorInvite": "Το Συνέδριο δεν έχει συσταθεί ακόμα. Παρακαλώ προσπαθήστε ξανά αργότερα.",
|
||||
"errorInviteFailed": "Γίνεται προσπάθεια για την επίλυση του ζητήματος. Παρακαλώ προσπαθήστε ξανά αργότερα.",
|
||||
"errorInviteFailedTitle": "Η πρόσκληση του/ης {{displayName}} απέτυχε",
|
||||
"errorInviteTitle": "Σφάλμα πρόσκλησης δωματίου",
|
||||
"pending": "Ο/Η {{displayName}} έχει προσκληθεί"
|
||||
},
|
||||
"videoStatus": {
|
||||
"audioOnly": "AUD",
|
||||
"audioOnlyExpanded": "Είστε σε λειτουργία χαμηλού εύρους ζώνης. Σε αυτή τη λειτουργία, θα λάβετε μόνο ήχο και κοινή χρήση οθόνης.",
|
||||
"callQuality": "Ποιότητα Βίντεο",
|
||||
"hd": "HD",
|
||||
"hdTooltip": "Προβολή βίντεο υψηλής ευκρίνειας",
|
||||
"highDefinition": "Υψηλής ευκρίνειας",
|
||||
"labelTooiltipNoVideo": "Χωρίς βίντεο",
|
||||
"labelTooltipAudioOnly": "Η Λειτουργία χαμηλού εύρους ζώνης είναι ενεργοποιημένη",
|
||||
"ld": "LD",
|
||||
"ldTooltip": "Προβολή χαμηλής ευκρίνειας βίντεο",
|
||||
"lowDefinition": "Χαμηλής ευκρίνειας",
|
||||
"onlyAudioAvailable": "Μόνο ο ήχος είναι διαθέσιμος",
|
||||
"onlyAudioSupported": "Υποστηρίζουμε μόνο ήχο σε αυτό το πρόγραμμα περιήγησης.",
|
||||
"p2pEnabled": "Λειτουργία Peer to Peer Ενεργοποιημένη",
|
||||
"p2pVideoQualityDescription": "Σε λειτουργία peer-to-peer, η ποιότητα του εισερχόμενου βίντεο μπορεί μόνο να εναλλάσσεται μεταξύ της υψηλής και μόνο ήχου. Οι υπόλοιπες ρυθμίσεις δεν θα ενεργοποιηθούν μέχρι να τερματιστεί η λειτουργία peer to peer.",
|
||||
"recHighDefinitionOnly": "Να προτιμηθεί υψηλή ευκρίνεια.",
|
||||
"sd": "SD",
|
||||
"sdTooltip": "Προβολή βίντεο τυπικής ανάλυσης",
|
||||
"standardDefinition": "Τυπική ανάλυση"
|
||||
},
|
||||
"videothumbnail": {
|
||||
"domute": "Σίγαση",
|
||||
"domuteOthers": "Σίγαση όλων των άλλων",
|
||||
"flip": "Περιστροφή",
|
||||
"kick": "Αποβολή",
|
||||
"moderator": "Συντονιστής",
|
||||
"mute": "Ο συμμετέχων είναι σε σίγαση",
|
||||
"muted": "Σίγαση",
|
||||
"remoteControl": "Ενεργοποίηση / απενεργοποίηση απομακρυσμένου ελέγχου",
|
||||
"show": "Εμφάνιση στη σκηνή",
|
||||
"videomute": "Ο συμμετέχων έχει σταματήσει την κάμερα"
|
||||
},
|
||||
"welcomepage": {
|
||||
"accessibilityLabel": {
|
||||
"join": "Πατήστε για να κάνετε είσοδο",
|
||||
"roomname": "Εισάγετε το όνομα δωματίου"
|
||||
},
|
||||
"appDescription": "Εμπρός, κάντε video chat με όλη την ομάδα. Στην πραγματικότητα, καλέστε όλους τους γνωστούς σας. Το {{app}} μια πλήρως κρυπτογραφημένη, 100% open source λύση τηλεδιάσκεψης που μπορείτε να χρησιμοποιήσετε για όλη την ημέρα, κάθε μέρα, εντελώς δωρεάν — χωρίς να απαιτείται δημιουργία λογαριασμού.",
|
||||
"audioVideoSwitch": {
|
||||
"audio": "Φωνή",
|
||||
"video": "Βίντεο"
|
||||
},
|
||||
"calendar": "Ημερολόγιο",
|
||||
"connectCalendarButton": "Συνδέστε το ημερολόγιο",
|
||||
"connectCalendarText": "Συνδέστε το ημερολόγιο για να δείτε όλες τις συναντήσεις σας στο {{app}}. Επιπλέον, προσθέστε συναντήσεις στο {{provider}} ημερολόγιό σας και ξεκινήστε με ένα κλικ.",
|
||||
"enterRoomTitle": "Ξεκινήστε μια νέα συνάντηση",
|
||||
"getHelp": "Βοήθεια",
|
||||
"roomNameAllowedChars": "Το όνομα συνάντησης δεν πρέπει να περιέχει οποιονδήποτε από αυτούς τους χαρακτήρες: ?, &, :, ', \", %, #.",
|
||||
"go": "ΠΑΜΕ",
|
||||
"goSmall": "ΠΑΜΕ",
|
||||
"join": "ΔΗΜΙΟΥΡΓΙΑ / ΕΙΣΟΔΟΣ",
|
||||
"info": "Πληροφορίες",
|
||||
"privacy": "Απόρρητο",
|
||||
"recentList": "Πρόσφατες",
|
||||
"recentListDelete": "Διαγραφή",
|
||||
"recentListEmpty": "Η λίστα με τα πρόσφατα σας είναι άδεια. Συνομιλήστε με την ομάδα σας και θα βρείτε όλες τις πρόσφατες συναντήσεις εδώ.",
|
||||
"reducedUIText": "Καλώς ήρθατε στο {{app}}!",
|
||||
"roomname": "Εισάγετε το όνομα δωματίου",
|
||||
"roomnameHint": "Εισάγετε το όνομα ή τη διεύθυνση URL του δωματίου στο οποίο θέλετε να συμμετάσχετε. Μπορείτε να βρείτε ένα όνομα, απλά ενημερώστε τους συμμετέχοντες, έτσι ώστε να εισάγουν το ίδιο όνομα.",
|
||||
"sendFeedback": "Στείλτε τα σχόλιά σας",
|
||||
"terms": "Όροι",
|
||||
"title": "Ασφαλής, πλήρως εξοπλισμένη, και εντελώς δωρεάν βίντεο συνομιλία"
|
||||
},
|
||||
"lonelyMeetingExperience": {
|
||||
"button": "Προσκαλέστε κι άλλους",
|
||||
"youAreAlone": "Είστε ο μόνος στη συνάντηση"
|
||||
},
|
||||
"helpView": {
|
||||
"header": "Κέντρο βοήθειας"
|
||||
},
|
||||
"prejoin": {
|
||||
"audioAndVideoError": "Σφάλμα ήχου και βίντεο:",
|
||||
"audioOnlyError": "Σφάλμα ήχου:",
|
||||
"audioTrackError": "Δεν ήταν δυνατό να δημιουργηθεί το κομμάτι ήχου.",
|
||||
"callMe": "Κάλεσέ με",
|
||||
"callMeAtNumber": "Κάλεσε με σε αυτό το νούμερο:",
|
||||
"configuringDevices": "Διαμόρφωση συσκευών",
|
||||
"connectedWithAudioQ": "Είστε συνδεδεμένοι με ήχο;",
|
||||
"copyAndShare": "Αντιγραφή & διαμοιρασμός συνδέσμου συνάντησης",
|
||||
"dialInMeeting": "Καλέστε στη συνάντηση",
|
||||
"dialInPin": "Καλέστε στη συνάντηση και εισάγετε κωδικό PIN:",
|
||||
"dialing": "Γίνεται κλήση",
|
||||
"doNotShow": "Να μην εμφανιστεί αυτό ξανά",
|
||||
"iWantToDialIn": "Θέλω να καλέσω",
|
||||
"joinAudioByPhone": "Σύνδεση με ήχο τηλεφώνου",
|
||||
"joinMeeting": "Σύνδεση στη συνάντηση",
|
||||
"joinWithoutAudio": "Σύνδεση χωρίς ήχο",
|
||||
"initiated": "Η κλήση ξεκίνησε",
|
||||
"linkCopied": "Ο σύνδεσμος αντιγράφηκε στο πρόχειρο",
|
||||
"lookGood": "Ακούγεται ότι το μικρόφωνό σας δουλεύει σωστά",
|
||||
"or": "ή",
|
||||
"calling": "Γίνεται κλήση...",
|
||||
"startWithPhone": "Έναρξη με ήχο τηλεφώνου",
|
||||
"screenSharingError": "Σφάλμα διαμοιρασμού οθόνης:",
|
||||
"videoOnlyError": "Σφάλμα βίντεο:",
|
||||
"videoTrackError": "Δεν μπορεί να δημιουργηθεί το βίντεο",
|
||||
"viewAllNumbers": "προβολή όλων των αριθμών"
|
||||
}
|
||||
}
|
||||
@@ -120,8 +120,10 @@
|
||||
"description": "Nothing happened? We tried launching your meeting in the {{app}} desktop app. Try again or launch it in the {{app}} web app.",
|
||||
"descriptionWithoutWeb": "",
|
||||
"downloadApp": "Download the app",
|
||||
"ifDoNotHaveApp": "If you don't have the app yet:",
|
||||
"ifHaveApp": "If you already have the app:",
|
||||
"joinInApp": "Join this meeting using the app",
|
||||
"launchWebButton": "Launch in web",
|
||||
"openApp": "Continue to the app",
|
||||
"title": "Launching your meeting in {{app}}…",
|
||||
"tryAgainButton": "Try again in desktop"
|
||||
},
|
||||
@@ -448,13 +450,13 @@
|
||||
"somebody": "Somebody",
|
||||
"startSilentTitle": "You joined with no audio output!",
|
||||
"startSilentDescription": "Rejoin the meeting to enable audio",
|
||||
"suboptimalExperienceDescription": "Eer... we are afraid your experience with {{appName}} isn't going to be that great here. We are looking for ways to improve this but, until then, please try using one of the <a href='static/recommendedBrowsers.html' target='_blank'>fully supported browsers</a>.",
|
||||
"suboptimalExperienceDescription": "Eer... we are afraid your experience with {{appName}} isn't going to be that great here. We are looking for ways to improve this but, until then, please try using one of the <a href='{{recommendedBrowserPageLink}}' target='_blank'>fully supported browsers</a>.",
|
||||
"suboptimalExperienceTitle": "Browser Warning",
|
||||
"unmute": "Unmute",
|
||||
"newDeviceCameraTitle": "New camera detected",
|
||||
"newDeviceAudioTitle": "New audio device detected",
|
||||
"newDeviceAction": "Use",
|
||||
"suboptimalBrowserWarning": "We are afraid your meeting experience isn't going to be that great here. We are looking for ways to improve this, but until then please try using one of the <a href='static/recommendedBrowsers.html' target='_blank'>fully supported browsers</a>."
|
||||
"suboptimalBrowserWarning": "We are afraid your meeting experience isn't going to be that great here. We are looking for ways to improve this, but until then please try using one of the <a href='{{recommendedBrowserPageLink}}' target='_blank'>fully supported browsers</a>."
|
||||
},
|
||||
"passwordSetRemotely": "set by another member",
|
||||
"passwordDigitsOnly": "Up to {{number}} digits",
|
||||
@@ -705,9 +707,6 @@
|
||||
"lowDefinition": "Low definition",
|
||||
"onlyAudioAvailable": "Only audio is available",
|
||||
"onlyAudioSupported": "We only support audio in this browser.",
|
||||
"p2pEnabled": "Peer to Peer Enabled",
|
||||
"p2pVideoQualityDescription": "In peer to peer mode, received call quality can only be toggled between high and audio only. Other settings will not be honoured until peer to peer is exited.",
|
||||
"recHighDefinitionOnly": "Will prefer high definition.",
|
||||
"sd": "SD",
|
||||
"standardDefinition": "Standard definition"
|
||||
},
|
||||
|
||||
@@ -663,9 +663,6 @@
|
||||
"lowDefinition": "Malaltkvalito distingivo",
|
||||
"onlyAudioAvailable": "",
|
||||
"onlyAudioSupported": "",
|
||||
"p2pEnabled": "Samtavola reĝimo ŝaltita",
|
||||
"p2pVideoQualityDescription": "",
|
||||
"recHighDefinitionOnly": "Preferos altkvalitan distingivon.",
|
||||
"sd": "ND",
|
||||
"standardDefinition": "Normalkvalita distingivo"
|
||||
},
|
||||
|
||||
@@ -1,21 +1,36 @@
|
||||
{
|
||||
"addPeople": {
|
||||
"add": "Invitar",
|
||||
"countryNotSupported": "Aún no contamos con soporte a este destino.",
|
||||
"addContacts": "Invitar a sus contactos",
|
||||
"copyInvite": "Copiar la invitación a la reunión",
|
||||
"copyLink": "Copiar el link de la reunión",
|
||||
"copyStream": "Copiar el link de la transmisión en vivo",
|
||||
"countryNotSupported": "Aun no contamos con soporte a este destino.",
|
||||
"countryReminder": "¿Llamando fuera de los Estados Unidos? ¡Por favor, asegúrese de empezar con el código de país!",
|
||||
"defaultEmail": "Dirección de correo por defecto",
|
||||
"disabled": "No puede invitar a otras personas.",
|
||||
"failedToAdd": "Error al agregar participantes",
|
||||
"footerText": "La marcación está desactivada.",
|
||||
"loading": "Búsqueda de personas y números de teléfono",
|
||||
"loadingNumber": "Validando el número de teléfono",
|
||||
"loadingPeople": "Buscando contactos a invitar",
|
||||
"googleEmail": "Correo electrónico de Google",
|
||||
"inviteMoreHeader": "Usted se encuentra solo en la reunión",
|
||||
"inviteMoreMailSubject": "Unirse a la reunion {{appName}}",
|
||||
"inviteMorePrompt": "Invitar a más personas",
|
||||
"linkCopied": "Link copiado al portapapeles",
|
||||
"loading": "Buscando por contacto y número telefónico",
|
||||
"loadingNumber": "Validando el número telefónico",
|
||||
"loadingPeople": "Buscando contactos a invitar",
|
||||
"noResults": "No se encontraron coincidencias",
|
||||
"noValidNumbers": "Por favor ingrese un número de teléfono",
|
||||
"searchNumbers": "Agregar números de teléfono",
|
||||
"searchPeople": "Búsqueda de personas",
|
||||
"outlookEmail": "Correo de Outlook",
|
||||
"searchNumbers": "Agregar números telefónicos",
|
||||
"searchPeople": "Búscar personas",
|
||||
"searchPeopleAndNumbers": "Buscar personas o añadir sus números de teléfono",
|
||||
"shareInvite": "Compartir la invitación a la reunión",
|
||||
"shareLink": "Compartir el link de la reunion",
|
||||
"shareStream": "Compartie el link de la transmición en vivo",
|
||||
"telephone": "Teléfono: {{number}}",
|
||||
"title": "Invitar a otras personas a esta reunión"
|
||||
"title": "Invitar a otras personas a esta reunión",
|
||||
"yahooEmail": "Correo de Yahoo"
|
||||
},
|
||||
"audioDevices": {
|
||||
"bluetooth": "Bluetooth",
|
||||
@@ -32,7 +47,7 @@
|
||||
"confirmAddLink": "¿Quiere añadir un enlace de Jitsi a este evento?",
|
||||
"error": {
|
||||
"appConfiguration": "La integración del calendario no está configurada correctamente",
|
||||
"generic": "Se ha producido un error. Compruebe la configuración del calendario o pruebe a recargarlo",
|
||||
"generic": "Se ha producido un error. Compruebe la configuración del calendario o pruebe cargarlo nuevamente.",
|
||||
"notSignedIn": "Se ha producido un error de autenticación para ver los eventos del calendario. Compruebe la configuración del calendario e intente iniciar sesión de nuevo"
|
||||
},
|
||||
"join": "Unirse",
|
||||
@@ -60,9 +75,9 @@
|
||||
"you": "usted"
|
||||
},
|
||||
"chromeExtensionBanner": {
|
||||
"installExtensionText": "",
|
||||
"buttonText": "",
|
||||
"dontShowAgain": ""
|
||||
"installExtensionText": "Instalar la extensión para Google Calendar y la integración con Office 365",
|
||||
"buttonText": "Instalar extensión de Chrome",
|
||||
"dontShowAgain": "No mostrar nuevamente"
|
||||
},
|
||||
"connectingOverlay": {
|
||||
"joiningRoom": "Conectándose a su reunión…"
|
||||
@@ -78,10 +93,10 @@
|
||||
"DISCONNECTING": "Desconectando",
|
||||
"ERROR": "Error",
|
||||
"RECONNECTING": "Ocurrió un problema en la red. Reconectando...",
|
||||
"LOW_BANDWIDTH": "",
|
||||
"GOT_SESSION_ID": "",
|
||||
"GET_SESSION_ID_ERROR": "",
|
||||
"FETCH_SESSION_ID": ""
|
||||
"FETCH_SESSION_ID": "Obteniendo session-ID…",
|
||||
"GET_SESSION_ID_ERROR": "Obtener session-id error: {{code}}",
|
||||
"GOT_SESSION_ID": "Obteniendo session-ID… Listo",
|
||||
"LOW_BANDWIDTH": "Video para {{displayName}} ha sido deshabilitado para economizar ancho de banda"
|
||||
},
|
||||
"connectionindicator": {
|
||||
"address": "Dirección:",
|
||||
@@ -89,13 +104,14 @@
|
||||
"bitrate": "Tasa de transferencia:",
|
||||
"bridgeCount": "Contador del servidor: ",
|
||||
"connectedTo": "Conectado a:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Fotogramas por segundo:",
|
||||
"less": "Mostrar menos",
|
||||
"localaddress": "Dirección local:",
|
||||
"localaddress_plural": "Direcciones locales:",
|
||||
"localport": "Puerto local:",
|
||||
"localport_plural": "Puertos locales:",
|
||||
"more": "Ver más",
|
||||
"more": "Mostrar más",
|
||||
"packetloss": "Pérdida de paquetes:",
|
||||
"quality": {
|
||||
"good": "Bueno",
|
||||
@@ -124,6 +140,10 @@
|
||||
"descriptionWithoutWeb": "¿No pasó nada? Intentamos iniciar su reunión en la aplicación de escritorio {{app}}.",
|
||||
"downloadApp": "Descargar la app",
|
||||
"launchWebButton": "Iniciar en web",
|
||||
"ifDoNotHaveApp": "Si aún no tienes la app:",
|
||||
"ifHaveApp": "Si ya tienes la app:",
|
||||
"joinInApp": "Unirse a la reunion usando la app",
|
||||
"launchWebButton": "Iniciar en la Web",
|
||||
"openApp": "Continuar a la aplicación",
|
||||
"title": "Iniciar su reunión en {{app}}…",
|
||||
"tryAgainButton": "Intentar de nuevo en el escritorio"
|
||||
@@ -175,6 +195,10 @@
|
||||
"dismiss": "Descartar",
|
||||
"displayNameRequired": "¡Hola! ¿Cuál es tu nombre?",
|
||||
"done": "Listo",
|
||||
"e2eeDescription": "<p>El cifrado Extremo-a-Extremo es actualmente <strong>EXPERIMENTAL</strong>. Por favor lea<a href='https://jitsi.org/blog/e2ee/' target='_blank'>este artículo</a> para más detalles.</p><br/><p>Tenga en cuenta que activar el cifrado extremo-a-extremo puede deshabilitar servicios en el servidor como: grabación, transmisión en vivo y participación telefónica. Sin embargo tenga en cuenta que esta reunion solo funcionará con personas que se unan usando un navegador.</p>",
|
||||
"e2eeLabel": "Clave",
|
||||
"e2eeTitle": "Cifrado Extremo-a-Extremo",
|
||||
"e2eeWarning": "<br /><p><strong>ATENCION:</strong> No todos los participantes de esta reunión soportan cifrado Extremo-a-Extremo. Si usted habilita el cifrado ellos no podrán verlo ni oirlo.</p>",
|
||||
"enterDisplayName": "Por favor ingresa tu nombre aquí",
|
||||
"error": "Error",
|
||||
"externalInstallationMsg": "Necesita instalar nuestra extensión para compartir escritorio.",
|
||||
@@ -208,8 +232,8 @@
|
||||
"micNotSendingData": "Vaya a la configuración de su computadora para activar el micrófono y ajustar su nivel",
|
||||
"micNotSendingDataTitle": "Su micrófono está silenciado en la configuración de su sistema",
|
||||
"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.",
|
||||
"micUnknownError": "No se puede usar su micrófono por motivos desconocidos.",
|
||||
"muteEveryoneElseDialog": "Una vez silenciados, No podrás quitarles el modo silencio, pero ellos podrán hacerlo en cualquier momento.",
|
||||
"micUnknownError": "No se puede usar el micrófono por motivos desconocidos.",
|
||||
"muteEveryoneElseDialog": "Una vez silenciados, no podrás quitarles el modo silencio, pero ellos podrán hacerlo en cualquier momento.",
|
||||
"muteEveryoneElseTitle": "¿Silenciar a todos los participantes excepto a {{whom}}?",
|
||||
"muteEveryoneDialog": "¿Estás seguro de silenciar a todos los participantes? No podrás quitarles el modo en silencio, pero ellos podrán hacerlo en cualquier momento.",
|
||||
"muteEveryoneTitle": "¿Silenciar a todos los participantes?",
|
||||
@@ -244,6 +268,7 @@
|
||||
"reservationError": "Error del sistema de reservación",
|
||||
"reservationErrorMsg": "Código de error: {{code}}, message: {{msg}}",
|
||||
"retry": "Reintentar",
|
||||
"screenSharingAudio": "Compartir audio",
|
||||
"screenSharingFailedToInstall": "Oops! Su extensión de uso compartido de pantalla no se pudo instalar.",
|
||||
"screenSharingFailedToInstallTitle": "La extensión para compartir la pantalla no se pudo instalar",
|
||||
"screenSharingFirefoxPermissionDeniedError": "Algo salió mal mientras tratábamos de compartir la pantalla. Por favor, asegúrese de que nos ha dado permiso para hacerlo. ",
|
||||
@@ -282,14 +307,17 @@
|
||||
"WaitingForHost": "Esperando al anfitrión …",
|
||||
"Yes": "Sí",
|
||||
"yourEntireScreen": "Su pantalla completa",
|
||||
"muteEveryoneDialog": ""
|
||||
"muteEveryoneDialog": "Silenciar a todos"
|
||||
},
|
||||
"dialOut": {
|
||||
"statusMessage": "esta {{status}}"
|
||||
"statusMessage": "está {{status}}"
|
||||
},
|
||||
"documentSharing": {
|
||||
"title": "Compartir documento"
|
||||
},
|
||||
"e2ee": {
|
||||
"labelToolTip": "La comunicación de Audio y Video en esta reunión está cifrada Extremo-a-Extremo"
|
||||
},
|
||||
"feedback": {
|
||||
"average": "Promedio",
|
||||
"bad": "Malo",
|
||||
@@ -453,16 +481,54 @@
|
||||
"somebody": "Alguien",
|
||||
"startSilentTitle": "¡Te uniste sin salida de audio!",
|
||||
"startSilentDescription": "Vuelva a unirse a la reunión para habilitar el audio",
|
||||
"suboptimalBrowserWarning": "Tememos que su experiencia en la reunión no sea tan buena. Estamos buscando formas de mejorar esto, pero hasta entonces intente utilizar uno de los <a href='static/recommendedBrowsers.html' target='_blank'>navegadores totalmente compatibles</a>.",
|
||||
"suboptimalBrowserWarning": "Tememos que su experiencia en la reunión no sea tan buena. Estamos buscando formas de mejorar esto, pero hasta entonces intente utilizar uno de los <a href='{{recommendedBrowserPageLink}}' target='_blank'>navegadores totalmente compatibles</a>.",
|
||||
"suboptimalExperienceTitle": "Advertencia del Explorador",
|
||||
"unmute": "Dejar de silenciar",
|
||||
"newDeviceCameraTitle": "Se ha detectado una nueva cámara",
|
||||
"newDeviceAudioTitle": "Se ha detectado un nuevo dispositivo de audio",
|
||||
"newDeviceAction": "Usar"
|
||||
"newDeviceAction": "Usar",
|
||||
"OldElectronAPPTitle": "Vulnerabilidades de Seguridad!",
|
||||
"oldElectronClientDescription1": "Aparentemente usted está usuado una versión antigua de Jitsi Meet que tiene problemas de seguridad. Por favor actualice la versión con nuestra ",
|
||||
"oldElectronClientDescription2": "ultima versión",
|
||||
"oldElectronClientDescription3": " ahora!"
|
||||
},
|
||||
"passwordSetRemotely": "definida por otro participante",
|
||||
"passwordDigitsOnly": "Hasta {{number]] cifras",
|
||||
"poweredby": "con tecnología de",
|
||||
"prejoin": {
|
||||
"audioAndVideoError": "Error en Audio y video:",
|
||||
"audioOnlyError": "Error en Audio:",
|
||||
"audioTrackError": "No se pured crear la pista de Audio.",
|
||||
"callMe": "Llámame",
|
||||
"callMeAtNumber": "Llamame a este número:",
|
||||
"configuringDevices": "Configurando dispositivos...",
|
||||
"connectedWithAudioQ": "Usted está conectado con Audio?",
|
||||
"copyAndShare": "Cipie y comparta el link de la reuinión",
|
||||
"dialInMeeting": "Marcar a la reunión",
|
||||
"dialInPin": "Marcar a la reunión e ingresarel código PIN:",
|
||||
"dialing": "Marcando",
|
||||
"doNotShow": "No mostrar nuevamente",
|
||||
"errorDialOut": "Could not dial out",
|
||||
"errorDialOutDisconnected": "Could not dial out. Disconnected",
|
||||
"errorDialOutFailed": "Could not dial out. Call failed",
|
||||
"errorDialOutStatus": "Error getting dial out status",
|
||||
"errorStatusCode": "Error dialing out, status code: {{status}}",
|
||||
"errorValidation": "Number validation failed",
|
||||
"iWantToDialIn": "I want to dial in",
|
||||
"joinAudioByPhone": "Join with phone audio",
|
||||
"joinMeeting": "Join meeting",
|
||||
"joinWithoutAudio": "Join without audio",
|
||||
"initiated": "Call initiated",
|
||||
"linkCopied": "Link copied to clipboard",
|
||||
"lookGood": "It sounds like your microphone is working properly",
|
||||
"or": "or",
|
||||
"calling": "Calling",
|
||||
"startWithPhone": "Start with phone audio",
|
||||
"screenSharingError": "Screen sharing error:",
|
||||
"videoOnlyError": "Video error:",
|
||||
"videoTrackError": "Could not create video track.",
|
||||
"viewAllNumbers": "view all numbers"
|
||||
},
|
||||
"passwordSetRemotely": "definido por otro participante",
|
||||
"passwordDigitsOnly": "Hasta {{number}} dígitos",
|
||||
"poweredby": "proporcionado por",
|
||||
"presenceStatus": {
|
||||
"busy": "Ocupado",
|
||||
"calling": "Llamando…",
|
||||
@@ -514,6 +580,11 @@
|
||||
"sectionList": {
|
||||
"pullToRefresh": "Actualizar"
|
||||
},
|
||||
"security": {
|
||||
"about": "Usted puede agregar una contraseña a la reunión. Los participantes necesitaran la contraseña para unirse a la reunión.",
|
||||
"insecureRoomNameWarning": "El nombre de la sala es inseguro. Participantes no desseados pueden llegar a unirse a la reunión.",
|
||||
"securityOptions": "Opciones de seguridad"
|
||||
},
|
||||
"settings": {
|
||||
"calendar": {
|
||||
"about": "La integración del calendario {{appName}} se utiliza para acceder de forma segura a su calendario para que pueda leer los próximos eventos.",
|
||||
@@ -526,6 +597,7 @@
|
||||
"followMe": "Todos me siguen",
|
||||
"language": "Idioma",
|
||||
"loggedIn": "Sesión iniciada como {{name}}",
|
||||
"microphones": "Micrófono",
|
||||
"moderator": "Moderador",
|
||||
"more": "Más",
|
||||
"name": "Nombre",
|
||||
@@ -540,6 +612,7 @@
|
||||
"settingsView": {
|
||||
"advanced": "Avanzado",
|
||||
"alertOk": "OK",
|
||||
"alertCancel": "Cancelar",
|
||||
"alertTitle": "Aviso",
|
||||
"alertURLText": "La dirección URL del servidor no es válida",
|
||||
"buildInfoSection": "Información de la compilación",
|
||||
@@ -549,6 +622,8 @@
|
||||
"displayName": "Nombre a mostrar",
|
||||
"email": "Email",
|
||||
"header": "Ajustes",
|
||||
"email": "Correo electrónico",
|
||||
"header": "Configuración",
|
||||
"profileSection": "Perfil",
|
||||
"serverURL": "URL del servidor",
|
||||
"showAdvanced": "Mostrar configuración avanzada",
|
||||
@@ -587,6 +662,7 @@
|
||||
"chat": "Alternar ventana de chat",
|
||||
"document": "Alternar documento compartido",
|
||||
"download": "Descarga nuestras aplicaciones",
|
||||
"e2ee": "Cifrado Extremo-a-Extremo",
|
||||
"feedback": "Dejar comentarios",
|
||||
"fullScreen": "Alternar pantalla completa",
|
||||
"hangup": "Dejar la llamada",
|
||||
@@ -604,6 +680,7 @@
|
||||
"raiseHand": "Levantar / Bajar tu mano",
|
||||
"recording": "Activar grabación",
|
||||
"remoteMute": "Silenciar participante",
|
||||
"security": "Opciones de seguridad",
|
||||
"Settings": "Alternar configuración",
|
||||
"sharedvideo": "Alternar compartir un vídeo de YouTube",
|
||||
"shareRoom": "Invitar a alguien",
|
||||
@@ -613,6 +690,7 @@
|
||||
"speakerStats": "Alternar estadísticas del orador",
|
||||
"tileView": "Alternar vista de mosaico",
|
||||
"toggleCamera": "Alternar cámara",
|
||||
"toggleFilmstrip": "Alternar mosaicos",
|
||||
"videomute": "Alternar silencio de video",
|
||||
"videoblur": "Alternar desenfoque de video"
|
||||
},
|
||||
@@ -627,6 +705,7 @@
|
||||
"documentClose": "Cerrar documento compartido",
|
||||
"documentOpen": "Abrir documento compartido",
|
||||
"download": "Descarga nuestras aplicaciones",
|
||||
"e2ee": "Cifrado Extremo-a-Extremo",
|
||||
"enterFullScreen": "Ver pantalla completa",
|
||||
"enterTileView": "Entrar en vista de mosaico",
|
||||
"exitFullScreen": "Salir de pantalla completa",
|
||||
@@ -640,18 +719,22 @@
|
||||
"lowerYourHand": "Bajar la mano",
|
||||
"moreActions": "Más acciones",
|
||||
"moreOptions": "Más opciones",
|
||||
"mute": "Activar / Desactivar Silencio",
|
||||
"mute": "Activar o silenciar el micrófono",
|
||||
"muteEveryone": "Silenciar a todos",
|
||||
"noAudioSignalTitle": "¡No hay entrada proveniente de su micrófono!",
|
||||
"noAudioSignalDesc": "Si no lo silenció a propósito desde la configuración del sistema o el dispositivo, considere cambiar el dispositivo.",
|
||||
"noAudioSignalDescSuggestion": "Si no lo silenció a propósito desde la configuración del sistema o el dispositivo, considere usar el siguiente dispositivo:",
|
||||
"noisyAudioInputTitle": "",
|
||||
"noisyAudioInputDesc": "",
|
||||
"noAudioSignalDialInDesc": "Usted puede además llamar usando:",
|
||||
"noAudioSignalDialInLinkDesc": "Números de llamada",
|
||||
"noisyAudioInputTitle": "Su micrófono parece estar ruidoso",
|
||||
"noisyAudioInputDesc": "Parece que su micráfono está haciendo ruido, por favor considere silenciarlo o cambiar de dispositivo.",
|
||||
"openChat": "Abrir chat",
|
||||
"pip": "Entra en el modo Picture-in-Picture",
|
||||
"privateMessage": "Enviar mensaje privado",
|
||||
"profile": "Editar tu perfil",
|
||||
"raiseHand": "Levantar / Bajar tu mano",
|
||||
"raiseYourHand": "Alzar la mano",
|
||||
"security": "Opciones de seguridad",
|
||||
"Settings": "Ajustes",
|
||||
"sharedvideo": "Compartir un vídeo de YouTube",
|
||||
"shareRoom": "Invitar a alguien",
|
||||
@@ -717,21 +800,19 @@
|
||||
"lowDefinition": "Baja definición",
|
||||
"onlyAudioAvailable": "Solo hay audio disponible",
|
||||
"onlyAudioSupported": "Solo soportamos audio en este navegador.",
|
||||
"p2pEnabled": "Punto a Punto Activado",
|
||||
"p2pVideoQualityDescription": "En el modo punto a punto, la calidad de video recibida solo se puede alternar entre calidad alta y solo audio. No se respetarán otras configuraciones hasta que se salga del modo punto a punto.",
|
||||
"recHighDefinitionOnly": "Preferirá alta definición.",
|
||||
"sd": "SD",
|
||||
"sdTooltip": "Visualizando vídeo en definición estándar",
|
||||
"standardDefinition": "Definición estándar"
|
||||
},
|
||||
"videothumbnail": {
|
||||
"domute": "Silenciar",
|
||||
"domuteOthers": "Silenciar a todos",
|
||||
"flip": "Voltear",
|
||||
"kick": "Expulsar",
|
||||
"moderator": "Moderador",
|
||||
"mute": "Participante está silenciado",
|
||||
"muted": "Silenciado",
|
||||
"remoteControl": "",
|
||||
"remoteControl": "Control remoto",
|
||||
"show": "Mostrar en escena",
|
||||
"videomute": "El participante ha detenido la cámara."
|
||||
},
|
||||
@@ -749,6 +830,7 @@
|
||||
"connectCalendarButton": "Conecte su calendario",
|
||||
"connectCalendarText": "Conecte su calendario para ver todas sus reuniones en {{app}}. Plus, add {{provider}}reuniones a tu calendario e iniciarlas con un solo clic.",
|
||||
"enterRoomTitle": "Comenzar una reunión",
|
||||
"getHelp": "Obtener ayuda",
|
||||
"roomNameAllowedChars": "El nombre de la reunión no debe contener ninguno de estos caracteres: ?, &, :, ', \", %, #.",
|
||||
"go": "IR",
|
||||
"goSmall": "IR",
|
||||
@@ -763,10 +845,13 @@
|
||||
"roomnameHint": "Introduce el nombre o URL de la sala a la que quieres unirte. Puedes crear un nombre nuevo, sólo tienes que hacer llegar este nombre al resto de participantes para que puedan unirse a esta sala.",
|
||||
"sendFeedback": "Enviar comentarios",
|
||||
"terms": "Términos",
|
||||
"title": "Seguro, lleno de funcionalidades y videoconferencias completamente gratuitas"
|
||||
"title": "Videoconferencias seguras, con gran variedad de funcionalidades y completamente gratuitas"
|
||||
},
|
||||
"lonelyMeetingExperience": {
|
||||
"button": "Invitar a otros",
|
||||
"youAreAlone": "Eres el único en la reunión"
|
||||
},
|
||||
"helpView": {
|
||||
"header": "Centro de ayuda"
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user