Compare commits

...

85 Commits

Author SHA1 Message Date
Paweł Domas
4b9e156c5d Generic iOS .ipa build script (#4775) 2019-10-22 12:45:28 -05:00
Bettenbuk Zoltan
9265e1ffec ui: web chat facelift 2019-10-22 13:16:00 +02:00
Bettenbuk Zoltan
d11735b04c feat: make the hangup button first 2019-10-21 19:00:12 +02:00
Saúl Ibarra Corretgé
d33b700477 rn,blank-page: refactor BlankPage
- Remove network-activity "feature"
    - It wasn't in use
    - It relied on internal React Native components, bound to break anytime
- Show an infinite loading indicator
- Style it just like the LoadConfigOverlay
    - Since it kinda represents the opposite, an "unload" then SDK is done
2019-10-21 11:17:56 +02:00
Saúl Ibarra Corretgé
97d75c2cb9 android: fix SDK release script for new dependency syntax
Skip the first character, since it's now like ^123456.0.0
2019-10-21 11:12:26 +02:00
Saúl Ibarra Corretgé
287115f4c3 deps: react-native-webrtc@latest
Fixes a crash on iOS when disposing streams.
2019-10-18 14:05:18 +02:00
Saúl Ibarra Corretgé
63a221212b ios: add ability to manually toggle WebRTC logging 2019-10-18 14:05:18 +02:00
Bettenbuk Zoltan
6a916fd0e1 fix: fix filmstrip-only toolbar 2019-10-18 13:16:15 +02:00
yanas
220691d61d Merge pull request #4762 from jitsi/fix-etherpad-follow-me
Fixes showing etherpad in follow-me mode.
2019-10-17 13:44:10 +01:00
damencho
5cafc4bcbd Fixes showing etherpad in follow-me mode. 2019-10-17 13:39:01 +01:00
yanas
b3a78dc2e6 Merge pull request #4761 from zbettenbuk/aot-icons
fix: fix and refactor AoT css
2019-10-17 12:34:13 +01:00
Bettenbuk Zoltan
bebc6eabe5 fix: fix and refactor AoT css 2019-10-17 12:15:29 +02:00
paweldomas
26dc6a4ac2 update logger and LJM to support log timestamps 2019-10-16 15:59:58 -05:00
Hristo Terezov
ff2626723a fix(HelpButton): Improvements. 2019-10-16 13:34:43 -07:00
Mihai Uscat
72bb897269 feat(DownloadOverflowButton): Implement. 2019-10-16 11:30:06 -07:00
damencho
f46387a226 Adds room name validation logic for web. 2019-10-16 17:52:24 +01:00
damencho
a4cbbccb2a Fixes loading recent lists on wrong meeting name stored.
decodeURIComponent is not needed any more and after adding a validation such meeting name should not happen to be stored.
2019-10-16 17:52:24 +01:00
damencho
3e1a008399 Adds copy icon next to the meeting url in info dialog. 2019-10-16 17:52:24 +01:00
Bettenbuk Zoltan
7e70a8c1de feat: make mobile chat messages selectable 2019-10-16 16:05:10 +02:00
Hristo Terezov
8efee04a10 feat(package.json): Node 12 support. 2019-10-16 06:34:44 -07:00
Bettenbuk Zoltan
a35099f949 feat: add chat color scheming 2019-10-16 10:38:28 +02:00
Mihai Uscat
8be02f9ca1 Implement review changes 2019-10-15 06:54:54 -07:00
Mihai Uscat
3c25a4c08c Naming conventions; Add variables 2019-10-15 06:54:54 -07:00
Mihai Uscat
5ade0cad8b feat(welcome): add posibility to extend settings toolbar 2019-10-15 06:54:54 -07:00
Saúl Ibarra Corretgé
0fa6ffc439 deps: react-native-google-signin@3.0.1 2019-10-14 19:12:45 +02:00
Saúl Ibarra Corretgé
c2ed296178 android: make check more resilient
If action is null (observed on some old devices) we'll get an exception.
Reversing the check fixes it since Actions.XXX is statically defined.
2019-10-14 17:45:43 +02:00
Saúl Ibarra Corretgé
febd12b871 ci: use Xcode 11.1 on Travis 2019-10-14 16:47:07 +02:00
Hristo Terezov
0a06e256b7 feat(HelpButton): Mobile support. 2019-10-14 07:35:39 -07:00
Hristo Terezov
f295f60bea feat(HelpOverflowButton): Implement. 2019-10-14 07:35:39 -07:00
Saúl Ibarra Corretgé
4a8f787519 rn: evaluate config.js in a sandboxed environment
We are downloading code off the Internet and executing it on the user's device,
so run it sandboxed to avoid potential bad actors.

Since it's impossible to eval() safely in JS and React Native doesn't offer
something akin to Node's vm module, here we are rolling our own.

On Android it uses the Duktape JavaScript engine and on iOS the builtin
JavaScriptCore engine. The extra JS engine is *only* used for evaluating the
downloaded code and returning a JSON string which is then passed back to RN.
2019-10-14 12:20:58 +02:00
Saúl Ibarra Corretgé
d85b869934 rn: skip loading configured scriptUrls
None of them work on mobile.
2019-10-14 12:20:58 +02:00
Saúl Ibarra Corretgé
35130f0736 rn: refactor loadScript
- use AbortController for setting the fetch timeout
- use async / await syntax for clarify
- set the default timeout to 5s (previously non-existent, aka 0)
- add ability to load but not evaluate a script
2019-10-14 12:20:58 +02:00
Saúl Ibarra Corretgé
1feff9709c config: drop configLocation and getroomnode options
They never worked on mobile and pose an impediment for makinf config.js more
future proof. Specially if we want to move to a non-executable form of
configuration.
2019-10-14 12:20:58 +02:00
Leonard Kim
1010f53a84 fix(config): add whitelisting for interface config
For now all keys are whitelisted.
2019-10-11 09:38:56 -07:00
Saúl Ibarra Corretgé
f7a526f488 rn: fix rendering unnecessary stuff when in PiP mode 2019-10-11 17:17:53 +02:00
Bettenbuk Zoltan
245eb89b85 fix BottomSheet shaking 2019-10-11 15:14:51 +02:00
Hristo Terezov
99de9d0bfa fix(remoteVideo): Attaching video stream. 2019-10-11 04:58:01 -07:00
Saúl Ibarra Corretgé
98698ba89a etherpad: refactor to share code with mobile
- simplify initialization procedure
- set user display name as the Etherpad name\
- use SharedDocumentButton
2019-10-10 11:19:38 +02:00
Saúl Ibarra Corretgé
19d1e3829d rn: add shared document support using Etherpad 2019-10-10 11:19:38 +02:00
Saúl Ibarra Corretgé
612586ed1f deps: react-native-webview@7.4.1 2019-10-10 11:19:38 +02:00
Saúl Ibarra Corretgé
2609e43f29 ios: misc Xcode changes due to an update 2019-10-10 11:19:38 +02:00
Saúl Ibarra Corretgé
c5cd4f534c dial-in-summary: center the loading indicator 2019-10-10 11:19:38 +02:00
Bettenbuk Zoltan
6e10ca5dd2 fix: chat error message 2019-10-09 18:35:09 +02:00
Bettenbuk Zoltan
0fff1c3534 ref: serve makefile libs locally 2019-10-09 11:56:06 +02:00
Bettenbuk Zoltan
42271b1b89 feat: private messages 2019-10-08 18:22:45 +02:00
Bettenbuk Zoltan
f270b50972 fix: remove unnecessary escaping 2019-10-08 18:22:45 +02:00
Saúl Ibarra Corretgé
ab4b6be9d7 rn: throw exception if default conference options set the room
See: https://github.com/jitsi/jitsi-meet/issues/4720
2019-10-08 14:31:13 +02:00
Saúl Ibarra Corretgé
c45ee0230f android: add getters to JitsiMeetConferenceOptions 2019-10-08 14:31:13 +02:00
George Politis
d210f2f2e7 Adds a noAutoPlayVideo configuration option (used in testing). (#4714)
This adds an option to disable video autoplay that will be used mostly with maleus (our selenium-based load testing tool for testing the new bridge). Disabling video rendering lowers the resource utilisation of the selenium nodes.
2019-10-08 11:34:25 +02:00
Bettenbuk Zoltan
13d78d6b49 fix: utf-8 room name case sensitivity 2019-10-08 10:35:19 +02:00
damencho
34a71042c6 Enables Hungarian translation. 2019-10-05 00:11:25 +01:00
damencho
47ecf7d035 Commit from translate.jitsi.org by user damencho.: 601 of 601 strings translated (0 fuzzy). 2019-10-04 23:15:36 +00:00
damencho
bbe8c52778 Commit from translate.jitsi.org by user damencho.: 600 of 601 strings translated (1 fuzzy). 2019-10-04 23:15:24 +00:00
damencho
2011421e9d Commit from translate.jitsi.org by user damencho.: 582 of 601 strings translated (3 fuzzy). 2019-10-04 23:15:08 +00:00
damencho
ce55952ca9 Commit from translate.jitsi.org by user damencho.: 524 of 601 strings translated (5 fuzzy). 2019-10-04 23:14:58 +00:00
damencho
f93482e815 Commit from translate.jitsi.org by user damencho.: 582 of 601 strings translated (0 fuzzy). 2019-10-04 23:14:45 +00:00
Andrei Gavrilescu
761ac6a730 feat: integrate rnnoise based service for voice activity (VAD) detection 2019-10-04 12:55:18 +02:00
Djorkaeff Alexandre
11d3a343e5 ios: use iPhone 8 simulator when archiving JitsiMeet framework
It's available on both Xcode 10 and 11.
2019-10-04 11:00:31 +02:00
Saúl Ibarra Corretgé
9666bf836e ios: update CocoaPods to version 1.8 2019-10-04 11:00:31 +02:00
Saúl Ibarra Corretgé
a6d3b09796 ios: support building with Xcode 11 2019-10-04 11:00:31 +02:00
Дамян Минков
bb0036fdab Adds notifications for who stop/start recording/live streaming. (#4708)
* Adds notifications for who stop/start recording/live streaming.

* Updates to latest lib-jitsi-meet.
2019-10-03 20:35:21 +01:00
paweldomas
8dc0f30a49 ref(NAT64AddrInfoModule): use 'ipv4only.arpa' well known host
defined in RFC7050 instead of 'nat64.jitsi.net' as suggested by
Jonathan Lennox.
2019-10-02 10:49:39 -05:00
Saúl Ibarra Corretgé
1aed08f460 deps: react-native-webrtc@latest
Fixes iOS crashes when restarting the AudioUnit in case of interruption.
2019-10-02 14:44:15 +02:00
Saúl Ibarra Corretgé
afccf6f06d rn: disable H.264 on iOS 10 devices
It crashes like hell. See:
https://bugs.chromium.org/p/webrtc/issues/detail?id=11002
2019-10-02 14:10:37 +02:00
damencho
5cd351a46f Updates rayo filter to add user token info to dial messages.
Adds option to limit number of outgoing calls per user.
2019-09-30 16:53:38 +01:00
damencho
51f257e894 chore(deps): update LJM to 3f7613748d7669cd3fd031bbdf9069e4309f6f56 2019-09-30 11:53:30 +01:00
Saúl Ibarra Corretgé
ac06892bb4 android,ios: now working on versions 19.4 / 2.4 2019-09-26 17:33:52 +02:00
Saúl Ibarra Corretgé
fd8473cb52 deps: react-native-webrtc@latest
Avoid Android crashes.
2019-09-26 17:33:52 +02:00
damencho
3f40257f89 chore(deps): update LJM to a61941fc9a1927daedc1c9446e4036702964b38a
Uses sendBeacon to send xmpp presence unavailable on unloading the window(leaving the conference).
2019-09-26 16:20:57 +01:00
paweldomas
14509adff2 chore(deps): update LJM to dda16f607ed190a0664d643d511cc87f9bfceaf1
It was referencing LJM from a PR branch instead of the master.
2019-09-25 16:57:06 -05:00
Bettenbuk Zoltan
c472537ecf update RN to 61 2019-09-25 17:31:52 +02:00
Jaya Allamsetty
d40fce741a Fix the WebGL memory leak for Blur effect in Chrome 77 and up (#4652) 2019-09-24 06:50:10 -07:00
Saúl Ibarra Corretgé
944e8f8353 android: fix NPE when handling onHostPause
If the Activity is put into the background before the ReactContext is created we
get an NPE here. While the window might be short, it's thechnically possible to
hit this, as our Crashlytics reports show.
2019-09-24 09:49:52 +02:00
Saúl Ibarra Corretgé
7d972a50f2 ios: set logger subsystem and category
The subsystem is set to the bundle ID and the category to "JitsiMeetSDK".
2019-09-24 09:49:33 +02:00
Leonard Kim
92e7be34e3 fix(icons): scope white svgs to Icon components 2019-09-20 07:50:41 -07:00
Bettenbuk Zoltan
f5dba929a5 fix: add support for functional component type icons 2019-09-20 16:35:56 +02:00
Saúl Ibarra Corretgé
64d2885233 android: raise SDK version 2019-09-20 10:25:42 +02:00
Saúl Ibarra Corretgé
4ce65ae7a7 android: make reportConnectedOutgoingCall return a Promise
The call-integration middleware relies on it returning it, as iOS does.
2019-09-20 10:25:42 +02:00
Saúl Ibarra Corretgé
07bf95f838 doc: add info on reporting security issues 2019-09-19 13:49:46 +02:00
Saúl Ibarra Corretgé
3469d5dc4f doc: move development sections to standalone file 2019-09-19 13:49:46 +02:00
Leonard Kim
8c0f942ae1 add more logging around attaching videos to thumbnails 2019-09-19 10:46:36 +02:00
Leonard Kim
b8aa74f212 fix(large-video): bring back workaround for selecting on conference join
Bring back the workaround introduced in afd2aea7
but removed in 21dcc41d. On conference join,
several other actions have already been fired
that try to set the large video participant
and select the participant on the bridge.
The problem is there is no conference during
these actions so the select participant
never fires. Then subsequent actions do not
fire select participant because the large
video participant has not changed.
2019-09-18 15:00:13 -07:00
George Politis
2a7c6681ad ref: Changes how isVideoPlayable is computed.
This commit changes how the SmallVideo.isVideoPlayable method works.

1st we remove the check on the video stream muted field (materialized with the
!this.videoStream.isMuted() guard). This check is redundant as it is
already materialized in the !this.isVideoMuted check (the isVideoMuted
field is updated with the return value of the videoStream.isMuted()
method).

2nd we return false if we're in audio only mode, because it's
(obviously) undesirable to have a playable video when in audio only
mode.
2019-09-17 18:18:44 +02:00
George Politis
324a9eba91 minor change in debug log wording 2019-09-17 18:18:44 +02:00
George Politis
fb1ed22c6c ref: Tweak logging logic for thumbnail display mode and tile view. 2019-09-17 18:18:44 +02:00
194 changed files with 8178 additions and 5570 deletions

View File

@@ -11,6 +11,9 @@ node_modules/react-native/Libraries/react-native/React.js
; "node_modules/react-native" but in the source repo it is in the root
node_modules/react-native/Libraries/react-native/React.js
; Flow doesn't support platforms
.*/Libraries/Utilities/LoadingView.js
; Ignore polyfills
node_modules/react-native/Libraries/polyfills/.*
@@ -112,4 +115,4 @@ untyped-import
untyped-type-import
[version]
^0.98.0
^0.104.0

View File

@@ -0,0 +1,11 @@
---
name: Security issues
about: Please email security@jitsi.org
---
We take security very seriously and develop all Jitsi projects to be secure and safe.
If you find (or simply suspect) a security issue in any of the Jitsi projects, please send us an email to security@jitsi.org.
We encourage responsible disclosure for the sake of our users, so please reach out before posting in a public space.

View File

@@ -1,4 +1,4 @@
osx_image: xcode10.2
osx_image: xcode11.1
language: objective-c
script:
- "./ios/travis-ci/build-ipa.sh"

View File

@@ -3,6 +3,7 @@ CLEANCSS = ./node_modules/.bin/cleancss
DEPLOY_DIR = libs
LIBJITSIMEET_DIR = node_modules/lib-jitsi-meet/
LIBFLAC_DIR = node_modules/libflacjs/dist/min/
RNNOISE_WASM_DIR = node_modules/rnnoise-wasm/dist/
NODE_SASS = ./node_modules/.bin/node-sass
NPM = npm
OUTPUT_DIR = .
@@ -20,7 +21,7 @@ compile:
clean:
rm -fr $(BUILD_DIR)
deploy: deploy-init deploy-appbundle deploy-lib-jitsi-meet deploy-libflac deploy-css deploy-local
deploy: deploy-init deploy-appbundle deploy-rnnoise-binary deploy-lib-jitsi-meet deploy-libflac deploy-css deploy-local
deploy-init:
rm -fr $(DEPLOY_DIR)
@@ -47,6 +48,8 @@ deploy-appbundle:
$(BUILD_DIR)/analytics-ga.min.map \
$(BUILD_DIR)/video-blur-effect.min.js \
$(BUILD_DIR)/video-blur-effect.min.map \
$(BUILD_DIR)/rnnoise-processor.min.js \
$(BUILD_DIR)/rnnoise-processor.min.map \
$(DEPLOY_DIR)
deploy-lib-jitsi-meet:
@@ -63,6 +66,11 @@ deploy-libflac:
$(LIBFLAC_DIR)/libflac4-1.3.2.min.js.mem \
$(DEPLOY_DIR)
deploy-rnnoise-binary:
cp \
$(RNNOISE_WASM_DIR)/rnnoise.wasm \
$(DEPLOY_DIR)
deploy-css:
$(NODE_SASS) $(STYLES_MAIN) $(STYLES_BUNDLE) && \
$(CLEANCSS) $(STYLES_BUNDLE) > $(STYLES_DESTINATION) ; \
@@ -71,7 +79,7 @@ deploy-css:
deploy-local:
([ ! -x deploy-local.sh ] || ./deploy-local.sh)
dev: deploy-init deploy-css deploy-lib-jitsi-meet deploy-libflac
dev: deploy-init deploy-css deploy-rnnoise-binary deploy-lib-jitsi-meet deploy-libflac
$(WEBPACK_DEV_SERVER)
source-package:

View File

@@ -31,82 +31,9 @@ You can get our mobile versions from here:
* [Android](https://play.google.com/store/apps/details?id=org.jitsi.meet)
* [iOS](https://itunes.apple.com/us/app/jitsi-meet/id1165103905)
## Building the sources
## Development
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 `beta.meet.jit.si`. 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/
For web development see [here](doc/development.md), and for mobile see [here](doc/mobile.md).
## Contributing
@@ -118,7 +45,8 @@ see our [guidelines for contributing](CONTRIBUTING.md).
Jitsi Meet provides a very flexible way of embedding in external applications by using the [Jitsi Meet API](doc/api.md).
## Security
WebRTC does not provide a way of conducting multi-party conversations with end-to-end encryption.
WebRTC does not (yet) provide a way of conducting multi-party conversations with end-to-end encryption.
Unless you consistently compare DTLS fingerprints with your peers vocally, the same goes for one-to-one calls.
As a result, your stream is encrypted on the network but decrypted on the machine that hosts the bridge when using Jitsi Meet.
@@ -130,9 +58,13 @@ Jitsi Meet in terms of security.
The [meet.jit.si](https://meet.jit.si) service is maintained by the Jitsi team
at [8x8](https://8x8.com).
## Mobile app
Jitsi Meet is also available as a React Native app for Android and iOS.
Instructions on how to build it can be found [here](doc/mobile.md).
## Security issues
We take security very seriously and develop all Jitsi projects to be secure and safe.
If you find (or simply suspect) a security issue in any of the Jitsi projects, please send us an email to security@jitsi.org.
**We encourage responsible disclosure for the sake of our users, so please reach out before posting in a public space.**
## Acknowledgements

View File

@@ -20,5 +20,5 @@
android.useAndroidX=true
android.enableJetifier=true
appVersion=19.3.0
sdkVersion=2.3.0
appVersion=19.4.0
sdkVersion=2.4.0

View File

@@ -10,7 +10,7 @@ MVN_HTTP=0
DEFAULT_SDK_VERSION=$(grep sdkVersion ${THIS_DIR}/../gradle.properties | cut -d"=" -f2)
SDK_VERSION=${OVERRIDE_SDK_VERSION:-${DEFAULT_SDK_VERSION}}
RN_VERSION=$(jq -r '.dependencies."react-native"' ${THIS_DIR}/../../package.json)
JSC_VERSION="r"$(jq -r '.dependencies."jsc-android"' ${THIS_DIR}/../../node_modules/react-native/package.json | cut -d . -f 1)
JSC_VERSION="r"$(jq -r '.dependencies."jsc-android"' ${THIS_DIR}/../../node_modules/react-native/package.json | cut -d . -f 1 | cut -c 2-)
DO_GIT_TAG=${GIT_TAG:-0}
if [[ $THE_MVN_REPO == http* ]]; then

View File

@@ -45,6 +45,7 @@ dependencies {
implementation 'com.dropbox.core:dropbox-core-sdk:3.0.8'
implementation 'com.jakewharton.timber:timber:4.7.1'
implementation 'com.squareup.duktape:duktape-android:1.3.0'
if (!rootProject.ext.libreBuild) {
implementation 'com.amplitude:android-sdk:2.14.1'

View File

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

View File

@@ -33,6 +33,9 @@ public class JitsiMeet {
}
public static void setDefaultConferenceOptions(JitsiMeetConferenceOptions options) {
if (options != null && options.getRoom() != null) {
throw new RuntimeException("'room' must be null in the default conference options");
}
defaultConferenceOptions = options;
}

View File

@@ -122,7 +122,7 @@ public class JitsiMeetActivityDelegate {
// https://github.com/facebook/react-native/blob/df4e67fe75d781d1eb264128cadf079989542755/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java#L512
// Why this happens is a mystery wrapped in an enigma.
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
if (activity == reactContext.getCurrentActivity()) {
if (reactContext != null && activity == reactContext.getCurrentActivity()) {
reactInstanceManager.onHostPause(activity);
}
}

View File

@@ -72,6 +72,46 @@ public class JitsiMeetConferenceOptions implements Parcelable {
*/
private JitsiMeetUserInfo userInfo;
public URL getServerURL() {
return serverURL;
}
public String getRoom() {
return room;
}
public String getSubject() {
return subject;
}
public String getToken() {
return token;
}
public Bundle getColorScheme() {
return colorScheme;
}
public Bundle getFeatureFlags() {
return featureFlags;
}
public boolean getAudioMuted() {
return audioMuted;
}
public boolean getAudioOnly() {
return audioOnly;
}
public boolean getVideoMuted() {
return videoMuted;
}
public JitsiMeetUserInfo getUserInfo() {
return userInfo;
}
/**
* Class used to build the immutable {@link JitsiMeetConferenceOptions} object.
*/

View File

@@ -87,7 +87,7 @@ public class JitsiMeetOngoingConferenceService extends Service
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
final String action = intent.getAction();
if (action.equals(Actions.START)) {
if (Actions.START.equals(action)) {
Notification notification = OngoingNotification.buildOngoingConferenceNotification();
if (notification == null) {
stopSelf();
@@ -96,7 +96,7 @@ public class JitsiMeetOngoingConferenceService extends Service
startForeground(OngoingNotification.NOTIFICATION_ID, notification);
JitsiMeetLogger.i(TAG + " Service started");
}
} else if (action.equals(Actions.HANGUP)) {
} else if (Actions.HANGUP.equals(action)) {
JitsiMeetLogger.i(TAG + " Hangup requested");
// Abort all ongoing calls
if (AudioModeModule.useConnectionService()) {

View File

@@ -144,9 +144,10 @@ class RNConnectionService
* @param callUUID - the call's UUID.
*/
@ReactMethod
public void reportConnectedOutgoingCall(String callUUID) {
public void reportConnectedOutgoingCall(String callUUID, Promise promise) {
JitsiMeetLogger.d(TAG + " reportConnectedOutgoingCall " + callUUID);
ConnectionService.setConnectionActive(callUUID);
promise.resolve(null);
}
@Override

View File

@@ -67,6 +67,7 @@ class ReactInstanceManagerHolder {
new AudioModeModule(reactContext),
new DropboxModule(reactContext),
new ExternalAPIModule(reactContext),
new JavaScriptSandboxModule(reactContext),
new LocaleDetector(reactContext),
new LogBridgeModule(reactContext),
new PictureInPictureModule(reactContext),

View File

@@ -43,7 +43,7 @@ public class NAT64AddrInfoModule
* The host for which the module wil try to resolve both IPv4 and IPv6
* addresses in order to figure out the NAT64 prefix.
*/
private final static String HOST = "nat64.jitsi.net";
private final static String HOST = "ipv4only.arpa";
/**
* How long is the {@link NAT64AddrInfo} instance valid.

View File

@@ -10,7 +10,7 @@ project(':react-native-community-async-storage').projectDir = new File(rootProje
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-google-signin'
project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-google-signin/android')
project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/google-signin/android')
include ':react-native-immersive'
project(':react-native-immersive').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-immersive/android')
include ':react-native-keep-awake'

View File

@@ -104,7 +104,6 @@ import {
trackRemoved
} from './react/features/base/tracks';
import { getJitsiMeetGlobalNS } from './react/features/base/util';
import { addMessage } from './react/features/chat';
import { showDesktopPicker } from './react/features/desktop-picker';
import { appendSuffix } from './react/features/display-name';
import {
@@ -114,7 +113,6 @@ import {
import { mediaPermissionPromptVisibilityChanged } from './react/features/overlay';
import { suspendDetected } from './react/features/power-monitor';
import { setSharedVideoStatus } from './react/features/shared-video';
import { isButtonEnabled } from './react/features/toolbox';
import { endpointMessageReceived } from './react/features/subtitles';
const logger = require('jitsi-meet-logger').getLogger(__filename);
@@ -244,8 +242,6 @@ class ConferenceConnector {
this._handleConferenceJoined.bind(this));
room.on(JitsiConferenceEvents.CONFERENCE_FAILED,
this._onConferenceFailed.bind(this));
room.on(JitsiConferenceEvents.CONFERENCE_ERROR,
this._onConferenceError.bind(this));
}
/**
@@ -348,31 +344,6 @@ class ConferenceConnector {
}
}
/**
*
*/
_onConferenceError(err, ...params) {
logger.error('CONFERENCE Error:', err, params);
switch (err) {
case JitsiConferenceErrors.CHAT_ERROR:
logger.error('Chat error.', err);
if (isButtonEnabled('chat') && !interfaceConfig.filmStripOnly) {
const [ code, msg ] = params;
APP.store.dispatch(addMessage({
hasRead: true,
error: code,
message: msg,
messageType: 'error',
timestamp: Date.now()
}));
}
break;
default:
logger.error('Unknown error.', err);
}
}
/**
*
*/

View File

@@ -1,16 +1,6 @@
/* eslint-disable no-unused-vars, no-var */
var config = {
// Configuration
//
// Alternative location for the configuration.
// configLocation: './config.json',
// Custom function which given the URL path should return a room name.
// getroomnode: function (path) { return 'someprefixpossiblybasedonpath'; },
// Connection
//
@@ -60,6 +50,10 @@ var config = {
// Enables the test specific features consumed by jitsi-meet-torture
// testMode: false
// 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
},
// Disables ICE/UDP by filtering out local and remote UDP candidates in
@@ -425,6 +419,16 @@ var config = {
// the menu has option to flip the locally seen video for local presentations
// disableLocalVideoFlip: false
// Deployment specific URLs.
// deploymentUrls: {
// // If specified a 'Help' button will be displayed in the overflow menu with a link to the specified URL for
// // user documentation.
// userDocumentationURL: 'https://docs.example.com/video-meetings.html',
// // If specified a 'Download our apps' button will be displayed in the overflow menu with a link
// // to the specified URL for an app download page.
// downloadAppsUrl: 'https://docs.example.com/our-apps.html'
// }
// List of undocumented settings used in jitsi-meet
/**
_immediateReloadThreshold

View File

@@ -33,7 +33,7 @@ body {
}
}
svg {
.jitsi-icon svg {
fill: white;
}

View File

@@ -80,6 +80,28 @@
}
}
#chat-recipient {
align-items: center;
background-color: $chatPrivateMessageBackgroundColor;
display: flex;
flex-direction: row;
font-weight: 100;
padding: 10px;
span {
color: white;
display: flex;
flex: 1;
}
div {
svg {
cursor: pointer;
fill: white
}
}
}
.chat-header {
background-color: $chatHeaderBackgroundColor;
height: 70px;
@@ -111,6 +133,7 @@
#chat-input {
border-top: 1px solid $chatInputSeparatorColor;
display: flex;
padding: 5px 10px;
* {
background-color: transparent;
@@ -131,8 +154,7 @@
box-shadow: none;
color: white;
font-size: 15px;
line-height: 30px;
padding: 5px;
padding: 10px;
overflow-y: auto;
resize: none;
width: 100%;
@@ -162,6 +184,7 @@
.display-name {
font-size: 13px;
font-weight: bold;
margin-bottom: 5px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
@@ -175,7 +198,6 @@
color: white;
margin-top: 3px;
max-width: 100%;
padding-bottom: 3px;
position: relative;
&.localuser {
@@ -196,6 +218,15 @@
padding: 0;
}
}
.privatemessagenotice {
font-size: 11px;
font-weight: 100;
}
.messagecontent {
margin: 5px 10px;
}
}
.smiley {
@@ -228,6 +259,7 @@
.smileys-panel {
bottom: 100%;
box-sizing: border-box;
background-color: rgba(0, 0, 0, .6) !important;
height: auto;
max-height: 0;
overflow: hidden;
@@ -270,10 +302,6 @@
cursor: pointer;
}
#usermsg::-webkit-input-placeholder {
line-height: 30px;
}
#usermsg::-webkit-scrollbar-track-piece {
background: #3a3a3a;
}
@@ -288,6 +316,10 @@
.chatmessage {
background-color: $chatLocalMessageBackgroundColor;
border-radius: 6px 0px 6px 6px;
&.privatemessage {
background-color: $chatPrivateMessageBackgroundColor;
}
}
.display-name {
@@ -301,8 +333,9 @@
&.error {
.chatmessage {
background-color: $defaultWarningColor;
border-radius: 0px;
color: red;
font-weight: 100;
}
.display-name {
@@ -312,6 +345,25 @@
.chatmessage-wrapper {
max-width: 100%;
.replywrapper {
display: flex;
flex-direction: row;
align-items: center;
.messageactions {
align-self: stretch;
border-left: 1px solid $chatActionsSeparatorColor;
display: flex;
flex-direction: column;
justify-content: center;
padding: 5px;
.toolbox-icon {
cursor: pointer;
}
}
}
}
.chatmessage {
@@ -320,6 +372,9 @@
display: inline-block;
margin-top: 3px;
color: white;
padding: 8px;
&.privatemessage {
background-color: $chatPrivateMessageBackgroundColor;
}
}
}

66
css/_mini_toolbox.scss Normal file
View File

@@ -0,0 +1,66 @@
.filmstrip-toolbox,
.always-on-top-toolbox {
background-color: $newToolbarBackgroundColor;
border-radius: 3px;
display: flex;
z-index: $toolbarZ;
.toolbox-icon {
cursor: pointer;
padding: 7px;
&.toggled {
background: $AOTToolbarButtonToggleColor;
}
&.disabled {
cursor: initial;
}
}
}
.always-on-top-toolbox {
flex-direction: row;
left: 50%;
position: absolute;
top: 10px;
transform: translateX(-50%);
.toolbox-button {
&:first-child {
.toolbox-icon {
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}
}
&:nth-child(2) {
svg {
fill: $hangupColor;
}
}
&:last-child {
.toolbox-icon {
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
}
}
}
.filmstrip-toolbox {
flex-direction: column;
.toolbox-button {
&:nth-child(1) {
svg {
fill: $hangupColor;
}
}
.toolbox-icon {
border-radius: 3px;
}
}
}

View File

@@ -6,7 +6,7 @@
min-width: 75px;
text-align: left;
padding: 0px;
width: 150px;
width: 180px;
white-space: nowrap;
&__item {
@@ -87,6 +87,7 @@
display: inline-block;
min-width: 20px;
height: 100%;
padding-right: 10px;
> * {
@include absoluteAligning();

View File

@@ -270,89 +270,6 @@
}
}
.always-on-top-toolbox,
.filmstrip-toolbox {
background-color: $newToolbarBackgroundColor;
box-sizing: border-box;
display: flex;
flex-direction: column;
z-index: $toolbarZ;
i {
cursor: pointer;
display: block;
}
i:hover {
background-color: $AOTToolbarButtonHoverColor;
}
i.toggled {
background: $AOTToolbarButtonToggleColor;
}
i.toggled:hover:not(.disabled) {
background-color: $AOTToolbarButtonHoverColor;
}
.toolbox-button {
color: $toolbarButtonColor;
cursor: pointer;
text-align: center;
}
border-radius: 3px;
}
.always-on-top-toolbox {
flex-direction: row;
left: 50%;
position: absolute;
top: 10px;
transform: translateX(-50%);
z-index: $toolbarZ;
i {
font-size: $newToolbarFontSize;
height: $newToolbarSize;
line-height: $newToolbarSize;
width: $newToolbarSize;
}
.disabled {
cursor: initial;
}
.toolbox-button:first-child i {
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}
.toolbox-button:last-child i {
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
}
.filmstrip-toolbox {
i {
font-size: 1.9em;
height: 37px;
line-height: 37px;
width: 37px;
}
.toolbox-button:first-child i {
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
.toolbox-button:last-child i {
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
}
}
/**
* START of fade in animation for main toolbar
*/

View File

@@ -28,6 +28,7 @@ $defaultColor: #F1F1F1;
$defaultSideBarFontColor: #44A5FF;
$defaultSemiDarkColor: #ACACAC;
$defaultDarkColor: #2b3d5c;
$defaultWarningColor: rgb(215, 121, 118);
/**
* Toolbar
@@ -85,10 +86,12 @@ $modalTextColor: #333;
/**
* Chat
*/
$chatActionsSeparatorColor: rgb(173, 105, 112);
$chatHeaderBackgroundColor: rgba(42, 58, 75, 0.9);
$chatInputSeparatorColor: #A4B8D1;
$chatLocalMessageBackgroundColor: rgba(26, 108, 180, 1);
$chatRemoteMessageBackgroundColor: rgba(240, 243, 247, 0.15);
$chatLocalMessageBackgroundColor: rgb(4, 98, 178);
$chatPrivateMessageBackgroundColor: rgb(153, 69, 77);
$chatRemoteMessageBackgroundColor: rgb(86, 101, 114);
$sidebarWidth: 375px;
/**
@@ -163,9 +166,45 @@ $watermarkHeight: 74px;
*/
$welcomePageDescriptionColor: #fff;
$welcomePageFontFamily: inherit;
$welcomePageHeaderBackground: linear-gradient(-90deg, #1251AE 0%, #0074FF 50%, #1251AE 100%);
$welcomePageBackground: linear-gradient(-90deg, #1251AE 0%, #0074FF 50%, #1251AE 100%);
$welcomePageTitleColor: #fff;
$welcomePageHeaderBackground: none;
$welcomePageHeaderBackgroundSmall: none;
$welcomePageHeaderBackgroundPosition: none;
$welcomePageHeaderBackgroundRepeat: none;
$welcomePageHeaderBackgroundSize: none;
$welcomePageHeaderPaddingBottom: 0px;
$welcomePageHeaderTextMarginTop: 35px;
$welcomePageHeaderTextMarginBottom: 35px;
$welcomePageHeaderTextTitleMarginBottom: 16px;
$welcomePageHeaderTextDescriptionDisplay: inherit;
$welcomePageEnterRoomWidth: 680px;
$welcomePageEnterRoomPadding: 25px 30px;
$welcomePageEnterRoomBorderRadius: 0px;
$welcomePageEnterRoomInputContainerPadding: 0 8px 5px 0px;
$welcomePageEnterRoomInputContainerBorderWidth: 0px 0px 2px 0px;
$welcomePageEnterRoomInputContainerBorderStyle: solid;
$welcomePageEnterRoomInputContainerBorderImage: linear-gradient(to right, #dee1e6, #fff) 1;
$welcomePageEnterRoomTitleDisplay: inherit;
$welcomePageTabContainerDisplay: flex;
$welcomePageTabContentDisplay: inherit;
$welcomePageTabButtonsDisplay: flex;
$welcomePageTabDisplay: block;
$welcomePageButtonWidth: 51px;
$welcomePageButtonHeight: 35px;
$welcomePageButtonFontWeight: inherit;
$welcomePageButtonBorderRadius: 4px;
$welcomePageButtonLineHeight: 35px;
/**
* Deep-linking page variables.
*/

View File

@@ -4,7 +4,7 @@ body.welcome-page {
}
.welcome {
background-image: $welcomePageHeaderBackground;
background-image: $welcomePageBackground;
display: flex;
flex-direction: column;
font-family: $welcomePageFontFamily;
@@ -13,6 +13,11 @@ body.welcome-page {
position: relative;
.header {
background-image: $welcomePageHeaderBackground;
background-position: $welcomePageHeaderBackgroundPosition;
background-repeat: $welcomePageHeaderBackgroundRepeat;
background-size: $welcomePageHeaderBackgroundSize;
padding-bottom: $welcomePageHeaderPaddingBottom;
align-items: center;
display: flex;
flex-direction: column;
@@ -24,8 +29,8 @@ body.welcome-page {
.header-text {
display: flex;
flex-direction: column;
margin-top: $watermarkHeight + 35;
margin-bottom: 35px;
margin-top: $watermarkHeight + $welcomePageHeaderTextMarginTop;
margin-bottom: $welcomePageHeaderTextMarginBottom;
max-width: calc(100% - 40px);
width: 650px;
z-index: $zindex2;
@@ -36,10 +41,11 @@ body.welcome-page {
font-size: 2.5rem;
font-weight: 500;
line-height: 1.18;
margin-bottom: 16px;
margin-bottom: $welcomePageHeaderTextTitleMarginBottom;
}
.header-text-description {
display: $welcomePageHeaderTextDescriptionDisplay;
color: $welcomePageDescriptionColor;
font-size: 1rem;
font-weight: 400;
@@ -51,23 +57,24 @@ body.welcome-page {
display: flex;
align-items: center;
max-width: calc(100% - 40px);
width: 680px;
width: $welcomePageEnterRoomWidth;
z-index: $zindex2;
background-color: #fff;
padding: 25px 30px;
padding: $welcomePageEnterRoomPadding;
border-radius: $welcomePageEnterRoomBorderRadius;
.enter-room-input-container {
width: 100%;
padding-right: 8px;
padding-bottom: 5px;
padding: $welcomePageEnterRoomInputContainerPadding;
text-align: left;
color: #253858;
height: fit-content;
border-width: 0px 0px 2px 0px;
border-style: solid;
border-image: linear-gradient(to right, #dee1e6, #fff) 1;
border-width: $welcomePageEnterRoomInputContainerBorderWidth;
border-style: $welcomePageEnterRoomInputContainerBorderStyle;
border-image: $welcomePageEnterRoomInputContainerBorderImage;
.enter-room-title {
display: $welcomePageEnterRoomTitleDisplay;
font-size: 18px;
font-weight: bold;
padding-bottom: 5px;
@@ -94,10 +101,11 @@ body.welcome-page {
min-height: 354px;
width: 710px;
background: #75A7E7;
display: flex;
display: $welcomePageTabContainerDisplay;
flex-direction: column;
.tab-content{
display: $welcomePageTabContentDisplay;
margin: 5px 0px;
overflow: hidden;
flex-grow: 1;
@@ -111,13 +119,14 @@ body.welcome-page {
.tab-buttons {
font-size: 18px;
color: #FFFFFF;
display: flex;
display: $welcomePageTabButtonsDisplay;
flex-grow: 0;
flex-direction: row;
min-height: 54px;
width: 100%;
.tab {
display: $welcomePageTabDisplay;
text-align: center;
background: rgba(9,30,66,0.37);
height: 55px;
@@ -138,15 +147,16 @@ body.welcome-page {
}
.welcome-page-button {
width: 51px;
height: 35px;
width: $welcomePageButtonWidth;
height: $welcomePageButtonHeight;
font-size: 14px;
font-weight: $welcomePageButtonFontWeight;
background: #0074E0;
border-radius: 4px;
border-radius: $welcomePageButtonBorderRadius;
color: #FFFFFF;
text-align: center;
vertical-align: middle;
line-height: 35px;
line-height: $welcomePageButtonLineHeight;
cursor: pointer;
}

View File

@@ -0,0 +1 @@
/** Insert custom CSS for any additional content in the welcome page settings toolbar **/

View File

@@ -32,6 +32,7 @@ $flagsImagePath: "../images/";
@import 'overlay/overlay';
@import 'inlay';
@import 'reload_overlay/reload_overlay';
@import 'mini_toolbox';
@import 'modals/desktop-picker/desktop-picker';
@import 'modals/device-selection/device-selection';
@import 'modals/dialog';
@@ -51,6 +52,7 @@ $flagsImagePath: "../images/";
@import 'ringing/ringing';
@import 'welcome_page';
@import 'welcome_page_content';
@import 'welcome_page_settings_toolbar';
@import 'toolbars';
@import 'jquery.contextMenu';
@import 'keyboard-shortcuts';

View File

@@ -63,6 +63,8 @@
width: -webkit-max-content;
word-break: break-all;
max-width: 400px;
display: flex;
align-items: center;
}
.info-dialog-dial-in {
@@ -86,6 +88,15 @@
cursor: inherit;
}
.info-dialog-url-icon {
display: inline-block;
margin-left: 5px;
svg {
cursor: pointer;
}
}
.info-dialog-title {
font-weight: bold;
margin-bottom: 10px;
@@ -214,4 +225,10 @@
-moz-user-select: text;
-webkit-user-select: text;
}
.info-dialog-url-text-unselectable {
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
}
}

View File

@@ -19,29 +19,37 @@ server {
ssl_certificate_key /etc/jitsi/meet/jitsi-meet.example.com.key;
root /usr/share/jitsi-meet;
ssi on;
index index.html index.htm;
error_page 404 /static/404.html;
location /config.js {
location = /config.js {
alias /etc/jitsi/meet/jitsi-meet.example.com-config.js;
}
location /external_api.js {
location = /external_api.js {
alias /usr/share/jitsi-meet/libs/external_api.min.js;
}
location ~ ^/([a-zA-Z0-9=\?]+)$ {
rewrite ^/(.*)$ / break;
}
location / {
ssi on;
#ensure all static content can always be found first
location ~ ^/(libs|css|static|images|fonts|lang|sounds|connection_optimization|.well-known)/(.*)$
{
add_header 'Access-Control-Allow-Origin' '*';
alias /usr/share/jitsi-meet/$1/$2;
}
# BOSH
location /http-bind {
location = /http-bind {
proxy_pass http://localhost:5280/http-bind;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
}
location ~ ^/([^?&:’“]+)$ {
try_files $uri @root_path;
}
location @root_path {
rewrite ^/(.*)$ / break;
}
}

78
doc/development.md Normal file
View File

@@ -0,0 +1,78 @@
# 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 `beta.meet.jit.si`. 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/

View File

@@ -148,6 +148,7 @@
<!--#include virtual="title.html" -->
<!--#include virtual="plugin.head.html" -->
<!--#include virtual="static/welcomePageAdditionalContent.html" -->
<!--#include virtual="static/settingsToolbarAdditionalContent.html" -->
</head>
<body>
<div id="react"></div>

View File

@@ -27,6 +27,7 @@ var interfaceConfig = {
SHOW_DEEP_LINKING_IMAGE: false,
GENERATE_ROOMNAMES_ON_WELCOME_PAGE: true,
DISPLAY_WELCOME_PAGE_CONTENT: true,
DISPLAY_WELCOME_PAGE_TOOLBAR_ADDITIONAL_CONTENT: false,
APP_NAME: 'Jitsi Meet',
NATIVE_APP_NAME: 'Jitsi Meet',
PROVIDER_NAME: 'Jitsi',
@@ -50,7 +51,7 @@ var interfaceConfig = {
'fodeviceselection', 'hangup', 'profile', 'info', 'chat', 'recording',
'livestreaming', 'etherpad', 'sharedvideo', 'settings', 'raisehand',
'videoquality', 'filmstrip', 'invite', 'feedback', 'stats', 'shortcuts',
'tileview', 'videobackgroundblur'
'tileview', 'videobackgroundblur', 'download', 'help'
],
SETTINGS_SECTIONS: [ 'devices', 'language', 'moderator', 'profile', 'calendar' ],
@@ -221,6 +222,13 @@ var interfaceConfig = {
* milliseconds, those notifications should remain displayed.
*/
// ENFORCE_NOTIFICATION_AUTO_DISMISS_TIMEOUT: 15000,
// List of undocumented settings
/**
INDICATOR_FONT_SIZES
MOBILE_DYNAMIC_LINK
PHONE_NUMBER_REGEX
*/
};
/* eslint-enable no-unused-vars, no-var, max-len */

View File

@@ -17,9 +17,20 @@ target 'JitsiMeet' do
# React Native and its dependencies
#
pod 'FBLazyVector', :path => '../node_modules/react-native/Libraries/FBLazyVector/'
pod 'FBReactNativeSpec', :path => '../node_modules/react-native/Libraries/FBReactNativeSpec/'
pod 'RCTRequired', :path => '../node_modules/react-native/Libraries/RCTRequired/'
pod 'RCTTypeSafety', :path => '../node_modules/react-native/Libraries/TypeSafety/'
pod 'React', :path => '../node_modules/react-native/'
pod 'React-Core', :path => '../node_modules/react-native/React'
pod 'React-DevSupport', :path => '../node_modules/react-native/React'
pod 'ReactCommon', :path => '../node_modules/react-native/ReactCommon', :subspecs => [
'turbomodule'
]
pod 'React-Core', :path => '../node_modules/react-native/', :subspecs => [
'CoreModulesHeaders',
'DevSupport',
'RCTWebSocket'
]
pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
@@ -29,13 +40,12 @@ target 'JitsiMeet' do
pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
pod 'React-RCTWebSocket', :path => '../node_modules/react-native/Libraries/WebSocket'
pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
@@ -52,7 +62,7 @@ target 'JitsiMeet' do
pod 'react-native-webrtc', :path => '../node_modules/react-native-webrtc'
pod 'BVLinearGradient', :path => '../node_modules/react-native-linear-gradient'
pod 'RNCAsyncStorage', :path => '../node_modules/@react-native-community/async-storage'
pod 'RNGoogleSignin', :path => '../node_modules/react-native-google-signin'
pod 'RNGoogleSignin', :path => '../node_modules/@react-native-community/google-signin'
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'
@@ -71,6 +81,7 @@ post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'YES'
config.build_settings['SUPPORTS_MACCATALYST'] = 'NO'
end
end
end

View File

@@ -1,5 +1,10 @@
PODS:
- Amplitude-iOS (4.0.4)
- AppAuth (1.2.0):
- AppAuth/Core (= 1.2.0)
- AppAuth/ExternalUserAgent (= 1.2.0)
- AppAuth/Core (1.2.0)
- AppAuth/ExternalUserAgent (1.2.0)
- boost-for-react-native (1.63.0)
- BVLinearGradient (2.5.6):
- React
@@ -10,6 +15,14 @@ PODS:
- Fabric (~> 1.9.0)
- DoubleConversion (1.1.6)
- Fabric (1.9.0)
- FBLazyVector (0.61.1)
- FBReactNativeSpec (0.61.1):
- Folly (= 2018.10.22.00)
- RCTRequired (= 0.61.1)
- RCTTypeSafety (= 0.61.1)
- React-Core (= 0.61.1)
- React-jsi (= 0.61.1)
- ReactCommon/turbomodule/core (= 0.61.1)
- Firebase/Core (5.18.0):
- Firebase/CoreOnly
- FirebaseAnalytics (= 5.7.0)
@@ -54,18 +67,10 @@ PODS:
- GoogleUtilities/Network (~> 5.2)
- "GoogleUtilities/NSData+zlib (~> 5.2)"
- nanopb (~> 0.3)
- GoogleSignIn (4.4.0):
- "GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)"
- "GoogleToolboxForMac/NSString+URLArguments (~> 2.1)"
- GoogleSignIn (5.0.1):
- AppAuth (~> 1.2)
- GTMAppAuth (~> 1.0)
- GTMSessionFetcher/Core (~> 1.1)
- GoogleToolboxForMac/DebugUtils (2.2.0):
- GoogleToolboxForMac/Defines (= 2.2.0)
- GoogleToolboxForMac/Defines (2.2.0)
- "GoogleToolboxForMac/NSDictionary+URLArguments (2.2.0)":
- GoogleToolboxForMac/DebugUtils (= 2.2.0)
- GoogleToolboxForMac/Defines (= 2.2.0)
- "GoogleToolboxForMac/NSString+URLArguments (= 2.2.0)"
- "GoogleToolboxForMac/NSString+URLArguments (2.2.0)"
- GoogleUtilities/AppDelegateSwizzler (5.4.1):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
@@ -84,58 +89,183 @@ PODS:
- GoogleUtilities/Logger
- GoogleUtilities/UserDefaults (5.4.1):
- GoogleUtilities/Logger
- GTMSessionFetcher/Core (1.2.1)
- GTMAppAuth (1.0.0):
- AppAuth/Core (~> 1.0)
- GTMSessionFetcher (~> 1.1)
- GTMSessionFetcher (1.2.2):
- GTMSessionFetcher/Full (= 1.2.2)
- GTMSessionFetcher/Core (1.2.2)
- GTMSessionFetcher/Full (1.2.2):
- GTMSessionFetcher/Core (= 1.2.2)
- nanopb (0.3.901):
- nanopb/decode (= 0.3.901)
- nanopb/encode (= 0.3.901)
- nanopb/decode (0.3.901)
- nanopb/encode (0.3.901)
- ObjectiveDropboxOfficial (3.9.4)
- React (0.60.5):
- React-Core (= 0.60.5)
- React-DevSupport (= 0.60.5)
- React-RCTActionSheet (= 0.60.5)
- React-RCTAnimation (= 0.60.5)
- React-RCTBlob (= 0.60.5)
- React-RCTImage (= 0.60.5)
- React-RCTLinking (= 0.60.5)
- React-RCTNetwork (= 0.60.5)
- React-RCTSettings (= 0.60.5)
- React-RCTText (= 0.60.5)
- React-RCTVibration (= 0.60.5)
- React-RCTWebSocket (= 0.60.5)
- React-Core (0.60.5):
- RCTRequired (0.61.1)
- RCTTypeSafety (0.61.1):
- FBLazyVector (= 0.61.1)
- Folly (= 2018.10.22.00)
- React-cxxreact (= 0.60.5)
- React-jsiexecutor (= 0.60.5)
- yoga (= 0.60.5.React)
- React-cxxreact (0.60.5):
- RCTRequired (= 0.61.1)
- React-Core (= 0.61.1)
- React (0.61.1):
- React-Core (= 0.61.1)
- React-Core/DevSupport (= 0.61.1)
- React-Core/RCTWebSocket (= 0.61.1)
- React-RCTActionSheet (= 0.61.1)
- React-RCTAnimation (= 0.61.1)
- React-RCTBlob (= 0.61.1)
- React-RCTImage (= 0.61.1)
- React-RCTLinking (= 0.61.1)
- React-RCTNetwork (= 0.61.1)
- React-RCTSettings (= 0.61.1)
- React-RCTText (= 0.61.1)
- React-RCTVibration (= 0.61.1)
- React-Core (0.61.1):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default (= 0.61.1)
- React-cxxreact (= 0.61.1)
- React-jsi (= 0.61.1)
- React-jsiexecutor (= 0.61.1)
- Yoga
- React-Core/CoreModulesHeaders (0.61.1):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.1)
- React-jsi (= 0.61.1)
- React-jsiexecutor (= 0.61.1)
- Yoga
- React-Core/Default (0.61.1):
- Folly (= 2018.10.22.00)
- glog
- React-cxxreact (= 0.61.1)
- React-jsi (= 0.61.1)
- React-jsiexecutor (= 0.61.1)
- Yoga
- React-Core/DevSupport (0.61.1):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default (= 0.61.1)
- React-Core/RCTWebSocket (= 0.61.1)
- React-cxxreact (= 0.61.1)
- React-jsi (= 0.61.1)
- React-jsiexecutor (= 0.61.1)
- React-jsinspector (= 0.61.1)
- Yoga
- React-Core/RCTActionSheetHeaders (0.61.1):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.1)
- React-jsi (= 0.61.1)
- React-jsiexecutor (= 0.61.1)
- Yoga
- React-Core/RCTAnimationHeaders (0.61.1):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.1)
- React-jsi (= 0.61.1)
- React-jsiexecutor (= 0.61.1)
- Yoga
- React-Core/RCTBlobHeaders (0.61.1):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.1)
- React-jsi (= 0.61.1)
- React-jsiexecutor (= 0.61.1)
- Yoga
- React-Core/RCTImageHeaders (0.61.1):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.1)
- React-jsi (= 0.61.1)
- React-jsiexecutor (= 0.61.1)
- Yoga
- React-Core/RCTLinkingHeaders (0.61.1):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.1)
- React-jsi (= 0.61.1)
- React-jsiexecutor (= 0.61.1)
- Yoga
- React-Core/RCTNetworkHeaders (0.61.1):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.1)
- React-jsi (= 0.61.1)
- React-jsiexecutor (= 0.61.1)
- Yoga
- React-Core/RCTSettingsHeaders (0.61.1):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.1)
- React-jsi (= 0.61.1)
- React-jsiexecutor (= 0.61.1)
- Yoga
- React-Core/RCTTextHeaders (0.61.1):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.1)
- React-jsi (= 0.61.1)
- React-jsiexecutor (= 0.61.1)
- Yoga
- React-Core/RCTVibrationHeaders (0.61.1):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.1)
- React-jsi (= 0.61.1)
- React-jsiexecutor (= 0.61.1)
- Yoga
- React-Core/RCTWebSocket (0.61.1):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default (= 0.61.1)
- React-cxxreact (= 0.61.1)
- React-jsi (= 0.61.1)
- React-jsiexecutor (= 0.61.1)
- Yoga
- React-CoreModules (0.61.1):
- FBReactNativeSpec (= 0.61.1)
- Folly (= 2018.10.22.00)
- RCTTypeSafety (= 0.61.1)
- React-Core/CoreModulesHeaders (= 0.61.1)
- React-RCTImage (= 0.61.1)
- ReactCommon/turbomodule/core (= 0.61.1)
- React-cxxreact (0.61.1):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-jsinspector (= 0.60.5)
- React-DevSupport (0.60.5):
- React-Core (= 0.60.5)
- React-RCTWebSocket (= 0.60.5)
- React-jsi (0.60.5):
- React-jsinspector (= 0.61.1)
- React-jsi (0.61.1):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-jsi/Default (= 0.60.5)
- React-jsi/Default (0.60.5):
- React-jsi/Default (= 0.61.1)
- React-jsi/Default (0.61.1):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-jsiexecutor (0.60.5):
- React-jsiexecutor (0.61.1):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-cxxreact (= 0.60.5)
- React-jsi (= 0.60.5)
- React-jsinspector (0.60.5)
- React-cxxreact (= 0.61.1)
- React-jsi (= 0.61.1)
- React-jsinspector (0.61.1)
- react-native-background-timer (2.1.1):
- React
- react-native-calendar-events (1.7.3):
@@ -146,35 +276,66 @@ PODS:
- React
- react-native-webrtc (1.75.0):
- React
- react-native-webview (5.8.1):
- react-native-webview (7.4.1):
- React
- React-RCTActionSheet (0.60.5):
- React-Core (= 0.60.5)
- React-RCTAnimation (0.60.5):
- React-Core (= 0.60.5)
- React-RCTBlob (0.60.5):
- React-Core (= 0.60.5)
- React-RCTNetwork (= 0.60.5)
- React-RCTWebSocket (= 0.60.5)
- React-RCTImage (0.60.5):
- React-Core (= 0.60.5)
- React-RCTNetwork (= 0.60.5)
- React-RCTLinking (0.60.5):
- React-Core (= 0.60.5)
- React-RCTNetwork (0.60.5):
- React-Core (= 0.60.5)
- React-RCTSettings (0.60.5):
- React-Core (= 0.60.5)
- React-RCTText (0.60.5):
- React-Core (= 0.60.5)
- React-RCTVibration (0.60.5):
- React-Core (= 0.60.5)
- React-RCTWebSocket (0.60.5):
- React-Core (= 0.60.5)
- React-RCTActionSheet (0.61.1):
- React-Core/RCTActionSheetHeaders (= 0.61.1)
- React-RCTAnimation (0.61.1):
- React-Core/RCTAnimationHeaders (= 0.61.1)
- React-RCTBlob (0.61.1):
- React-Core/RCTBlobHeaders (= 0.61.1)
- React-Core/RCTWebSocket (= 0.61.1)
- React-jsi (= 0.61.1)
- React-RCTNetwork (= 0.61.1)
- React-RCTImage (0.61.1):
- React-Core/RCTImageHeaders (= 0.61.1)
- React-RCTNetwork (= 0.61.1)
- React-RCTLinking (0.61.1):
- React-Core/RCTLinkingHeaders (= 0.61.1)
- React-RCTNetwork (0.61.1):
- React-Core/RCTNetworkHeaders (= 0.61.1)
- React-RCTSettings (0.61.1):
- React-Core/RCTSettingsHeaders (= 0.61.1)
- React-RCTText (0.61.1):
- React-Core/RCTTextHeaders (= 0.61.1)
- React-RCTVibration (0.61.1):
- React-Core/RCTVibrationHeaders (= 0.61.1)
- ReactCommon/jscallinvoker (0.61.1):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-cxxreact (= 0.61.1)
- ReactCommon/turbomodule (0.61.1):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-Core (= 0.61.1)
- React-cxxreact (= 0.61.1)
- React-jsi (= 0.61.1)
- ReactCommon/jscallinvoker (= 0.61.1)
- ReactCommon/turbomodule/core (= 0.61.1)
- ReactCommon/turbomodule/samples (= 0.61.1)
- ReactCommon/turbomodule/core (0.61.1):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-Core (= 0.61.1)
- React-cxxreact (= 0.61.1)
- React-jsi (= 0.61.1)
- ReactCommon/jscallinvoker (= 0.61.1)
- ReactCommon/turbomodule/samples (0.61.1):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-Core (= 0.61.1)
- React-cxxreact (= 0.61.1)
- React-jsi (= 0.61.1)
- ReactCommon/jscallinvoker (= 0.61.1)
- ReactCommon/turbomodule/core (= 0.61.1)
- RNCAsyncStorage (1.3.4):
- React
- RNGoogleSignin (2.0.0):
- GoogleSignIn (~> 4.4.0)
- RNGoogleSignin (3.0.1):
- GoogleSignIn (~> 5.0.0)
- React
- RNSound (0.11.0):
- React
@@ -185,7 +346,7 @@ PODS:
- React
- RNWatch (0.2.0):
- React
- yoga (0.60.5.React)
- Yoga (1.14.0)
DEPENDENCIES:
- Amplitude-iOS (~> 4.0.4)
@@ -194,15 +355,21 @@ DEPENDENCIES:
- Crashlytics (~> 3.12.0)
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- Fabric (~> 1.9.0)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector/`)
- FBReactNativeSpec (from `../node_modules/react-native/Libraries/FBReactNativeSpec/`)
- Firebase/Core (~> 5.18.0)
- Firebase/DynamicLinks (~> 5.18.0)
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- ObjectiveDropboxOfficial (~> 3.9.4)
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired/`)
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety/`)
- React (from `../node_modules/react-native/`)
- React-Core (from `../node_modules/react-native/React`)
- React-Core/CoreModulesHeaders (from `../node_modules/react-native/`)
- React-Core/DevSupport (from `../node_modules/react-native/`)
- React-Core/RCTWebSocket (from `../node_modules/react-native/`)
- React-CoreModules (from `../node_modules/react-native/React/CoreModules`)
- React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`)
- React-DevSupport (from `../node_modules/react-native/React`)
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
@@ -221,16 +388,16 @@ DEPENDENCIES:
- React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`)
- React-RCTText (from `../node_modules/react-native/Libraries/Text`)
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
- React-RCTWebSocket (from `../node_modules/react-native/Libraries/WebSocket`)
- ReactCommon/turbomodule (from `../node_modules/react-native/ReactCommon`)
- "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)"
- RNGoogleSignin (from `../node_modules/react-native-google-signin`)
- "RNGoogleSignin (from `../node_modules/@react-native-community/google-signin`)"
- RNSound (from `../node_modules/react-native-sound`)
- RNSVG (from `../node_modules/react-native-svg`)
- RNWatch (from `../node_modules/react-native-watch-connectivity`)
- yoga (from `../node_modules/react-native/ReactCommon/yoga`)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
SPEC REPOS:
https://github.com/cocoapods/specs.git:
https://github.com/CocoaPods/Specs.git:
- Amplitude-iOS
- boost-for-react-native
- CocoaLumberjack
@@ -243,30 +410,40 @@ SPEC REPOS:
- FirebaseDynamicLinks
- FirebaseInstanceID
- GoogleAppMeasurement
- GoogleSignIn
- GoogleToolboxForMac
- GoogleUtilities
- GTMSessionFetcher
- nanopb
- ObjectiveDropboxOfficial
trunk:
- AppAuth
- GoogleSignIn
- GTMAppAuth
- GTMSessionFetcher
EXTERNAL SOURCES:
BVLinearGradient:
:path: "../node_modules/react-native-linear-gradient"
DoubleConversion:
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
FBLazyVector:
:path: "../node_modules/react-native/Libraries/FBLazyVector/"
FBReactNativeSpec:
:path: "../node_modules/react-native/Libraries/FBReactNativeSpec/"
Folly:
:podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec"
glog:
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
RCTRequired:
:path: "../node_modules/react-native/Libraries/RCTRequired/"
RCTTypeSafety:
:path: "../node_modules/react-native/Libraries/TypeSafety/"
React:
:path: "../node_modules/react-native/"
React-Core:
:path: "../node_modules/react-native/React"
:path: "../node_modules/react-native/"
React-CoreModules:
:path: "../node_modules/react-native/React/CoreModules"
React-cxxreact:
:path: "../node_modules/react-native/ReactCommon/cxxreact"
React-DevSupport:
:path: "../node_modules/react-native/React"
React-jsi:
:path: "../node_modules/react-native/ReactCommon/jsi"
React-jsiexecutor:
@@ -303,29 +480,32 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/Libraries/Text"
React-RCTVibration:
:path: "../node_modules/react-native/Libraries/Vibration"
React-RCTWebSocket:
:path: "../node_modules/react-native/Libraries/WebSocket"
ReactCommon:
:path: "../node_modules/react-native/ReactCommon"
RNCAsyncStorage:
:path: "../node_modules/@react-native-community/async-storage"
RNGoogleSignin:
:path: "../node_modules/react-native-google-signin"
:path: "../node_modules/@react-native-community/google-signin"
RNSound:
:path: "../node_modules/react-native-sound"
RNSVG:
:path: "../node_modules/react-native-svg"
RNWatch:
:path: "../node_modules/react-native-watch-connectivity"
yoga:
Yoga:
:path: "../node_modules/react-native/ReactCommon/yoga"
SPEC CHECKSUMS:
Amplitude-iOS: 2ad4d7270c99186236c1272a3a9425463b1ae1a7
AppAuth: bce82c76043657c99d91e7882e8a9e1a93650cd4
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
CocoaLumberjack: 2f44e60eb91c176d471fdba43b9e3eae6a721947
Crashlytics: 07fb167b1694128c1c9a5a5cc319b0e9c3ca0933
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
Fabric: f988e33c97f08930a413e08123064d2e5f68d655
FBLazyVector: 0846affdb2924b01093eb696766ecb0104e409e0
FBReactNativeSpec: c4cf958af1b97799b524f63a26a1c509c0295b04
Firebase: 02f3281965c075426141a0ce1277e9de6649cab9
FirebaseAnalytics: 23851fe602c872130a2c5c55040b302120346cc2
FirebaseAnalyticsInterop: efbe45c8385ec626e29f9525e5ebd38520dfb6c1
@@ -335,42 +515,44 @@ SPEC CHECKSUMS:
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
glog: 1f3da668190260b06b429bb211bfbee5cd790c28
GoogleAppMeasurement: 6cf307834da065863f9faf4c0de0a936d81dd832
GoogleSignIn: 7ff245e1a7b26d379099d3243a562f5747e23d39
GoogleToolboxForMac: ff31605b7d66400dcec09bed5861689aebadda4d
GoogleSignIn: 3a51b9bb8e48b635fd7f4272cee06ca260345b86
GoogleUtilities: 1e25823cbf46540b4284f6ef8e17b3a68ee12bbc
GTMSessionFetcher: 32aeca0aa144acea523e1c8e053089dec2cb98ca
GTMAppAuth: 4deac854479704f348309e7b66189e604cf5e01e
GTMSessionFetcher: 61bb0f61a4cb560030f1222021178008a5727a23
nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48
ObjectiveDropboxOfficial: a5afefc83f6467c42c45f2253f583f2ad1ffc701
React: 53c53c4d99097af47cf60594b8706b4e3321e722
React-Core: ba421f6b4f4cbe2fb17c0b6fc675f87622e78a64
React-cxxreact: 8384287780c4999351ad9b6e7a149d9ed10a2395
React-DevSupport: 197fb409737cff2c4f9986e77c220d7452cb9f9f
React-jsi: 4d8c9efb6312a9725b18d6fc818ffc103f60fec2
React-jsiexecutor: 90ad2f9db09513fc763bc757fdc3c4ff8bde2a30
React-jsinspector: e08662d1bf5b129a3d556eb9ea343a3f40353ae4
RCTRequired: 53825815218847d3e9c7b6d92ad2d197a926d51e
RCTTypeSafety: d886540c518e53064dfa081bf7693fd650699b92
React: 5dea58967c421bd1fdf6b94c18b9ed0f5134683c
React-Core: b381e65aa0da9b94b9dcdc4a99298075b1c3876c
React-CoreModules: 4ed224e29848ba76d26aacb8e3fe85712d3c4fe1
React-cxxreact: 52c98f5c1fb4e4d9f4b588742718350a55f4f088
React-jsi: 61ff417c95e6c3af50fb96399037e80752fb5ce7
React-jsiexecutor: ee45274419eb95614bbbadb98e20684c5f29996e
React-jsinspector: 574d597112f9ea3d1b717f6fb62aef764c70dd6f
react-native-background-timer: 0d34748e53a972507c66963490c775321a88f6f2
react-native-calendar-events: 2fe35a9294af05de0ed819d3a1b5dac048d2c010
react-native-keep-awake: eba3137546b10003361b37c761f6c429b59814ae
react-native-netinfo: 8d8db463bcc5db66a8ac5c48a7d86beb3b92f61a
react-native-webrtc: c5e3d631179a933548a8e49bddbd8fad02586095
react-native-webview: a95842e3f351a6d2c8bc8bcc9eab689c7e7e5ad4
React-RCTActionSheet: b0f1ea83f4bf75fb966eae9bfc47b78c8d3efd90
React-RCTAnimation: 359ba1b5690b1e87cc173558a78e82d35919333e
React-RCTBlob: 5e2b55f76e9a1c7ae52b826923502ddc3238df24
React-RCTImage: f5f1c50922164e89bdda67bcd0153952a5cfe719
React-RCTLinking: d0ecbd791e9ddddc41fa1f66b0255de90e8ee1e9
React-RCTNetwork: e26946300b0ab7bb6c4a6348090e93fa21f33a9d
React-RCTSettings: d0d37cb521b7470c998595a44f05847777cc3f42
React-RCTText: b074d89033583d4f2eb5faf7ea2db3a13c7553a2
React-RCTVibration: 2105b2e0e2b66a6408fc69a46c8a7fb5b2fdade0
React-RCTWebSocket: cd932a16b7214898b6b7f788c8bddb3637246ac4
react-native-webview: 4dbc1d2a4a6b9c5e9e723c62651917aa2b5e579e
React-RCTActionSheet: af4d951113b1e068bb30611f91b984a7a73597ff
React-RCTAnimation: 4f518d70bb6890b7c3d9d732f84786d6693ca297
React-RCTBlob: 072a4888c08de0eef6d04eaa727d25e577e6ff26
React-RCTImage: 78c5cdf1b2de6cd3cd650dd741868fad19a35528
React-RCTLinking: 486ed1c9a659c7f9fea213868f8930b9a0a79f07
React-RCTNetwork: e79599f3160b459da03447e32b8bcca1a0f0f797
React-RCTSettings: 48b7c5a64ffe0c54c39d59eb7d9036e72305f95a
React-RCTText: 81b62b4e7f11531a5154e4daa5617670d5a2d5de
React-RCTVibration: 8be61459e3749d1fb02cf414edd05b3007622882
ReactCommon: 4fba5be89efdf0b5720e0adb3d8d7edf6e532db0
RNCAsyncStorage: 8e31405a9f12fbf42c2bb330e4560bfd79c18323
RNGoogleSignin: d030c6c6591db24c3cee649f64c7babf0a1699a0
RNGoogleSignin: 39336070b35fc4cea6a98cf111e00480317be0ae
RNSound: c980916b596cc15c8dcd2f6ecd3b13c4881dbe20
RNSVG: aac12785382e8fd4f28d072fe640612e34914631
RNWatch: 09738b339eceb66e4d80a2371633ca5fb380fa42
yoga: 312528f5bbbba37b4dcea5ef00e8b4033fdd9411
Yoga: d8c572ddec8d05b7dba08e4e5f1924004a177078
PODFILE CHECKSUM: 86bb4d2bc94c6c76b971b9a33e5b2ced9bbfb09f
PODFILE CHECKSUM: cb84b325b724c6ef7c8b24aa52ca7b6f681a095c
COCOAPODS: 1.7.2
COCOAPODS: 1.8.1

View File

@@ -41,8 +41,6 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
@@ -52,8 +50,8 @@
ReferencedContainer = "container:app.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -75,8 +73,6 @@
ReferencedContainer = "container:app.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"

View File

@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>19.3.0</string>
<string>19.4.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>

View File

@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>19.3.0</string>
<string>19.4.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>UISupportedInterfaceOrientations</key>

View File

@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>19.3.0</string>
<string>19.4.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>CLKComplicationPrincipalClass</key>

103
ios/ci/build-ipa.sh Executable file
View File

@@ -0,0 +1,103 @@
#!/bin/bash
set -e
# Mandatory arguments with no default values provided:
# PR_REPO_SLUG - the Github name of the repo to be merged into the origin/master
# PR_BRANCH - the branch to be merged, if set to "master" no merge will happen
# IPA_DEPLOY_LOCATION - the location understandable by the "scp" command
# executed at the end of the script to deploy the output .ipa file
# LIB_JITSI_MEET_PKG (optional) - the npm package for lib-jitsi-meet which will
# be put in place of the current version in the package.json file.
#
# Other than that the script requires the following env variables to be set:
#
# DEPLOY_SSH_CERT_URL - the SSH private key used by the 'scp' command to deploy
# the .ipa. It is expected to be encrypted with the $ENCRYPTION_PASSWORD.
# ENCRYPTION_PASSWORD - the password used to decrypt certificate/key files used
# in the script.
# IOS_TEAM_ID - the team ID inserted into build-ipa-.plist.template file in
# place of "YOUR_TEAM_ID".
function echoAndExit1() {
echo $1
exit 1
}
if [ -z $PR_REPO_SLUG ]; then
echoAndExit1 "No PR_REPO_SLUG defined"
fi
if [ -z $PR_BRANCH ]; then
echoAndExit1 "No PR_BRANCH defined"
fi
if [ -z $IPA_DEPLOY_LOCATION ]; then
echoAndExit1 "No IPA_DEPLOY_LOCATION defined"
fi
echo "PR_REPO_SLUG=${PR_REPO_SLUG} PR_BRANCH=${PR_BRANCH}"
# do the marge and git log
if [ $PR_BRANCH != "master" ]; then
echo "Will merge ${PR_REPO_SLUG}/${PR_BRANCH} into master"
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
git fetch origin master
git checkout master
git pull https://github.com/${PR_REPO_SLUG}.git $PR_BRANCH --no-edit
fi
# Link this lib-jitsi-meet checkout in jitsi-meet through the package.json
if [ ! -z ${LIB_JITSI_MEET_PKG} ];
then
echo "Adjusting lib-jitsi-meet package in package.json to ${LIB_JITSI_MEET_PKG}"
# escape for the sed
LIB_JITSI_MEET_PKG=$(echo $LIB_JITSI_MEET_PKG | sed -e 's/\\/\\\\/g; s/\//\\\//g; s/&/\\\&/g')
sed -i.bak -e "s/\"lib-jitsi-meet.*/\"lib-jitsi-meet\"\: \"${LIB_JITSI_MEET_PKG}\",/g" package.json
echo "Package.json lib-jitsi-meet line:"
grep lib-jitsi-meet package.json
else
echo "LIB_JITSI_MEET_PKG var not set - will not modify the package.json"
fi
git log -20 --graph --pretty=format':%C(yellow)%h%Cblue%d%Creset %s %C(white) %an, %ar%Creset'
# certificates
CERT_DIR="ios/ci/certs"
mkdir -p $CERT_DIR
curl -L -o ${CERT_DIR}/id_rsa.enc ${DEPLOY_SSH_CERT_URL}
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/id_rsa.enc -d -a -out ${CERT_DIR}/id_rsa
chmod 0600 ${CERT_DIR}/id_rsa
ssh-add ${CERT_DIR}/id_rsa
npm install
# Ever since the Apple Watch app has been added the bitcode for WebRTC needs to be downloaded in order to build successfully
./node_modules/react-native-webrtc/tools/downloadBitcode.sh
cd ios
pod install --repo-update --no-ansi
cd ..
mkdir -p /tmp/jitsi-meet/
xcodebuild archive -quiet -workspace ios/jitsi-meet.xcworkspace -scheme jitsi-meet -configuration Release -archivePath /tmp/jitsi-meet/jitsi-meet.xcarchive
sed -e "s/YOUR_TEAM_ID/${IOS_TEAM_ID}/g" ios/ci/build-ipa.plist.template > ios/ci/build-ipa.plist
IPA_EXPORT_DIR=/tmp/jitsi-meet/jitsi-meet-ipa
xcodebuild -quiet -exportArchive -archivePath /tmp/jitsi-meet/jitsi-meet.xcarchive -exportPath $IPA_EXPORT_DIR -exportOptionsPlist ios/ci/build-ipa.plist
echo "Will try deploy the .ipa to: ${IPA_DEPLOY_LOCATION}"
if [ ! -z ${SCP_PROXY_HOST} ];
then
scp -o ProxyCommand="ssh -t -A -l %r ${SCP_PROXY_HOST} -o \"StrictHostKeyChecking no\" -o \"BatchMode yes\" -W %h:%p" -o StrictHostKeyChecking=no -o LogLevel=DEBUG "${IPA_EXPORT_DIR}/jitsi-meet.ipa" "${IPA_DEPLOY_LOCATION}"
else
scp -o StrictHostKeyChecking=no -o LogLevel=DEBUG "${IPA_EXPORT_DIR}/jitsi-meet.ipa" "${IPA_DEPLOY_LOCATION}"
fi
rm -r /tmp/jitsi-meet/
rm -r $CERT_DIR

100
ios/ci/setup-certificates.sh Executable file
View File

@@ -0,0 +1,100 @@
# The script is based on tutorial written by Antonis Tsakiridis published at:
# https://medium.com/@atsakiridis/continuous-deployment-for-ios-using-travis-ci-55dcea342d9
#
# APPLE_CERT_URL - the URL pointing to Apple certificate (set to
# http://developer.apple.com/certificationauthority/AppleWWDRCA.cer by default)
# DEPLOY_SSH_CERT_URL - the SSH private key used by the 'scp' command to deploy
# the .ipa. It is expected to be encrypted with the $ENCRYPTION_PASSWORD.
# ENCRYPTION_PASSWORD - the password used to decrypt certificate/key files used
# in the script.
# IOS_DEV_CERT_KEY_URL - URL pointing to provisioning profile certificate key
# file (development-key.p12.enc from the tutorial) encrypted with the
# $ENCRYPTION_PASSWORD.
# IOS_DEV_CERT_URL - URL pointing to provisioning profile certificate file
# (development-cert.cer.enc from the tutorial) encrypted with the
# $ENCRYPTION_PASSWORD.
# IOS_DEV_PROV_PROFILE_URL - URL pointing to provisioning profile file
# (profile-development-olympus.mobileprovision.enc from the tutorial) encrypted
# IOS_DEV_WATCH_PROV_PROFILE_URL - URL pointing to watch app provisioning profile file(encrypted).
# with the $ENCRYPTION_PASSWORD.
# IOS_SIGNING_CERT_PASSWORD - the password to the provisioning profile
# certificate key (used to open development-key.p12 from the tutorial).
function echoAndExit1() {
echo $1
exit 1
}
CERT_DIR=$1
if [ -z $CERT_DIR ]; then
echoAndExit1 "First argument must be certificates directory"
fi
if [ -z $APPLE_CERT_URL ]; then
APPLE_CERT_URL="http://developer.apple.com/certificationauthority/AppleWWDRCA.cer"
fi
if [ -z $DEPLOY_SSH_CERT_URL ]; then
echoAndExit1 "DEPLOY_SSH_CERT_URL env var is not defined"
fi
if [ -z $ENCRYPTION_PASSWORD ]; then
echoAndExit1 "ENCRYPTION_PASSWORD env var is not defined"
fi
if [ -z $IOS_DEV_CERT_KEY_URL ]; then
echoAndExit1 "IOS_DEV_CERT_KEY_URL env var is not defined"
fi
if [ -z $IOS_DEV_CERT_URL ]; then
echoAndExit1 "IOS_DEV_CERT_URL env var is not defined"
fi
if [ -z $IOS_DEV_PROV_PROFILE_URL ]; then
echoAndExit1 "IOS_DEV_PROV_PROFILE_URL env var is not defined"
fi
if [ -z $IOS_DEV_WATCH_PROV_PROFILE_URL ]; then
echoAndExit1 "IOS_DEV_WATCH_PROV_PROFILE_URL env var is not defined"
fi
if [ -z $IOS_SIGNING_CERT_PASSWORD ]; then
echoAndExit1 "IOS_SIGNING_CERT_PASSWORD env var is not defined"
fi
# certificates
curl -L -o ${CERT_DIR}/AppleWWDRCA.cer 'http://developer.apple.com/certificationauthority/AppleWWDRCA.cer'
curl -L -o ${CERT_DIR}/dev-cert.cer.enc ${IOS_DEV_CERT_URL}
curl -L -o ${CERT_DIR}/dev-key.p12.enc ${IOS_DEV_CERT_KEY_URL}
curl -L -o ${CERT_DIR}/dev-profile.mobileprovision.enc ${IOS_DEV_PROV_PROFILE_URL}
curl -L -o ${CERT_DIR}/dev-watch-profile.mobileprovision.enc ${IOS_DEV_WATCH_PROV_PROFILE_URL}
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/dev-cert.cer.enc -d -a -out ${CERT_DIR}/dev-cert.cer
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/dev-key.p12.enc -d -a -out ${CERT_DIR}/dev-key.p12
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/dev-profile.mobileprovision.enc -d -a -out ${CERT_DIR}/dev-profile.mobileprovision
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/dev-watch-profile.mobileprovision.enc -d -a -out ${CERT_DIR}/dev-watch-profile.mobileprovision
security create-keychain -p $ENCRYPTION_PASSWORD ios-build.keychain
security default-keychain -s ios-build.keychain
security unlock-keychain -p $ENCRYPTION_PASSWORD ios-build.keychain
security set-keychain-settings -t 3600 -l ~/Library/Keychains/ios-build.keychain
echo "importing Apple cert"
security import ${CERT_DIR}/AppleWWDRCA.cer -k ios-build.keychain -A
echo "importing dev-cert.cer"
security import ${CERT_DIR}/dev-cert.cer -k ios-build.keychain -A
echo "importing dev-key.p12"
security import ${CERT_DIR}/dev-key.p12 -k ios-build.keychain -P $IOS_SIGNING_CERT_PASSWORD -A
echo "will set-key-partition-list"
# Fix for OS X Sierra that hungs in the codesign step
security set-key-partition-list -S apple-tool:,apple: -s -k $ENCRYPTION_PASSWORD ios-build.keychain > /dev/null
echo "done set-key-partition-list"
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp "${CERT_DIR}/dev-profile.mobileprovision" ~/Library/MobileDevice/Provisioning\ Profiles/
cp "${CERT_DIR}/dev-watch-profile.mobileprovision" ~/Library/MobileDevice/Provisioning\ Profiles/

View File

@@ -42,6 +42,7 @@
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 */; };
DE438CDA2350934700DD541D /* JavaScriptSandbox.m in Sources */ = {isa = PBXBuildFile; fileRef = DE438CD82350934700DD541D /* JavaScriptSandbox.m */; };
DE65AACA2317FFCD00290BEC /* LogUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AAC92317FFCD00290BEC /* LogUtils.h */; };
DE65AACC2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */; };
DE762DB422AFDE76000DEBD6 /* JitsiMeetUserInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DE762DB322AFDE76000DEBD6 /* JitsiMeetUserInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -104,6 +105,7 @@
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>"; };
DE438CD82350934700DD541D /* JavaScriptSandbox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JavaScriptSandbox.m; sourceTree = "<group>"; };
DE65AAC92317FFCD00290BEC /* LogUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LogUtils.h; sourceTree = "<group>"; };
DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetBaseLogHandler+Private.h"; sourceTree = "<group>"; };
DE762DB322AFDE76000DEBD6 /* JitsiMeetUserInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeetUserInfo.h; sourceTree = "<group>"; };
@@ -190,6 +192,7 @@
A4A934E7212F3AB8001E9388 /* dropbox */,
0BA13D301EE83FF8007BEF7F /* ExternalAPI.m */,
0BD906E91EC0C00300C8C18E /* Info.plist */,
DE438CD82350934700DD541D /* JavaScriptSandbox.m */,
0BD906E81EC0C00300C8C18E /* JitsiMeet.h */,
DEFE535821FB311F00011A3A /* JitsiMeet+Private.h */,
DEFE535321FB1BF800011A3A /* JitsiMeet.m */,
@@ -493,6 +496,7 @@
C69EFA0E209A0F660027712B /* JMCallKitListener.swift in Sources */,
0B412F191EDEC65D00B1A0A6 /* JitsiMeetView.m in Sources */,
DEFE535421FB1BF800011A3A /* JitsiMeet.m in Sources */,
DE438CDA2350934700DD541D /* JavaScriptSandbox.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -634,15 +638,18 @@
ENABLE_BITCODE = NO;
INFOPLIST_FILE = src/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.JitsiMeetSDK.ios;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SUPPORTS_MACCATALYST = NO;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
@@ -662,14 +669,17 @@
ENABLE_BITCODE = YES;
INFOPLIST_FILE = src/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.JitsiMeetSDK.ios;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SUPPORTS_MACCATALYST = NO;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};

View File

@@ -81,7 +81,7 @@
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
<ActionContent
title = "Run Script"
scriptText = "exec &gt; /tmp/${PROJECT_NAME}_archive.log 2&gt;&amp;1&#10;&#10;UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal&#10;&#10;if [ &quot;true&quot; == ${ALREADYINVOKED:-false} ]&#10;then&#10;echo &quot;RECURSION: Detected, stopping&quot;&#10;else&#10;export ALREADYINVOKED=&quot;true&quot;&#10;&#10;# make sure the output directory exists&#10;mkdir -p &quot;${UNIVERSAL_OUTPUTFOLDER}&quot;&#10;&#10;echo &quot;Building for iPhoneSimulator&quot;&#10;xcodebuild -workspace &quot;${WORKSPACE_PATH}&quot; -scheme &quot;${TARGET_NAME}&quot; -configuration ${CONFIGURATION} -sdk iphonesimulator -destination &apos;platform=iOS Simulator,name=iPhone 6&apos; ONLY_ACTIVE_ARCH=NO ARCHS=&apos;i386 x86_64&apos; BUILD_DIR=&quot;${BUILD_DIR}&quot; BUILD_ROOT=&quot;${BUILD_ROOT}&quot; ENABLE_BITCODE=YES OTHER_CFLAGS=&quot;-fembed-bitcode&quot; BITCODE_GENERATION_MODE=bitcode clean build&#10;&#10;# Step 1. Copy the framework structure (from iphoneos build) to the universal folder&#10;echo &quot;Copying to output folder&quot;&#10;cp -R &quot;${BUILD_DIR}/${CONFIGURATION}-iphoneos/${FULL_PRODUCT_NAME}&quot; &quot;${UNIVERSAL_OUTPUTFOLDER}/&quot;&#10;&#10;# Step 2. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory&#10;SIMULATOR_SWIFT_MODULES_DIR=&quot;${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/Modules/${TARGET_NAME}.swiftmodule/.&quot;&#10;if [ -d &quot;${SIMULATOR_SWIFT_MODULES_DIR}&quot; ]; then&#10;cp -R &quot;${SIMULATOR_SWIFT_MODULES_DIR}&quot; &quot;${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Modules/${TARGET_NAME}.swiftmodule&quot;&#10;fi&#10;&#10;# Step 3. Create universal binary file using lipo and place the combined executable in the copied framework directory&#10;echo &quot;Combining executables&quot;&#10;lipo -create -output &quot;${UNIVERSAL_OUTPUTFOLDER}/${EXECUTABLE_PATH}&quot; &quot;${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${EXECUTABLE_PATH}&quot; &quot;${BUILD_DIR}/${CONFIGURATION}-iphoneos/${EXECUTABLE_PATH}&quot;&#10;&#10;# Step 4. Create universal binaries for embedded frameworks&#10;#for SUB_FRAMEWORK in $( ls &quot;${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Frameworks&quot; ); do&#10;#BINARY_NAME=&quot;${SUB_FRAMEWORK%.*}&quot;&#10;#lipo -create -output &quot;${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}&quot; &quot;${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${SUB_FRAMEWORK}/${BINARY_NAME}&quot; &quot;${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/${TARGET_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}&quot;&#10;#done&#10;&#10;# Step 5. Convenience step to copy the framework to the project&apos;s directory&#10;echo &quot;Copying to project dir&quot;&#10;yes | cp -Rf &quot;${UNIVERSAL_OUTPUTFOLDER}/${FULL_PRODUCT_NAME}&quot; &quot;${PROJECT_DIR}&quot;&#10;&#10;fi">
scriptText = "exec &gt; /tmp/${PROJECT_NAME}_archive.log 2&gt;&amp;1&#10;&#10;UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal&#10;&#10;if [ &quot;true&quot; == ${ALREADYINVOKED:-false} ]&#10;then&#10;echo &quot;RECURSION: Detected, stopping&quot;&#10;else&#10;export ALREADYINVOKED=&quot;true&quot;&#10;&#10;# make sure the output directory exists&#10;mkdir -p &quot;${UNIVERSAL_OUTPUTFOLDER}&quot;&#10;&#10;echo &quot;Building for iPhoneSimulator&quot;&#10;xcodebuild -workspace &quot;${WORKSPACE_PATH}&quot; -scheme &quot;${TARGET_NAME}&quot; -configuration ${CONFIGURATION} -sdk iphonesimulator -destination &apos;platform=iOS Simulator,name=iPhone 8&apos; ONLY_ACTIVE_ARCH=NO ARCHS=&apos;i386 x86_64&apos; BUILD_DIR=&quot;${BUILD_DIR}&quot; BUILD_ROOT=&quot;${BUILD_ROOT}&quot; ENABLE_BITCODE=YES OTHER_CFLAGS=&quot;-fembed-bitcode&quot; BITCODE_GENERATION_MODE=bitcode clean build&#10;&#10;# Step 1. Copy the framework structure (from iphoneos build) to the universal folder&#10;echo &quot;Copying to output folder&quot;&#10;cp -R &quot;${BUILD_DIR}/${CONFIGURATION}-iphoneos/${FULL_PRODUCT_NAME}&quot; &quot;${UNIVERSAL_OUTPUTFOLDER}/&quot;&#10;&#10;# Step 2. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory&#10;SIMULATOR_SWIFT_MODULES_DIR=&quot;${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/Modules/${TARGET_NAME}.swiftmodule/.&quot;&#10;if [ -d &quot;${SIMULATOR_SWIFT_MODULES_DIR}&quot; ]; then&#10;cp -R &quot;${SIMULATOR_SWIFT_MODULES_DIR}&quot; &quot;${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Modules/${TARGET_NAME}.swiftmodule&quot;&#10;fi&#10;&#10;# Step 3. Create universal binary file using lipo and place the combined executable in the copied framework directory&#10;echo &quot;Combining executables&quot;&#10;lipo -create -output &quot;${UNIVERSAL_OUTPUTFOLDER}/${EXECUTABLE_PATH}&quot; &quot;${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${EXECUTABLE_PATH}&quot; &quot;${BUILD_DIR}/${CONFIGURATION}-iphoneos/${EXECUTABLE_PATH}&quot;&#10;&#10;# Step 4. Create universal binaries for embedded frameworks&#10;#for SUB_FRAMEWORK in $( ls &quot;${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Frameworks&quot; ); do&#10;#BINARY_NAME=&quot;${SUB_FRAMEWORK%.*}&quot;&#10;#lipo -create -output &quot;${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}&quot; &quot;${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${SUB_FRAMEWORK}/${BINARY_NAME}&quot; &quot;${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/${TARGET_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}&quot;&#10;#done&#10;&#10;# Step 5. Convenience step to copy the framework to the project&apos;s directory&#10;echo &quot;Copying to project dir&quot;&#10;yes | cp -Rf &quot;${UNIVERSAL_OUTPUTFOLDER}/${FULL_PRODUCT_NAME}&quot; &quot;${PROJECT_DIR}&quot;&#10;&#10;fi&#10;">
<EnvironmentBuildable>
<BuildableReference
BuildableIdentifier = "primary"

View File

@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.3.0</string>
<string>2.4.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>

View File

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

View File

@@ -37,7 +37,6 @@
* List of domains used for universal linking.
*/
@property (copy, nonatomic, nullable) NSArray<NSString *> *universalLinkDomains;
/**
* Default conference options used for all conferences. These options will be merged
* with those passed to JitsiMeetView.join when joining a conference.

View File

@@ -24,6 +24,7 @@
#import "ReactUtils.h"
#import <RNGoogleSignin/RNGoogleSignin.h>
#import <WebRTC/RTCLogging.h>
@implementation JitsiMeet {
@@ -54,6 +55,11 @@
// Register a log handler for React.
registerReactLogHandler();
#if 0
// Enable WebRTC logs
RTCSetMinDebugLogLevel(RTCLoggingSeverityInfo);
#endif
}
return self;
@@ -90,8 +96,7 @@
if ([RNGoogleSignin application:app
openURL:url
sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]
annotation:options[UIApplicationOpenURLOptionsAnnotationKey]]) {
options:options]) {
return YES;
}
@@ -179,6 +184,15 @@
return _universalLinkDomains ? _universalLinkDomains : @[];
}
- (void)setDefaultConferenceOptions:(JitsiMeetConferenceOptions *)defaultConferenceOptions {
if (defaultConferenceOptions != nil && _defaultConferenceOptions.room != nil) {
@throw [NSException exceptionWithName:@"RuntimeError"
reason:@"'room' must be null in the default conference options"
userInfo:nil];
}
_defaultConferenceOptions = defaultConferenceOptions;
}
#pragma mark - Private API methods
- (NSDictionary *)getDefaultProps {

View File

@@ -26,7 +26,9 @@
*/
__attribute__((constructor))
static void initializeLogger() {
[DDLog addLogger:[DDOSLogger sharedInstance]];
NSString *mainBundleId = [NSBundle mainBundle].bundleIdentifier;
DDOSLogger *osLogger = [[DDOSLogger alloc] initWithSubsystem:mainBundleId category:@"JitsiMeetSDK"];
[DDLog addLogger:osLogger];
}
+ (void)addHandler:(JitsiMeetBaseLogHandler *)handler {

View File

@@ -37,6 +37,7 @@ set -e
# IOS_TEAM_ID - the team ID inserted into build-ipa-.plist.template file in
# place of "YOUR_TEAM_ID".
# Travis will not print the last echo if there's no sleep 1
function echoSleepAndExit1() {
echo $1
@@ -57,10 +58,6 @@ if [ -z $IPA_DEPLOY_LOCATION ]; then
echoSleepAndExit1 "No IPA_DEPLOY_LOCATION defined"
fi
if [ -z $APPLE_CERT_URL ]; then
APPLE_CERT_URL="http://developer.apple.com/certificationauthority/AppleWWDRCA.cer"
fi
echo "PR_REPO_SLUG=${PR_REPO_SLUG} PR_BRANCH=${PR_BRANCH}"
# do the marge and git log
@@ -88,47 +85,17 @@ fi
git log -20 --graph --pretty=format':%C(yellow)%h%Cblue%d%Creset %s %C(white) %an, %ar%Creset'
# certificates
#certificates
CERT_DIR="ios/travis-ci/certs"
mkdir $CERT_DIR
mkdir -p $CERT_DIR
./ios/ci/setup-certificates.sh $CERT_DIR
curl -L -o ${CERT_DIR}/AppleWWDRCA.cer 'http://developer.apple.com/certificationauthority/AppleWWDRCA.cer'
curl -L -o ${CERT_DIR}/dev-cert.cer.enc ${IOS_DEV_CERT_URL}
curl -L -o ${CERT_DIR}/dev-key.p12.enc ${IOS_DEV_CERT_KEY_URL}
curl -L -o ${CERT_DIR}/dev-profile.mobileprovision.enc ${IOS_DEV_PROV_PROFILE_URL}
curl -L -o ${CERT_DIR}/dev-watch-profile.mobileprovision.enc ${IOS_DEV_WATCH_PROV_PROFILE_URL}
curl -L -o ${CERT_DIR}/id_rsa.enc ${DEPLOY_SSH_CERT_URL}
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/dev-cert.cer.enc -d -a -out ${CERT_DIR}/dev-cert.cer
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/dev-key.p12.enc -d -a -out ${CERT_DIR}/dev-key.p12
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/dev-profile.mobileprovision.enc -d -a -out ${CERT_DIR}/dev-profile.mobileprovision
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/dev-watch-profile.mobileprovision.enc -d -a -out ${CERT_DIR}/dev-watch-profile.mobileprovision
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/id_rsa.enc -d -a -out ${CERT_DIR}/id_rsa
chmod 0600 ${CERT_DIR}/id_rsa
security create-keychain -p $ENCRYPTION_PASSWORD ios-build.keychain
security default-keychain -s ios-build.keychain
security unlock-keychain -p $ENCRYPTION_PASSWORD ios-build.keychain
security set-keychain-settings -t 3600 -l ~/Library/Keychains/ios-build.keychain
echo "importing Apple cert"
security import ${CERT_DIR}/AppleWWDRCA.cer -k ios-build.keychain -A
echo "importing dev-cert.cer"
security import ${CERT_DIR}/dev-cert.cer -k ios-build.keychain -A
echo "importing dev-key.p12"
security import ${CERT_DIR}/dev-key.p12 -k ios-build.keychain -P $IOS_SIGNING_CERT_PASSWORD -A
echo "will set-key-partition-list"
# Fix for OS X Sierra that hungs in the codesign step
security set-key-partition-list -S apple-tool:,apple: -s -k $ENCRYPTION_PASSWORD ios-build.keychain > /dev/null
echo "done set-key-partition-list"
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp "${CERT_DIR}/dev-profile.mobileprovision" ~/Library/MobileDevice/Provisioning\ Profiles/
cp "${CERT_DIR}/dev-watch-profile.mobileprovision" ~/Library/MobileDevice/Provisioning\ Profiles/
ssh-add ${CERT_DIR}/id_rsa
npm install
@@ -136,24 +103,21 @@ npm install
./node_modules/react-native-webrtc/tools/downloadBitcode.sh
cd ios
pod update
pod install
pod install --repo-update --no-ansi
cd ..
mkdir -p /tmp/jitsi-meet/
xcodebuild archive -quiet -workspace ios/jitsi-meet.xcworkspace -scheme jitsi-meet -configuration Release -archivePath /tmp/jitsi-meet/jitsi-meet.xcarchive
sed -e "s/YOUR_TEAM_ID/${IOS_TEAM_ID}/g" ios/travis-ci/build-ipa.plist.template > ios/travis-ci/build-ipa.plist
sed -e "s/YOUR_TEAM_ID/${IOS_TEAM_ID}/g" ios/ci/build-ipa.plist.template > ios/ci/build-ipa.plist
IPA_EXPORT_DIR=/tmp/jitsi-meet/jitsi-meet-ipa
xcodebuild -quiet -exportArchive -archivePath /tmp/jitsi-meet/jitsi-meet.xcarchive -exportPath $IPA_EXPORT_DIR -exportOptionsPlist ios/travis-ci/build-ipa.plist
xcodebuild -quiet -exportArchive -archivePath /tmp/jitsi-meet/jitsi-meet.xcarchive -exportPath $IPA_EXPORT_DIR -exportOptionsPlist ios/ci/build-ipa.plist
echo "Will try deploy the .ipa to: ${IPA_DEPLOY_LOCATION}"
ssh-add ${CERT_DIR}/id_rsa
if [ ! -z ${SCP_PROXY_HOST} ];
then
scp -o ProxyCommand="ssh -t -A -l %r ${SCP_PROXY_HOST} -o \"StrictHostKeyChecking no\" -o \"BatchMode yes\" -W %h:%p" -o StrictHostKeyChecking=no -o LogLevel=DEBUG "${IPA_EXPORT_DIR}/jitsi-meet.ipa" "${IPA_DEPLOY_LOCATION}"

View File

@@ -1,27 +1,31 @@
{
"en": "Английски",
"af": "Африканс",
"az": "Азербайджански",
"bg": "Български",
"ca": "Каталонски",
"cs": "Чешки",
"de": "Немски",
"el": "Гръцки",
"enGB": "Английски (Великобритания)",
"eo": "Есперанто",
"es": "Испански",
"esUS": "Испански (Латинска Америка)",
"fi": "Фински",
"fr": "Френски",
"frCA": "Френски (Канада)",
"hr": "Хърватски",
"hy": "Арменски",
"it": "Италиански",
"ja": "Японски",
"ko": "Корейски",
"nb": "Норвежки букмол",
"nl": "Нидерландски",
"oc": "Окситански",
"pl": "Полски",
"ptBR": "Португалски (Бразилия)",
"ru": "Руски",
"sk": "Словашки",
"sl": "Словенски",
"sv": "Шведски",
"tr": "Турски",
"vi": "Виетнамски",
"zhCN": "Китайски (Китай)"
"zhCN": "Китайски (Китай)",
"zhTW": "Тайвански"
}

View File

@@ -1,27 +1,31 @@
{
"en": "Angol",
"af": "",
"az": "",
"bg": "Bolgár",
"cs": "",
"de": "Német",
"el": "",
"eo": "Eszperantó",
"es": "Spanyol",
"fr": "Francia",
"hy": "Örmény",
"it": "Olasz",
"ja": "",
"ko": "",
"nb": "Norvég bokmal",
"oc": "Okszitán",
"pl": "Lengyel",
"ptBR": "Portugál (Brazil)",
"ru": "Orosz",
"sk": "Szlovák",
"sl": "Szlovén",
"sv": "Svéd",
"tr": "Török",
"vi": "",
"zhCN": "Kínai (Kína)"
"en": "angol",
"af": "afrikaans",
"bg": "bolgár",
"ca": "katalán",
"cs": "cseh",
"de": "német",
"el": "görög",
"enGB": "angol (Egyesült Királyság)",
"eo": "eszperantó",
"es": "spanyol",
"esUS": "spanyol (Latin-Amerika)",
"fi": "finn",
"fr": "francia",
"frCA": "francia (kanadai)",
"hr": "horvát",
"hy": "örmény",
"it": "olasz",
"ja": "japán",
"ko": "koreai",
"nl": "holland",
"oc": "okszitán",
"pl": "lengyel",
"ptBR": "portugál (Brazil)",
"ru": "orosz",
"sv": "svéd",
"tr": "török",
"vi": "vietnámi",
"zhCN": "kínai (Kína)",
"zhTW": "kínai (Tajvan)"
}

View File

@@ -2,23 +2,23 @@
"en": "Anglés",
"af": "Afrikaans",
"bg": "Bulgar",
"ca": "",
"ca": "Catalan",
"cs": "Chèc",
"de": "Aleman",
"el": "Grèc",
"enGB": "",
"enGB": "Anglés (Reialme Unit)",
"eo": "Esperanto",
"es": "Castelhan",
"esUS": "",
"fi": "",
"esUS": "Espanhòl (America latina)",
"fi": "Finés",
"fr": "Francés",
"frCA": "",
"hr": "",
"frCA": "Francés (Canadian)",
"hr": "Croat",
"hy": "Armenian",
"it": "Italian",
"ja": "Japonés",
"ko": "Corean",
"nl": "",
"nl": "Neerlandés",
"oc": "Occitan",
"pl": "Polonés",
"ptBR": "Portugués (Brasil)",
@@ -27,5 +27,5 @@
"tr": "Turc",
"vi": "Vietnamian",
"zhCN": "Chinés (China)",
"zhTW": ""
"zhTW": "Chinés (Taiwan)"
}

View File

@@ -1,27 +1,31 @@
{
"en": "Anglik",
"af": "",
"az": "Azerski",
"en": "Angielski",
"af": "Afrykanerski",
"bg": "Bułgarski",
"ca": "",
"cs": "Czeski",
"de": "Niemiecki",
"el": "Grecki",
"enGB": "",
"eo": "Esperanto",
"es": "Hiszpański",
"esUS": "",
"fi": "",
"fr": "Francuski",
"frCA": "",
"hr": "",
"hy": "Ormiański",
"it": "Włoski",
"ja": "Japoński",
"ko": "Koreański",
"nb": "Norweski Bokmal",
"nl": "",
"oc": "Oksytański",
"pl": "Polski",
"ptBR": "portugalski (brazylijski)",
"ptBR": "Portugalski (brazylijski)",
"ru": "Rosyjski",
"sk": "Słowacki",
"sl": "Słoweński",
"sv": "Szwedzki",
"tr": "Turecki",
"vi": "Wietnamski",
"zhCN": "Chiński (Chiny)"
"zhCN": "Chiński (Chiny)",
"zhTW": ""
}

View File

@@ -1,27 +1,31 @@
{
"en": "Inglês",
"af": "Africâner",
"az": "Azerbaijanês",
"bg": "Búlgaro",
"ca": "",
"cs": "Checo",
"de": "Alemão",
"el": "Grego",
"enGB": "",
"eo": "Esperanto",
"es": "Espanhol",
"esUS": "",
"fi": "",
"fr": "Francês",
"frCA": "",
"hr": "",
"hy": "Armênio",
"it": "Italiano",
"ja": "Japonês",
"ko": "Coreano",
"nb": "Bokmal norueguês",
"nl": "",
"oc": "Occitano",
"pl": "Polonês",
"ptBR": "Português (Brasil)",
"ru": "Russo",
"sk": "Eslovaco",
"sl": "Esloveno",
"sv": "Sueco",
"tr": "Turco",
"vi": "Vietnamita",
"zhCN": "Chinês (China)"
"zhCN": "Chinês (China)",
"zhTW": ""
}

View File

@@ -14,6 +14,7 @@
"fr": "French",
"frCA": "French (Canadian)",
"hr": "Croatian",
"hu": "Hungarian",
"hy": "Armenian",
"it": "Italian",
"ja": "Japanese",

View File

@@ -4,8 +4,8 @@
"countryNotSupported": "Желаната дестинация не се поддържа.",
"countryReminder": "Международно обаждане? Започнете номера с международният код!",
"disabled": "Не можете да каните хора.",
"failedToAdd": "",
"footerText": "Изходящиите разговори не са разрешени.",
"failedToAdd": "Неуспешно добавяне на участници",
"footerText": "Изходящите разговори не са разрешени.",
"loading": "Търсене на хора и телефонни номера.",
"loadingNumber": "Валидиране на номера",
"loadingPeople": "Търсене на хора",
@@ -13,48 +13,49 @@
"noValidNumbers": "Моля въведете телефонен номер",
"searchNumbers": "Добавяне на номера",
"searchPeople": "Търсене на хора",
"searchPeopleAndNumbers": "",
"telephone": "",
"title": ""
"searchPeopleAndNumbers": "Търсене на участници или добавяне с телефони номера",
"telephone": "Телефон: {{number}}",
"title": "Добавяне на участници в срещата"
},
"audioDevices": {
"bluetooth": "",
"bluetooth": "Bluetooth",
"headphones": "Слушалки",
"phone": "Телефон",
"speaker": "Говорещ"
"speaker": "Говорещ",
"none": "Няма налични устройства за звук"
},
"audioOnly": {
"audioOnly": "Само звук"
"audioOnly": "Нисък дебит"
},
"calendarSync": {
"addMeetingURL": "",
"confirmAddLink": "",
"addMeetingURL": "Добавяне на връзка за среща",
"confirmAddLink": "Искате ли да добавите връзка към това събитие?",
"error": {
"appConfiguration": "",
"generic": "",
"notSignedIn": ""
"appConfiguration": "Интеграцията с календара не е настроена.",
"generic": "Грешка, моля проверете настройката за календара или го обновете.",
"notSignedIn": "Грешка при идентификация за изтегляне на събития. Моля проверете настройките на календара и опитайте отново."
},
"join": "",
"joinTooltip": "",
"nextMeeting": "",
"noEvents": "",
"ongoingMeeting": "",
"permissionButton": "",
"permissionMessage": "",
"refresh": "",
"today": ""
"join": "Влизане",
"joinTooltip": "Влизане в срещата",
"nextMeeting": "следваща среща",
"noEvents": "Няма насрочени бъдещи събития.",
"ongoingMeeting": "настояща среща",
"permissionButton": "Отваряне на настройки",
"permissionMessage": "За показване на срещите ви е нужно позволение за ползване на календара.",
"refresh": "Обновяване на календара",
"today": "Днес"
},
"chat": {
"error": "",
"messagebox": "",
"error": "Грешка: вашето съобщение \"{{originalText}}\" не е бе изпратено. Поради: {{error}}",
"messagebox": "Въведете съобщение",
"nickname": {
"popover": "Избор на име",
"title": ""
"title": "Въведете име за да обменяте съобщения"
},
"title": ""
"title": "Текстови съобщения"
},
"connectingOverlay": {
"joiningRoom": ""
"joiningRoom": "Свързване с вашата среща..."
},
"connection": {
"ATTACHED": "Прикрепен",
@@ -72,8 +73,8 @@
"address": "Адрес:",
"bandwidth": "Предполагаема скорост:",
"bitrate": "Скорост:",
"bridgeCount": "",
"connectedTo": "",
"bridgeCount": "Брой сървъри:",
"connectedTo": "Свързан към:",
"framerate": "Кадри в секунда:",
"less": "Скриване",
"localaddress": "Локален адрес:",
@@ -96,26 +97,25 @@
"resolution": "Резолюция:",
"status": "Връзка:",
"transport": "Транспорт:",
"transport_plural": "Транспорти:",
"turn": " (обръщане)"
"transport_plural": "Транспорти:"
},
"dateUtils": {
"earlier": "",
"today": "",
"yesterday": ""
"earlier": "По-рано",
"today": "Днес",
"yesterday": "Вчера"
},
"deepLinking": {
"appNotInstalled": "",
"description": "",
"descriptionWithoutWeb": "",
"downloadApp": "Сваляне не приложението",
"launchWebButton": "",
"openApp": "",
"title": "",
"tryAgainButton": ""
"appNotInstalled": "Имате нужда от мобилното приложение {{app}} за влизане в тази среща от телефона.",
"description": "Нищо не се случва? Опитахме се да заредим срещата в приложението {{app}}. Пробвайте отново или влезте чрез уеб приложението {{app}}.",
"descriptionWithoutWeb": "Нищо не се случва? Опитахме се да заредим срещата в приложението {{app}}.",
"downloadApp": "Свалете приложението",
"launchWebButton": "Заредете уеб страницата",
"openApp": "Продължете към приложението",
"title": "Зареждане на срещата в {{app}}...",
"tryAgainButton": "Пробвайте отново"
},
"\u0005deepLinking": {},
"defaultLink": "напр. {{url}}",
"defaultNickname": "напр. Иван Иванов",
"deviceError": {
"cameraError": "Камерата е недостъпна",
"cameraPermission": "Грешка при получаване на разрешение за достъп до камерата",
@@ -126,14 +126,14 @@
"noPermission": "Не е получено разрешение",
"previewUnavailable": "Няма възможност за преглед",
"selectADevice": "Изберете устройство",
"testAudio": ""
"testAudio": "Пусни пробен звук"
},
"dialog": {
"accessibilityLabel": {
"liveStreaming": "Излъчване на живо"
},
"allow": "Разрешаване",
"alreadySharedVideoMsg": "",
"alreadySharedVideoMsg": "Друг участник вече е споделил видео. Тази среща позволява само едно споделено видео.",
"alreadySharedVideoTitle": "Разрешено е споделянето само на едно видео в даден момент",
"applicationWindow": "Прозореца на програмата",
"Back": "Назад",
@@ -150,8 +150,8 @@
"conferenceDisconnectTitle": "Връзката се разпадна.",
"conferenceReloadMsg": "Опитваме се да оправим нещата. Повторно свързване след {{seconds}} сек…",
"conferenceReloadTitle": "За съжаление, нещо се обърка.",
"confirm": "",
"confirmNo": "",
"confirm": "Потвърждение",
"confirmNo": "Не",
"confirmYes": "Да",
"connectError": "Опа! Нещо се обърка и не успяхме да се свържем с конференцията.",
"connectErrorWithMsg": "Опа! Нещо се обърка и не успяхме да се свържем с конференцията: {{msg}}",
@@ -159,66 +159,66 @@
"contactSupport": "Връзка с отдела по поддръжка",
"copy": "Копиране",
"dismiss": "Отхвърляне",
"displayNameRequired": "",
"displayNameRequired": "Здравей! Как се казваш?",
"done": "Готово",
"enterDisplayName": "",
"enterDisplayName": "Моля въведете вашето име",
"error": "Грешка",
"externalInstallationMsg": "Трябва да инсталирате разширението за споделяне на екрана.",
"externalInstallationTitle": "Нужно е разширение",
"goToStore": "Към магазина в Интернет",
"gracefulShutdown": "Услугата временно не е достъпна поради профилактика. Моля опитайте по-късно.",
"IamHost": "Аз съм домакина",
"incorrectRoomLockPassword": "",
"incorrectRoomLockPassword": "Грешна парола",
"incorrectPassword": "Неправилно потребителско име или парола",
"inlineInstallationMsg": "Трябва да инсталирате разширението за споделяне на екрана.",
"inlineInstallExtension": "Инсталиране сега",
"internalError": "Опа! Нещо се обърка. Възникна следната грешка: {{error}}",
"internalErrorTitle": "Вътрешна грешка",
"kickMessage": "",
"kickParticipantButton": "",
"kickParticipantDialog": "",
"kickParticipantTitle": "",
"kickTitle": "",
"kickMessage": "Може да се свържете с {{participantDisplayName}} за повече подробности.",
"kickParticipantButton": "Изгони",
"kickParticipantDialog": "Сигурни ли сте че искате да изгоните участника?",
"kickParticipantTitle": "Изгонване на този участник?",
"kickTitle": "Ауч! {{participantDisplayName}} ви изгони от тази среща",
"liveStreaming": "Излъчване на живо",
"liveStreamingDisabledForGuestTooltip": "",
"liveStreamingDisabledTooltip": "",
"liveStreamingDisabledForGuestTooltip": "Гостите не могат да стартират излъчване на живо.",
"liveStreamingDisabledTooltip": "Излъчването на живо е деактивирано.",
"lockMessage": "Неуспешно заключване на конференцията.",
"lockRoom": "",
"lockRoom": "Добавяне $t(lockRoomPasswordUppercase) за срещата",
"lockTitle": "Неуспешно заключване",
"logoutQuestion": "Сигурни ли сте, че искате да излезете и да прекъснете конференцията?",
"logoutTitle": "Изход",
"maxUsersLimitReached": "",
"maxUsersLimitReachedTitle": "",
"maxUsersLimitReached": "Лимитът за максимален брой участници бе достигнат. Капацитета на срещата е запълнен. Моля свържете се с организатора или опитайте по-късно!",
"maxUsersLimitReachedTitle": "Достигнат е лимита за максимален брой участници",
"micConstraintFailedError": "Микрофонът Ви не покрива някои от изискванията.",
"micNotFoundError": "Не е открит микрофон.",
"micNotSendingData": "",
"micNotSendingDataTitle": "",
"micNotSendingData": "Пуснете микрофона си от системните настройки на компютъра ви.",
"micNotSendingDataTitle": "Микрофона ви е спрян от системните настройки",
"micPermissionDeniedError": "Не сте дали разрешение за използване на микрофона. Ще можете да се присъедините в беседата, но другите няма да Ви чуват. Използвайте бутона с камерата в адресната лента, за да оправите това.",
"micUnknownError": "Не възможен достъп до микрофона по неясна причина.",
"micUnknownError": "Невъзможен достъп до микрофона по неясна причина.",
"muteParticipantBody": "Вие няма да можете да спрете заглушаването на участника, но той ще може да го направи по всяко време.",
"muteParticipantButton": "Изключи микрофона",
"muteParticipantDialog": "",
"muteParticipantTitle": "",
"muteParticipantDialog": "Сигурни ли сте че искате да заглушите този участник? Няма да можете да пуснете обратно звука му, но участника ще може да направи това сам.",
"muteParticipantTitle": "Спиране звука на участник?",
"Ok": "Готово",
"passwordLabel": "",
"passwordNotSupported": "Задаването на парола за срещата не се поддържа.",
"passwordNotSupportedTitle": "",
"passwordRequired": "",
"passwordLabel": "Парола",
"passwordNotSupported": "Задаването на $t(lockRoomPassword) за срещата не се поддържа.",
"passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) не се поддържа",
"passwordRequired": "Изисква се $t(lockRoomPassword) ",
"popupError": "Браузърът Ви блокира изскачащите прозорци от този уеб сайт. Моля, разрешете изскачащите прозорци от настройките за сигурност на браузъра си и след това опитайте отново.",
"popupErrorTitle": "Блокиран изскачащ прозорец",
"recording": "Запис",
"recordingDisabledForGuestTooltip": "",
"recordingDisabledTooltip": "",
"recordingDisabledForGuestTooltip": "Гостите не могат да стартират запис",
"recordingDisabledTooltip": "Стартирането на запис е спряно",
"rejoinNow": "Повторно присъединяване сега",
"remoteControlAllowedMessage": "{{user}} прие заявката Ви за отдалечено управление!",
"remoteControlDeniedMessage": "{{user}} отказа заявката Ви за отдалечено управление!",
"remoteControlErrorMessage": "Възникна грешка при опита за искана на разрешение за отдалечено управление от {{user}}!",
"remoteControlErrorMessage": "Възникна грешка при опита за искане на разрешение за отдалечено управление от {{user}}!",
"remoteControlRequestMessage": "Ще позволите ли на {{user}} да управлява отдалечено компютъра Ви?",
"remoteControlShareScreenWarning": "Ако натиснете „Разрешаване“, ще споделите екрана си!",
"remoteControlStopMessage": "Сесията за отдалечено управление приключи!",
"remoteControlTitle": "Отдалечено управление на компютъра",
"Remove": "Премахване",
"removePassword": "",
"removePassword": "Премахване на $t(lockRoomPassword)",
"removeSharedVideoMsg": "Наистина ли искате да премахнете споделеното си видео?",
"removeSharedVideoTitle": "Край на споделянето на видео",
"reservationError": "Грешка в системата за резервации",
@@ -226,8 +226,8 @@
"retry": "Повторен опит",
"screenSharingFailedToInstall": "Опа! Разширението за споделяне на екрана не успя да се инсталира.",
"screenSharingFailedToInstallTitle": "Разширението за споделяне на екрана не успя да се инсталира",
"screenSharingFirefoxPermissionDeniedError": "",
"screenSharingFirefoxPermissionDeniedTitle": "",
"screenSharingFirefoxPermissionDeniedError": "Нещо се обърка докато се опитвахме да споделим екрана. Моля уверете се че сте дали права за това.",
"screenSharingFirefoxPermissionDeniedTitle": "Упс! Не успяхме да стартираме споделянето на екрана!",
"screenSharingPermissionDeniedError": "Опа! Нещо се обърка с разрешенията на разширението за споделяне на екрана. Моля, презаредете и опитайте отново.",
"serviceUnavailable": "Услугата не е налична",
"sessTerminated": "Разговорът приключи",
@@ -235,91 +235,86 @@
"shareVideoLinkError": "Моля въведете правилна връзка към YouTube.",
"shareVideoTitle": "Сподели видео",
"shareYourScreen": "Споделяне на екрана",
"shareYourScreenDisabled": "",
"shareYourScreenDisabledForGuest": "",
"shareYourScreenDisabled": "Споделянето на екрана не се поддържа.",
"shareYourScreenDisabledForGuest": "Гостите не могат да споделят екрана.",
"startLiveStreaming": "Започване на излъчване на живо",
"startRecording": "Край на записа",
"startRecording": "Стартиране на запис",
"startRemoteControlErrorMessage": "Възникна грешка при опита за започване на сесията за отдалечено управление!",
"stopLiveStreaming": "Спиране на излъчването на живо",
"stopRecording": "Край на записа",
"stopRecordingWarning": "Наистина ли искате да спрем записа?",
"stopStreamingWarning": "Наистина ли искате да спрете излъчването на живо?",
"streamKey": "",
"streamKey": "Ключ за излъчване на живо",
"Submit": "Изпращане",
"thankYou": "Благодарим, че използвахте {{appName}}!",
"token": "код за достъп",
"tokenAuthFailed": "Съжаляваме, но не можете да се присъедините към този разговор.",
"tokenAuthFailedTitle": "Неуспешна идентификация",
"transcribing": "",
"unlockRoom": "",
"transcribing": "Транскрипция",
"unlockRoom": "Премахване $t(lockRoomPassword) от срещата",
"userPassword": "потребителска парола",
"WaitForHostMsg": "",
"WaitForHostMsgWOk": "",
"WaitForHostMsg": "Конференцията <b>{{room}}</b> все още не е започнала. Ако сте домакинът тогава се идентифицирайте. В противен случай изчакайте докато домакинът пристигне.",
"WaitForHostMsgWOk": "Конференцията <b>{{room}}</b> все още не е започнала. Ако сте домакинът тогава натиснете бутона за да се идентифицирате. В противен случай изчакайте докато домакинът пристигне.",
"WaitingForHost": "Чакаме домакина ...",
"Yes": "Да",
"yourEntireScreen": "Целия екран"
},
"\u0005dialog": {
"accessibilityLabel": {}
},
"dialOut": {
"statusMessage": "в момента е {{status}}"
},
"feedback": {
"average": "Средно",
"bad": "Лошо",
"detailsLabel": "",
"detailsLabel": "Разкажете ни повече.",
"good": "Добра",
"rateExperience": "Моля, оценете качеството на срещата.",
"veryBad": "Много лошо",
"veryGood": "Много добра"
},
"\u0005feedback": {},
"incomingCall": {
"answer": "",
"audioCallTitle": "",
"answer": "Вдигни",
"audioCallTitle": "Входящ разговор",
"decline": "Отхвърляне",
"productLabel": "",
"videoCallTitle": ""
"productLabel": "от Jitsi Meet",
"videoCallTitle": "Входящ видео разговор"
},
"info": {
"accessibilityLabel": "",
"addPassword": "",
"cancelPassword": "",
"conferenceURL": "",
"country": "",
"dialANumber": "",
"dialInConferenceID": "",
"dialInNotSupported": "",
"dialInNumber": "",
"dialInSummaryError": "",
"dialInTollFree": "",
"genericError": "",
"inviteLiveStream": "",
"invitePhone": "",
"invitePhoneAlternatives": "",
"inviteURLFirstPartGeneral": "",
"inviteURLFirstPartPersonal": "",
"inviteURLSecondPart": "",
"liveStreamURL": "Излъчване на живо",
"moreNumbers": "",
"noNumbers": "",
"accessibilityLabel": "Покажи информация",
"addPassword": "Добави $t(lockRoomPassword)",
"cancelPassword": "Премахни $t(lockRoomPassword)",
"conferenceURL": "Връзка:",
"country": "Страна",
"dialANumber": "За влизане в срещата, наберете един от изброените номера и въведете кода.",
"dialInConferenceID": "Код:",
"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": "",
"noRoom": "Няма посочена стая за информация за номера за набиране.",
"numbers": "Номера",
"password": "$t(lockRoomPasswordUppercase):",
"title": "Споделяне",
"tooltip": "",
"label": ""
"tooltip": "Споделете връзката и информацията за номера свързани със срещата",
"label": "Информация за срещата"
},
"\u0005info": {},
"inviteDialog": {
"alertText": "",
"alertText": "Не успях да поканя участниците.",
"header": "Покани",
"searchCallOnlyPlaceholder": "Въведете телефонен номер",
"searchPeopleOnlyPlaceholder": "",
"searchPlaceholder": "",
"send": ""
"searchPeopleOnlyPlaceholder": "Търсене на участници",
"searchPlaceholder": "Участник или телефонен номер",
"send": "Изпрати"
},
"inlineDialogFailure": {
"msg": "Имаше грешка.",
@@ -329,181 +324,182 @@
},
"keyboardShortcuts": {
"focusLocal": "Фокусиране върху Вашето видео",
"focusRemote": "Фокусиране върху видеото на друг участник",
"focusRemote": "Фокусирай видеото на друг участник",
"fullScreen": "Влизане/излизане от режим на цял екран",
"keyboardShortcuts": "Клавишни комбинации",
"localRecording": "",
"localRecording": "Показване или скриване на контролите за локален запис",
"mute": "Спиране/пускане на микрофона",
"pushToTalk": "Натиснете, за да говорите",
"raiseHand": "Вдигнете или свалете ръка",
"showSpeakerStats": "Показване на статистика за говорителя",
"toggleChat": "Отваряне/скриване на текстовите съобщения",
"toggleFilmstrip": "",
"toggleFilmstrip": "Показване или скриване на видео миниатюрите",
"toggleScreensharing": "Смяна между камера и споделен екран",
"toggleShortcuts": "",
"videoMute": "Пускане/спиране на камерата"
"toggleShortcuts": "Показване или скриване на клавишните комбинации",
"videoMute": "Пускане/спиране на камерата",
"videoQuality": "Управление на качество на обаждането"
},
"\u0005keyboardShortcuts": {},
"liveStreaming": {
"busy": "Работим върху това да освободим ресурси за излъчване. Моля, опитайте отново след няколко минути.",
"busyTitle": "Всички излъчватели в момента са заети.",
"changeSignIn": "",
"choose": "",
"chooseCTA": "",
"enterStreamKey": "",
"changeSignIn": "Смяна на акаунти.",
"choose": "Изберете предаване на живо",
"chooseCTA": "Изберете опция за предаване. Влезли сте като {{email}}.",
"enterStreamKey": "Въведете ключа от YouTube за предаване на живо.",
"error": "Излъчването на живо беше неуспешно. Моля, опитайте отново.",
"errorAPI": "",
"errorLiveStreamNotEnabled": "",
"expandedOff": "",
"expandedOn": "",
"expandedPending": "",
"errorAPI": "Изникна проблем с връзката към YouTube. Моля опитайте отново.",
"errorLiveStreamNotEnabled": "Предаването на живо не е пуснато за {{email}}. Моля активирайте го или сменете акаунта.",
"expandedOff": "Предаването на живо бе спряно",
"expandedOn": "Срещата се излъчва на живо в YouTube.",
"expandedPending": "Излъчването на живо се стартира...",
"failedToStart": "Излъчването на живо не успя да започне",
"getStreamKeyManually": "",
"invalidStreamKey": "",
"getStreamKeyManually": "Не успяхме да открием никакво предаване на живо. Опитайте да вземете ключа за такова от YouTube.",
"invalidStreamKey": "Ключът за предаване на живо е грешен.",
"off": "Край на излъчването на живо",
"offBy": "{{name}} спря излъчването на живо",
"on": "Излъчване на живо",
"onBy": "{{name}} пусна излъчване на живо",
"pending": "Започване на излъчването на живо…",
"serviceName": "",
"signedInAs": "",
"signIn": "",
"signInCTA": "",
"serviceName": "Предаване на живо",
"signedInAs": "В момента сте влезли като:",
"signIn": "Влезте с Гугъл",
"signInCTA": "Влезте или въведете ключът за излъчване на живо от YouTube.",
"signOut": "",
"start": "Започване на излъчване на живо",
"streamIdHelp": "",
"start": "Започни излъчване на живо",
"streamIdHelp": "Какво е това?",
"unavailableTitle": "Излъчването на живо е недостъпно"
},
"\u0005liveStreaming": {},
"localRecording": {
"clientState": {
"off": "",
"on": "",
"unknown": ""
"off": "Изключено",
"on": "Включено",
"unknown": "Непознат"
},
"dialogTitle": "",
"duration": "",
"durationNA": "",
"encoding": "",
"label": "",
"labelToolTip": "",
"localRecording": "",
"dialogTitle": "Управление на локален запис",
"duration": "Продължителност",
"durationNA": "Няма",
"encoding": "Кодек",
"label": "Етикет",
"labelToolTip": "Локалния запис е включен",
"localRecording": "Локален запис",
"me": "Аз",
"messages": {
"engaged": "",
"finished": "",
"finishedModerator": "",
"notModerator": ""
"engaged": "Локалния запис е включен.",
"finished": "Записа на сесията {{token}} приключи. Моля изпратете записа на вашият домакин.",
"finishedModerator": "Сесията {{token}} за запис приключи. Локалният запис беше запазен. Моля поканете останалите участници да ви изпратят техните записи.",
"notModerator": "Нямате права да пускате спирате локален запис."
},
"moderator": "Модератор",
"no": "",
"no": "Не",
"participant": "Участник",
"participantStats": "",
"sessionToken": "",
"start": "Край на записа",
"stop": "Край на записа",
"participantStats": "Статистика на участник",
"sessionToken": "Тоукън за сесията",
"start": "Започни запис",
"stop": "Спри записа",
"yes": "Да"
},
"\u0005localRecording": {},
"lockRoomPassword": "парола",
"lockRoomPasswordUppercase": "Парола",
"me": "аз",
"notify": {
"connectedOneMember": "",
"connectedThreePlusMembers": "",
"connectedTwoMembers": "",
"disconnected": "Връзка:",
"connectedOneMember": "{{name}} влезна в срещата",
"connectedThreePlusMembers": "{{name}} и още {{count}} влезнаха в срещата",
"connectedTwoMembers": "{{first}} и {{second}} влезнаха в срещата",
"disconnected": "Напусна срещата",
"focus": "Конферентен фокус",
"focusFail": "{{component}} не е на раположения - следващ опит след {{ms}} секунди",
"focusFail": "{{component}} не е на раположение - следващ опит след {{ms}} секунди",
"grantedTo": "Даване на роля модератор на {{to}}!",
"invitedOneMember": "",
"invitedThreePlusMembers": "",
"invitedTwoMembers": "",
"kickParticipant": "",
"invitedOneMember": "{{name}} бе поканен",
"invitedThreePlusMembers": "{{name}} и още {{count}} бяха поканени",
"invitedTwoMembers": "{{first}} и {{second}} бяха поканени",
"kickParticipant": "{{kicked}} беше изгонен от {{kicker}}",
"me": "Аз",
"moderator": "Придобихте права на модератор!",
"muted": "Започвате разговора без звук.",
"mutedTitle": "Звукът ви е спрян!",
"mutedRemotelyTitle": "",
"mutedRemotelyDescription": "",
"passwordRemovedRemotely": "",
"passwordSetRemotely": "",
"raisedHand": "",
"mutedRemotelyTitle": "Микрофонът ви бе спрян от {{participantDisplayName}}!",
"mutedRemotelyDescription": "Винаги можете да пуснете микрофона си когато сте готови да говорите. Заглушете го отново за да не изпращате шум в срещата.",
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) е премахната от друг потребител",
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) създадена от друг потребител",
"raisedHand": "{{name}} иска думата.",
"somebody": "Някой",
"startSilentTitle": "",
"startSilentDescription": "",
"suboptimalExperienceDescription": "",
"suboptimalExperienceTitle": "",
"unmute": "",
"newDeviceCameraTitle": "",
"newDeviceAudioTitle": "",
"newDeviceAction": ""
"startSilentTitle": "Влязохте с опция да не чувате аудио!",
"startSilentDescription": "Влезте повторно за да пуснете звука",
"suboptimalBrowserWarning": "Опасяваме се, че няма да можете да се насладите на срещата. Работим по въпроса, междувременно използвайте някой от <a href='static/recommendedBrowsers.html' target='_blank'>напълно поддържаните браузъри</a>.",
"suboptimalExperienceTitle": "Внимание",
"unmute": "Пускане на микрофона",
"newDeviceCameraTitle": "Засечена е нова камера",
"newDeviceAudioTitle": "Ново аудио устройство е засечено",
"newDeviceAction": "Използвай"
},
"passwordSetRemotely": "",
"passwordDigitsOnly": "",
"passwordSetRemotely": "зададена от друг участник",
"passwordDigitsOnly": "До {{number}} цифри",
"poweredby": "с подкрепата на",
"presenceStatus": {
"busy": "",
"calling": "",
"busy": "Зает",
"calling": "Обаждане...",
"connected": "Свързан",
"connecting": "Свързване",
"connecting2": "Свързване",
"connecting": "Свързване...",
"connecting2": "Свързване*...",
"disconnected": "Изключен",
"expired": "",
"ignored": "",
"initializingCall": "",
"invited": "Покани",
"rejected": "",
"ringing": ""
"expired": "Изтекъл",
"ignored": "Пренебрегнат",
"initializingCall": "Свързване на обаждането...",
"invited": "Поканен",
"rejected": "Отхвърлен",
"ringing": "Звъни..."
},
"\u0005presenceStatus": {},
"profile": {
"setDisplayNameLabel": "Задайте екранното си име",
"setEmailInput": "Въведете е-поща",
"setEmailLabel": "Задайте е-пощата си в „gravatar“",
"title": "Профил"
},
"raisedHand": "Иска думата",
"recording": {
"authDropboxText": "",
"availableSpace": "",
"beta": "",
"authDropboxText": "Качете в Dropbox",
"availableSpace": "Налично място: {{spaceLeft}} MB (приблизително {{duration}} минути запис)",
"beta": "БЕТА",
"busy": "Работим върху това да освободим ресурси за запис. Моля, опитайте отново след няколко минути.",
"busyTitle": "Всички възможности за запис в момента са заети",
"error": "Грешка при опит за запис. Моля опитайте отново.",
"expandedOff": "Записът спрян",
"expandedOn": "",
"expandedPending": "Записът започна",
"expandedOff": "Записът спря",
"expandedOn": "Срещата се записва в момента",
"expandedPending": "Записът започва...",
"failedToStart": "Неуспешен опит за записване",
"fileSharingdescription": "",
"live": "",
"loggedIn": "",
"fileSharingdescription": "Споделете записа с участниците в срещата",
"live": "На Живо",
"loggedIn": "Влезли сте като {{userName}}",
"off": "Записът спрян",
"offBy": "{{name}} спря записът",
"on": "Запис",
"pending": "",
"rec": "",
"serviceDescription": "",
"serviceName": "",
"signIn": "",
"signOut": "",
"unavailable": "",
"onBy": "{{name}} пусна запис",
"pending": "Стартира запис на срещата...",
"rec": "ЗАПИС",
"serviceDescription": "Записът ви ще се запише от специална записваща услуга",
"serviceName": "Записваща услуга",
"signIn": "Влизане",
"signOut": "Излизане",
"unavailable": "Упс! В момент {{serviceName}} е недостъпна. В момента се опитваме да решим проблема. Моля опитайте отново малко по-късно.",
"unavailableTitle": "Записът е невъзможен"
},
"\u0005recording": {},
"sectionList": {
"pullToRefresh": ""
"pullToRefresh": "Издърпай за да се обнови"
},
"settings": {
"calendar": {
"about": "",
"disconnect": "Изключен",
"microsoftSignIn": "",
"signedIn": "",
"about": "Календарната интеграция на {{appName}} сигурно достъпва вашия календар за да покаже настъпващите събития.",
"disconnect": "Разкачи",
"microsoftSignIn": "Влез с Microsoft акаунт",
"signedIn": "В момента достъпва календара с {{email}}. Натиснете бутона Разкачи за да спрете достъпа.",
"title": ""
},
"devices": "",
"devices": "Устройства",
"followMe": "Всички ме следват",
"language": "",
"loggedIn": "",
"language": "Език",
"loggedIn": "Влезли сте като {{name}}",
"moderator": "Модератор",
"more": "",
"more": "Повече",
"name": "Име",
"noDevice": "Няма",
"selectAudioOutput": "Звуков изход",
@@ -513,27 +509,24 @@
"startVideoMuted": "Всички започват скрити",
"title": "Настройки"
},
"\u0005settings": {
"calendar": {}
},
"settingsView": {
"alertOk": "",
"alertOk": "Потвърди",
"alertTitle": "Внимание",
"alertURLText": "",
"buildInfoSection": "",
"conferenceSection": "",
"displayName": "",
"email": "",
"alertURLText": "Въведената връзка за сървър е невалидна",
"buildInfoSection": "Информация за програмата",
"conferenceSection": "Конференция",
"displayName": "Име",
"email": "Поща",
"header": "Настройки",
"profileSection": "Профил",
"serverURL": "",
"startWithAudioMuted": "",
"startWithVideoMuted": "",
"version": ""
"serverURL": "Линк на сървъра",
"startWithAudioMuted": "Започни със спрян звук",
"startWithVideoMuted": "Започни със спряно видео",
"version": "Версия"
},
"share": {
"dialInfoText": "",
"mainText": ""
"dialInfoText": "\n\n=====\n\nИскате да наберете от телефона?\n\n{{defaultDialInNumber}}Използвайте този линк за повече номера\n{{dialInfoPageUrl}}",
"mainText": "Използвайте линка за да влезете в срещата:\n{{roomUrl}}"
},
"speaker": "Говорещ",
"speakerStats": {
@@ -555,99 +548,95 @@
},
"toolbar": {
"accessibilityLabel": {
"audioOnly": "",
"audioOnly": "Пускане на режим само с звук",
"audioRoute": "",
"callQuality": "",
"cc": "",
"chat": "",
"document": "Отваряне/затваряне на споделен документ",
"callQuality": "Управление на качестото на обаждането",
"cc": "Пускане на субтитри",
"chat": "Активиране на прозорец за съобщения",
"document": "Показване на споделен документ",
"feedback": "",
"fullScreen": "",
"hangup": "",
"fullScreen": "Пускане/Спиране на изглед в цял екран",
"hangup": "Напускане на срещата",
"invite": "Поканете участници",
"kick": "",
"localRecording": "",
"lockRoom": "",
"moreActions": "",
"moreActionsMenu": "",
"mute": "",
"pip": "",
"kick": "Изгони участник",
"localRecording": "Показване на контроли за локален запис",
"lockRoom": "Смяна парола на среща",
"moreActions": "Показване на меню с повече опции",
"moreActionsMenu": "Меню с повече опции",
"mute": "Пускане/спиране на видеото",
"pip": "Пускане на Картина-в-Картина",
"profile": "Редактиране на профила",
"raiseHand": "",
"recording": "",
"remoteMute": "",
"Settings": "",
"sharedvideo": "",
"raiseHand": "Смяна искане на думата",
"recording": "Пускане/спиране на запис",
"remoteMute": "Заглуши участник",
"Settings": "Промяна на настройки",
"sharedvideo": "Споделяне на YouTube видео",
"shareRoom": "",
"shareYourScreen": "",
"shortcuts": "",
"shareYourScreen": "Споделяне на екрана",
"shortcuts": "Бързи клавиши",
"show": "",
"speakerStats": "",
"speakerStats": "Показване на статистики за участниците",
"tileView": "",
"toggleCamera": "",
"videomute": "",
"videoblur": ""
"videomute": "Пускане/спиране на видеото",
"videoblur": "Пускане/спиране на замъгляване на видеото"
},
"addPeople": "Добавяне на участници в разговора",
"audioOnlyOff": "",
"audioOnlyOn": "",
"audioRoute": "",
"audioOnlyOff": "Спиране режима с нисък трафик",
"audioOnlyOn": "Пускане режима с нисък трафик",
"audioRoute": "Изберете устройство за звук",
"authenticate": "Идентификация",
"callQuality": "",
"callQuality": "Промяна качеството на видеото",
"chat": "Отваряне/затваряне на текстовите съобщения",
"closeChat": "",
"documentClose": "Отваряне/затваряне на споделен документ",
"documentOpen": "Отваряне/затваряне на споделен документ",
"enterFullScreen": "",
"enterTileView": "",
"exitFullScreen": "",
"exitTileView": "",
"feedback": "",
"closeChat": "Затваряне на съобщенията",
"documentClose": "Затваряне на споделеният документ",
"documentOpen": "Отваряне на споделен документ",
"enterFullScreen": "Вижте на цял екран",
"enterTileView": "Влизане в изглед галерия",
"exitFullScreen": "Изход от цял екран",
"exitTileView": "Спиране на изглед галерия",
"feedback": "Отзиви",
"hangup": "Напускане",
"invite": "Поканете участници",
"login": "Влез",
"logout": "Изход",
"lowerYourHand": "",
"moreActions": "",
"lowerYourHand": "Махни искането на думата",
"moreActions": "Още опции",
"mute": "Спиране/пускане на микрофона",
"openChat": "",
"pip": "",
"openChat": "Отвори съобщенията",
"pip": "Пусни Картина-в-Картина",
"profile": "Редактиране на профила",
"raiseHand": "Вдигане/сваляне на ръка",
"raiseYourHand": "Вдигни ръка.",
"raiseYourHand": "Поискай думата",
"Settings": "Настройки",
"sharedvideo": "Пускане/спиране на споделянето на екрана",
"shareRoom": "",
"shortcuts": "",
"speakerStats": "Статистика на говорителя",
"startScreenSharing": "",
"startSubtitles": "",
"stopScreenSharing": "",
"stopSubtitles": "",
"stopSharedVideo": "",
"shareRoom": "Добавете някого",
"shortcuts": "Виж бързите клавиши",
"speakerStats": "Статистика за говорителите",
"startScreenSharing": "Започни споделяне на екрана",
"startSubtitles": "Пускане на субтитри",
"stopScreenSharing": "Спиране споделяне на екрана",
"stopSubtitles": "Спиране на субтитри",
"stopSharedVideo": "Спиране на YouTube видео",
"talkWhileMutedPopup": "Опитвате се да говорите? В момента микрофонът Ви е заглушен.",
"tileViewToggle": "",
"toggleCamera": "",
"tileViewToggle": "Превключване на изглед галерия",
"toggleCamera": "Пускане/спиране на камера",
"videomute": "Пускане/спиране на камерата",
"startvideoblur": "",
"stopvideoblur": ""
},
"\u0005toolbar": {
"accessibilityLabel": {}
"startvideoblur": "Замъгли фона ми",
"stopvideoblur": "Спиране замъгляването на фона"
},
"transcribing": {
"ccButtonTooltip": "",
"error": "Грешка при опит за запис. Моля опитайте отново.",
"expandedLabel": "",
"failedToStart": "",
"labelToolTip": "",
"off": "",
"pending": "",
"start": "",
"stop": "",
"tr": ""
"ccButtonTooltip": "Пускане / Спиране на субтитри",
"error": "Грешка при опит за транскрибиране. Моля опитайте отново.",
"expandedLabel": "Транскрибирането е пуснато",
"failedToStart": "Транскрибирането не успя при пускане",
"labelToolTip": "Тази среща се транскрибира",
"off": "Транскрибирането спря",
"pending": "Стартира се транскрибиране на срещата...",
"start": "Започва показване на субтитри",
"stop": "Спира показване на субтитри",
"tr": "СУБ"
},
"\u0005transcribing": {},
"userMedia": {
"androidGrantPermissions": "Изберете <b><i>Разрешаване</i></b>, когато браузърът Ви помоли за разрешение.",
"chromeGrantPermissions": "Изберете <b><i>Разрешаване</i></b>, когато браузърът Ви помоли за разрешение.",
@@ -661,31 +650,34 @@
"safariGrantPermissions": "Изберете <b><i>Добре</i></b>, когато браузърът Ви помоли за разрешение."
},
"videoSIPGW": {
"busy": "",
"busyTitle": "",
"errorAlreadyInvited": "",
"errorInvite": "",
"errorInviteFailed": "",
"errorInviteFailedTitle": "",
"errorInviteTitle": "",
"pending": ""
"busy": "Работим по освобождаване на ресурси. Моля, опитайте след няколко минути.",
"busyTitle": "Услугата за стаи в момента е заета",
"errorAlreadyInvited": "{{displayName}} вече е поканен",
"errorInvite": "Конференцията не е стартирана. Моля, опитайте по-късно.",
"errorInviteFailed": "Работим по разрешаването на проблем. Моля, опитайте по-късно.",
"errorInviteFailedTitle": "Добавянето на {{displayName}} не успя",
"errorInviteTitle": "Грешка при добавяне на стая",
"pending": "{{displayName}} бе поканен"
},
"videoStatus": {
"audioOnly": "",
"audioOnlyExpanded": "",
"callQuality": "",
"audioOnly": "АУДИО",
"audioOnlyExpanded": "Вие сте в режим на нисък трафик. В този режим ще получавате само аудио или споделени екрани.",
"callQuality": "Качество на видеото",
"hd": "ВК",
"hdTooltip": "Гледате високо качество на видеото",
"highDefinition": "Високо качество",
"labelTooiltipNoVideo": "",
"labelTooltipAudioOnly": "Включен е режим само със звук",
"labelTooiltipNoVideo": "Няма видео",
"labelTooltipAudioOnly": "Пуснат режим на нисък трафик",
"ld": "НК",
"ldTooltip": "Виждате ниско качество на видеото",
"lowDefinition": "Ниско качество",
"onlyAudioAvailable": "",
"onlyAudioSupported": "",
"onlyAudioAvailable": "Само аудио е налично",
"onlyAudioSupported": "Този браузър поддържа само аудио.",
"p2pEnabled": "Вкл. директно свързване",
"p2pVideoQualityDescription": "",
"p2pVideoQualityDescription": "В директна връзка, получаваното качество може да се сменя между високо и само аудио. Останалите настройки ще са достъпни когато връзката не е директна.",
"recHighDefinitionOnly": "Ще се предпочита високо качество.",
"sd": "СК",
"sdTooltip": "Гледате стандартно качество на видеото",
"standardDefinition": "Стандартно качество"
},
"videothumbnail": {
@@ -693,38 +685,39 @@
"flip": "Огледално",
"kick": "Изгони",
"moderator": "Модератор",
"mute": "Учасника е с изключен микрофон",
"mute": "Участника е с изключен микрофон",
"muted": "Изключен микрофон",
"remoteControl": "Отдалечено управление",
"show": "",
"videomute": ""
"show": "Покажи на главния екран",
"videomute": "Участник е спрял камерата си"
},
"welcomepage": {
"accessibilityLabel": {
"join": "",
"join": "Натиснете за да влезете",
"roomname": "Въведете име на стаята"
},
"appDescription": "",
"appDescription": "Хайде на видео разговорите с целият ви екип. Всъщност, поканете всички познати. {{app}} е напълно защитено, 100% решение за видеоконференции с отворен код което може да ползвате по цял ден, всеки ден, безплатно - без да ви е нужна регистрация.",
"audioVideoSwitch": {
"audio": "",
"video": ""
"audio": "Глас",
"video": "Видео"
},
"calendar": "",
"connectCalendarButton": "",
"connectCalendarText": "",
"enterRoomTitle": "",
"calendar": "Календар",
"connectCalendarButton": "Свържете вашия календар",
"connectCalendarText": "Свържете вашия календар за да видите срещите си в {{app}}. Добавяйки {{provider}} срещите в календара си ще можете да ги старирате с едно докосване.",
"enterRoomTitle": "Започни нова среща",
"onlyAsciiAllowed": "Името на срещата може да съдържа само латински букви и цифри.",
"go": "НАПРЕД",
"join": "ПРИСЪЕДИНЯВАНЕ",
"info": "",
"info": "Информация",
"privacy": "Поверителност",
"recentList": "",
"recentListDelete": "",
"recentListEmpty": "",
"reducedUIText": "",
"recentList": "Скорошни срещи",
"recentListDelete": "Изтрий",
"recentListEmpty": "Списъка с скорошни срещи е празен. След като участвате в някоя среща, ще я намерите тук.",
"reducedUIText": "Добре дошли в {{app}}!",
"roomname": "Въведете име на стаята",
"roomnameHint": "",
"roomnameHint": "Въведете името или връзката на стаята в която искате да влезете. Също може да си измислите име. Само го споделете с някой, за да може и той да въведе същото име за да се срещнете.",
"sendFeedback": "Изпращане на отзиви",
"terms": "Условия",
"title": ""
"title": "Сигурна, с много възможности, и напълно безплатна платформа за видео конференции"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -22,7 +22,7 @@
"headphones": "Escotadors",
"phone": "Telefòn",
"speaker": "Nautparlaire",
"none": ""
"none": "Cap de periferic àudio pas disponible"
},
"audioOnly": {
"audioOnly": "Benda passanta febla"
@@ -182,7 +182,7 @@
"liveStreamingDisabledForGuestTooltip": "Los convidats pòdon pas aviar una difusion en dirècte",
"liveStreamingDisabledTooltip": "Difusion en dirècte desactivada.",
"lockMessage": "Impossible de verrolhar la conferéncia.",
"lockRoom": "",
"lockRoom": "Ajustar un $t(lockRoomPasswordUppercase) a la conferéncia",
"lockTitle": "Fracàs del verrolhatge",
"logoutQuestion": "Sètz segur que vos volètz desconnectar e arrestar la conferéncia ?",
"logoutTitle": "Desconnexion",
@@ -199,10 +199,10 @@
"muteParticipantDialog": "",
"muteParticipantTitle": "Copar lo micro als participants ?",
"Ok": "D'acòrdi",
"passwordLabel": "",
"passwordNotSupported": "Ajustar un senhal a una conferéncia es pas suportat.",
"passwordNotSupportedTitle": "",
"passwordRequired": "",
"passwordLabel": "SENHAL",
"passwordNotSupported": "Ajustar un $t(lockRoomPassword) a una conferéncia es pas suportat.",
"passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) pas suportat",
"passwordRequired": "$t(lockRoomPasswordUppercase) requesit",
"popupError": "Vòstre navigator bloca las fenèstras que sorgisson a partir d'aqueste site. Mercés d'activar aquelas fenèstras dins los paramètres de vòstre navigator e de tornar ensajar.",
"popupErrorTitle": "Fenèstra que sorgís blocada",
"recording": "Enregistrament",
@@ -217,7 +217,7 @@
"remoteControlStopMessage": "La session de contraròtle alonhat es acabada !",
"remoteControlTitle": "Contraròtle a distància",
"Remove": "Suprimir",
"removePassword": "",
"removePassword": "Suprimir lo",
"removeSharedVideoMsg": "Sètz segur que volètz suprimir vòstra vidèo partejada ?",
"removeSharedVideoTitle": "Suprimir la vidèo partejada",
"reservationError": "Error del sistèma de reservacion",
@@ -250,7 +250,7 @@
"tokenAuthFailed": "O planhèm, sètz pas autorizat a rejónher l'apèl.",
"tokenAuthFailedTitle": "Fracàs de l'autentificacion",
"transcribing": "Transcripcion",
"unlockRoom": "",
"unlockRoom": "Suprimir lo $t(lockRoomPassword) de la conferéncia",
"userPassword": "senhal utilizaire",
"WaitForHostMsg": "La conferéncia <b>{{room}}</b> a pas encara començat. Se sètz lòst volgatz ben vos identificar. Autrament esperatz quarribe lòste.",
"WaitForHostMsgWOk": "La conferéncia <b>{{room}}</b> a pas encara començat. Se sètz lòst volgatz ben clicar Ok per vos identificar. Autrament esperatz quarribe lòste.",
@@ -279,8 +279,8 @@
},
"info": {
"accessibilityLabel": "Mostrar las info",
"addPassword": "",
"cancelPassword": "",
"addPassword": "Ajustar un $t(lockRoomPassword)",
"cancelPassword": "Anullar lo $t(lockRoomPassword)",
"conferenceURL": "Ligam:",
"country": "País",
"dialANumber": "Per participar a la conferéncia, sonatz un daquestes numèros puèi picatz lo senhal.",
@@ -355,7 +355,9 @@
"getStreamKeyManually": "",
"invalidStreamKey": "La clau de difusion en dirècte es benlèu pas corrècta.",
"off": "La difusion en dirècte es estada arrestada",
"offBy": "",
"on": "La difusion en dirècte es estada arrestada",
"onBy": "",
"pending": "Començar lo dirècte...",
"serviceName": "Servici de difusion en dirècte",
"signedInAs": "Sètz connectat coma :",
@@ -416,8 +418,8 @@
"mutedTitle": "Sètz en mut !",
"mutedRemotelyTitle": "{{participantDisplayName}} vos a mes en silenci !",
"mutedRemotelyDescription": "",
"passwordRemovedRemotely": "",
"passwordSetRemotely": "",
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) tirat per un autre participant",
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) definit per un autre participant",
"raisedHand": "{{name}} volriá parlar.",
"somebody": "Qualqu'un",
"startSilentTitle": "Avètz jonch sens cap de sortida àudio !",
@@ -468,7 +470,9 @@
"live": "DIRÈCTE",
"loggedIn": "Session a {{userName}}",
"off": "Enregistrament arrestar",
"offBy": "",
"on": "Enregistrament",
"onBy": "",
"pending": "Preparacion de lenregistrament de la conferéncia...",
"rec": "ENRG",
"serviceDescription": "Vòstre enregistrament serà salvagardat pel servici dedicat.",
@@ -508,7 +512,7 @@
"alertOk": "Dacòrdi",
"alertTitle": "Avertiment",
"alertURLText": "LURL del servidor es pas valida",
"buildInfoSection": "",
"buildInfoSection": "Informacions de generacion",
"conferenceSection": "Conferéncia",
"displayName": "Escais-nom",
"email": "Corrièl",
@@ -553,7 +557,7 @@
"fullScreen": "Passar al ecran complèt",
"hangup": "Quitar la sonada",
"invite": "Convidar de monde",
"kick": "",
"kick": "Exclure un participan ",
"localRecording": "Passar al panèl denregistraments locals",
"lockRoom": "Tirar lo senhal de la conferéncia",
"moreActions": "Passar al menú mai daccions",
@@ -563,7 +567,7 @@
"profile": "Modificar vòstre perfil",
"raiseHand": "Demandar la paraula",
"recording": "Passar al enregistraments",
"remoteMute": "",
"remoteMute": "Copar lo son del participant",
"Settings": "Passar als paramètres",
"sharedvideo": "Passar al partatge de vidèo Youtube",
"shareRoom": "Convidar qualquun",
@@ -577,8 +581,8 @@
"videoblur": ""
},
"addPeople": "Ajustar de monde a vòstra sonada",
"audioOnlyOff": "",
"audioOnlyOn": "",
"audioOnlyOff": "Desactivar lo mòde connexion febla",
"audioOnlyOn": "Activar lo mòde connexion febla",
"audioRoute": "Seleccionar lo periferic àudio",
"authenticate": "Autentificatz-vos",
"callQuality": "Gerir la qualitat vidèo",
@@ -587,9 +591,9 @@
"documentClose": "Tampar los documents partejats",
"documentOpen": "Dobrir los documents partejats",
"enterFullScreen": "Veire lecran complèt",
"enterTileView": "",
"enterTileView": "Dintrar dins la vista mosaïca",
"exitFullScreen": "Sortir de lecran complèt",
"exitTileView": "",
"exitTileView": "Quitar la vista mosaïca",
"feedback": "Daissar un comentari",
"hangup": "Quitar",
"invite": "Convidar de monde",
@@ -617,8 +621,8 @@
"tileViewToggle": "Activar/Desactivar la vista en mosaïc",
"toggleCamera": "Passar a la camèra",
"videomute": "Aviar / Arrestar la camèra",
"startvideoblur": "",
"stopvideoblur": ""
"startvideoblur": "Trebolar mon rèire-plan",
"stopvideoblur": "Desactivar lo borrolatge del rèire-plan"
},
"transcribing": {
"ccButtonTooltip": "Aviar / Arrestat los sostítols",
@@ -656,13 +660,13 @@
},
"videoStatus": {
"audioOnly": "AUD",
"audioOnlyExpanded": "",
"audioOnlyExpanded": "Sètz en mòde connexion febla. Amb aqueste mòde recebretz pas que làudio e lo partatge decran.",
"callQuality": "Qualitat vidèo",
"hd": "HD",
"hdTooltip": "Difusion vidèo en nauta definicion",
"highDefinition": "Nauta definicion",
"labelTooiltipNoVideo": "Pas cap de vidèo",
"labelTooltipAudioOnly": "",
"labelTooltipAudioOnly": "Mòde connexion febla activat",
"ld": "Bassa definicion",
"ldTooltip": "Difusion vidèo en bassa definicion",
"lowDefinition": "Bassa definicion",
@@ -684,7 +688,7 @@
"muted": "Mut",
"remoteControl": "Contraròtle alonhat",
"show": "",
"videomute": ""
"videomute": "Lo participant a arrestat la camèra"
},
"welcomepage": {
"accessibilityLabel": {
@@ -698,11 +702,12 @@
},
"calendar": "Calendari",
"connectCalendarButton": "Connectar lo calendari",
"connectCalendarText": "",
"connectCalendarText": "Connectatz vòstre calendièr per veire vòstras reünions dins {{app}}. Ajustatz tanben las reünions de {{provider}} a vòstre calendièr e aviatz-las amb un sol clic.",
"enterRoomTitle": "Començar una nòva conferéncia",
"onlyAsciiAllowed": "",
"go": "Crear",
"join": "PARTICIPATZ",
"info": "",
"info": "Infor",
"privacy": "Vida privada",
"recentList": "Recents",
"recentListDelete": "Suprimits",

File diff suppressed because it is too large Load Diff

View File

@@ -21,10 +21,11 @@
"bluetooth": "Bluetooth",
"headphones": "Fones de ouvido",
"phone": "Celular",
"speaker": "Apresentador"
"speaker": "Alto-falantes",
"none": ""
},
"audioOnly": {
"audioOnly": "Somente áudio"
"audioOnly": "Largura de banda baixa"
},
"calendarSync": {
"addMeetingURL": "Adicionar um link da reunião",
@@ -49,9 +50,9 @@
"messagebox": "Digite uma mensagem",
"nickname": {
"popover": "Escolha um apelido",
"title": "Digite um apelido para usar o chat"
"title": "Digite um apelido para usar o bate-papo"
},
"title": "Chat"
"title": "Bate-papo"
},
"connectingOverlay": {
"joiningRoom": "Conectando você à reunião…"
@@ -96,8 +97,7 @@
"resolution": "Resolução:",
"status": "Conexão:",
"transport": "Transporte:",
"transport_plural": "Transportes:",
"turn": " (virar)"
"transport_plural": "Transportes:"
},
"dateUtils": {
"earlier": "Mais cedo",
@@ -107,7 +107,7 @@
"deepLinking": {
"appNotInstalled": "Você precisa do aplicativo móvel {{app}} para participar da reunião no seu telefone.",
"description": "Nada acontece? Estamos tentando iniciar sua reunião no aplicativo desktop {{app}}. Tente novamente ou inicie ele na aplicação web {{app}}.",
"descriptionWithoutWeb": "",
"descriptionWithoutWeb": "Nada aconteceu? Tentamos iniciar sua reunião no aplicativo de desktop {{app}}.",
"downloadApp": "Baixe o Aplicativo",
"launchWebButton": "Iniciar na web",
"openApp": "Continue na aplicação",
@@ -115,6 +115,7 @@
"tryAgainButton": "Tente novamente no desktop"
},
"defaultLink": "ex.: {{url}}",
"defaultNickname": "ex.: João Pedro",
"deviceError": {
"cameraError": "Falha ao acessar sua câmera",
"cameraPermission": "Erro ao obter permissão para a câmera",
@@ -132,7 +133,7 @@
"liveStreaming": "Transmissão ao vivo"
},
"allow": "Permitir",
"alreadySharedVideoMsg": "",
"alreadySharedVideoMsg": "Outro participante já está compartilhando um vídeo. Esta conferência permite apenas um vídeo compartilhado por vez.",
"alreadySharedVideoTitle": "Somente um vídeo compartilhado é permitido por vez",
"applicationWindow": "Janela de aplicativo",
"Back": "Voltar",
@@ -158,51 +159,51 @@
"contactSupport": "Contate o suporte",
"copy": "Copiar",
"dismiss": "Dispensar",
"displayNameRequired": "",
"displayNameRequired": "Oi! Qual o seu nome?",
"done": "Feito",
"enterDisplayName": "",
"enterDisplayName": "Digite seu nome aqui",
"error": "Erro",
"externalInstallationMsg": "Você precisa instalar nossa extensão de compartilhamento de tela.",
"externalInstallationTitle": "Extensão requerida",
"goToStore": "Vá para a loja virtual",
"gracefulShutdown": "O sistema está em manutenção. Por favor tente novamente mais tarde.",
"IamHost": "Eu sou o anfitrião",
"incorrectRoomLockPassword": "",
"incorrectRoomLockPassword": "Senha incorreta",
"incorrectPassword": "Usuário ou senha incorretos",
"inlineInstallationMsg": "Você precisa instalar nossa extensão de compartilhamento de tela.",
"inlineInstallExtension": "Instalar agora",
"internalError": "Oops! Alguma coisa está errada. O seguinte erro ocorreu: {{error}}",
"internalErrorTitle": "Erro interno",
"kickMessage": "",
"kickMessage": "Você pode contatar com {{participantDisplayName}} para obter mais detalhes.",
"kickParticipantButton": "Remover",
"kickParticipantDialog": "Tem certeza de que deseja remover este participante?",
"kickParticipantTitle": "Deixar mudo este participante?",
"kickTitle": "",
"kickParticipantTitle": "Chutar este participante?",
"kickTitle": "Ai! {{participantDisplayName}} expulsou você da reunião",
"liveStreaming": "Transmissão ao Vivo",
"liveStreamingDisabledForGuestTooltip": "Visitantes não podem iniciar transmissão ao vivo.",
"liveStreamingDisabledTooltip": "Iniciar transmissão ao vivo desativada.",
"lockMessage": "Falha ao travar a conferência.",
"lockRoom": "",
"lockRoom": "Adicionar reunião $t(lockRoomPasswordUppercase)",
"lockTitle": "Bloqueio falhou",
"logoutQuestion": "Deseja encerrar a sessão e finalizar a conferência?",
"logoutTitle": "Encerrar sessão",
"maxUsersLimitReached": "",
"maxUsersLimitReachedTitle": "",
"maxUsersLimitReached": "O limite para o número máximo de participantes foi atingido. A conferência está cheia. Entre em contato com o proprietário da reunião ou tente novamente mais tarde!",
"maxUsersLimitReachedTitle": "Limite máximo de participantes atingido",
"micConstraintFailedError": "Seu microfone não satisfaz algumas condições necessárias.",
"micNotFoundError": "O microfone não foi encontrado.",
"micNotSendingData": "",
"micNotSendingDataTitle": "",
"micNotSendingData": "Vá para as configurações do seu computador para ativar o som do microfone e ajustar seu nível",
"micNotSendingDataTitle": "Seu microfone está mudo pelas configurações do sistema",
"micPermissionDeniedError": "Não foi permitido acessar o seu microfone. Você ainda pode entrar na conferência, mas sem enviar áudio. Clique no botão do microfone para tentar reparar.",
"micUnknownError": "Não pode usar o microfone por uma razão desconhecida.",
"muteParticipantBody": "Você não está habilitado para tirar o mudo deles, mas eles podem tirar o mudo deles mesmos a qualquer tempo.",
"muteParticipantButton": "Mudo",
"muteParticipantDialog": "Tem certeza de que deseja silenciar este participante? Você não poderá desativar a opção silenciar dele, mas ele poderá fazer isso quando desejar.",
"muteParticipantDialog": "Tem certeza de que deseja silenciar este participante? Você não poderá desfazer isso, mas o participante pode reabilitar o áudio a qualquer momento.",
"muteParticipantTitle": "Deixar mudo este participante?",
"Ok": "Ok",
"passwordLabel": "",
"passwordNotSupported": "Configuração de senha para a reunião não é suportada.",
"passwordNotSupportedTitle": "",
"passwordRequired": "",
"passwordLabel": "$t(lockRoomPasswordUppercase)",
"passwordNotSupported": "A configuração de uma reunião $t(lockRoomPassword) não é suportada.",
"passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) não suportado",
"passwordRequired": "$t(lockRoomPasswordUppercase) requerido",
"popupError": "Seu navegador está bloqueando janelas popup deste site. Habilite os popups nas configurações de segurança no seu navegador e tente novamente.",
"popupErrorTitle": "Popup bloqueado",
"recording": "Gravando",
@@ -217,7 +218,7 @@
"remoteControlStopMessage": "A sessão de controle remoto terminou!",
"remoteControlTitle": "Conexão de área de trabalho remota",
"Remove": "Remover",
"removePassword": "",
"removePassword": "Remove $t(lockRoomPassword)",
"removeSharedVideoMsg": "Deseja remover seu vídeo compartilhado?",
"removeSharedVideoTitle": "Remover vídeo compartilhado",
"reservationError": "Erro de sistema de reserva",
@@ -250,7 +251,7 @@
"tokenAuthFailed": "Desculpe, você não está autorizado a entrar nesta chamada.",
"tokenAuthFailedTitle": "Falha de autenticação",
"transcribing": "Transcrevendo",
"unlockRoom": "",
"unlockRoom": "Remove a reunião $t(lockRoomPassword)",
"userPassword": "senha do usuário",
"WaitForHostMsg": "A conferência <b>{{room}}</b> ainda não começou. Se você é o anfitrião, faça a autenticação. Do contrário, aguarde a chegada do anfitrião.",
"WaitForHostMsgWOk": "A conferência <b>{{room}}</b> ainda não começou. Se você é o anfitrião, pressione Ok para autenticar. Do contrário, aguarde a chegada do anfitrião.",
@@ -279,8 +280,8 @@
},
"info": {
"accessibilityLabel": "Mostrar info",
"addPassword": "",
"cancelPassword": "",
"addPassword": "Adicione $t(lockRoomPassword)",
"cancelPassword": "Cancela $t(lockRoomPassword)",
"conferenceURL": "Link:",
"country": "País",
"dialANumber": "Para entrar na reunião, disque um desses números e depois insira o PIN.",
@@ -291,18 +292,18 @@
"dialInTollFree": "Chamada gratuita",
"genericError": "Oops, alguma coisa deu errado.",
"inviteLiveStream": "Para ver a transmissão ao vivo da reunião, clique no link: {{url}}",
"invitePhone": "",
"invitePhoneAlternatives": "",
"invitePhone": "Para participar por telefone, toque aqui: {{number}} ,, {{conferenceID}} # \\ n",
"invitePhoneAlternatives": "Procurando um número de discagem diferente?\nVeja os números de discagem da reunião: {{url}} \n\n\nSe você também estiver discando através de um telefone da sala, participe sem conectar-se ao áudio: {{silentUrl}}",
"inviteURLFirstPartGeneral": "Você foi convidado para uma reunião.",
"inviteURLFirstPartPersonal": "",
"inviteURLSecondPart": "",
"inviteURLFirstPartPersonal": "{{name}} está convidando você para uma reunião.\n",
"inviteURLSecondPart": "\nEntre na reunião:\n{{url}}\n",
"liveStreamURL": "Transmissão ao vivo:",
"moreNumbers": "Mais números",
"noNumbers": "Sem números de discagem.",
"noPassword": "Nenhum",
"noRoom": "Nenhuma sala foi especificada para entrar.",
"numbers": "Números de discagem",
"password": "",
"password": "$t(lockRoomPasswordUppercase):",
"title": "Compartilhar",
"tooltip": "Compartilhar link e discagem para esta reunião",
"label": "Informações da reunião"
@@ -335,7 +336,8 @@
"toggleFilmstrip": "Mostrar ou ocultar miniaturas de vídeo",
"toggleScreensharing": "Trocar entre câmera e compartilhamento de tela",
"toggleShortcuts": "Mostrar ou ocultar atalhos de teclado",
"videoMute": "Iniciar ou parar sua câmera"
"videoMute": "Iniciar ou parar sua câmera",
"videoQuality": "Gerenciar qualidade da chamada"
},
"liveStreaming": {
"busy": "Estamos trabalhando para liberar os recursos de transmissão. Tente novamente em alguns minutos.",
@@ -349,15 +351,17 @@
"errorLiveStreamNotEnabled": "Transmissão ao vivo não está ativada em {{email}}. Ative a transmissão ao vivo ou registre numa conta com transmissão ao vivo ativada.",
"expandedOff": "A transmissão ao vivo foi encerrada",
"expandedOn": "A reunião está sendo transmitida pelo YouTube.",
"expandedPending": "A transmissão ao vivo está sendo iniciada…",
"expandedPending": "Iniciando a transmissão ao vivo...",
"failedToStart": "Falha ao iniciar a transmissão ao vivo",
"getStreamKeyManually": "",
"getStreamKeyManually": "Não conseguimos buscar nenhuma transmissão ao vivo. Tente obter sua chave de transmissão ao vivo no YouTube.",
"invalidStreamKey": "A senha para transmissão ao vivo pode estar incorreta.",
"off": "Transmissão ao vivo encerrada",
"offBy": "",
"on": "Transmissão ao Vivo",
"onBy": "",
"pending": "Iniciando Transmissão ao Vivo...",
"serviceName": "Serviço de Transmissão ao Vivo",
"signedInAs": "Você está conectado atualmente como:",
"signedInAs": "Você está conectado como:",
"signIn": "Faça login no Google",
"signInCTA": "Faça login ou insira sua chave de transmissão ao vivo do YouTube.",
"signOut": "Sair",
@@ -367,16 +371,16 @@
},
"localRecording": {
"clientState": {
"off": "Off",
"on": "On",
"off": "Desligado",
"on": "Ligado",
"unknown": "Desconhecido"
},
"dialogTitle": "Controles da Gravação Local",
"duration": "Duração",
"durationNA": "N/A",
"durationNA": "N/D",
"encoding": "Codificando",
"label": "LOR",
"labelToolTip": "Gravação local está envolvida",
"labelToolTip": "Gravação local ativada",
"localRecording": "Gravação local",
"me": "Eu",
"messages": {
@@ -406,30 +410,30 @@
"focusFail": "{{component}} não disponĩvel - tente em {{ms}} seg.",
"grantedTo": "Direitos de moderador concedido para {{to}}!",
"invitedOneMember": "{{displayName}} foi convidado",
"invitedThreePlusMembers": "",
"invitedTwoMembers": "",
"kickParticipant": "",
"invitedThreePlusMembers": "{{name}} e {{count}} outros foram convidados",
"invitedTwoMembers": "{{first}} e {{second}} foram convidados",
"kickParticipant": "{{kicked}} foi chutado por {{kicker}}",
"me": "Eu",
"moderator": "Direitos de moderador concedidos!",
"muted": "Você iniciou uma conversa em mudo.",
"mutedTitle": "Você está mudo!",
"mutedRemotelyTitle": "",
"mutedRemotelyDescription": "",
"passwordRemovedRemotely": "",
"passwordSetRemotely": "",
"mutedRemotelyTitle": "Você foi silenciado por {{participantDisplayName}}!",
"mutedRemotelyDescription": "Você sempre pode ativar o som quando estiver pronto para falar. Retire o som quando terminar para manter o ruído longe da reunião.",
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) removido por outro participante",
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) definido por outro participante",
"raisedHand": "{{name}} gostaria de falar.",
"somebody": "Alguém",
"startSilentTitle": "",
"startSilentDescription": "",
"suboptimalExperienceDescription": "Eer ... temos medo de que sua experiência com o {{appName}} não seja tão boa aqui. Estamos procurando maneiras de melhorar isso, mas até lá tente usar um dos <a href='static/recommendedBrowsers.html' target='_blank'> navegadores totalmente compatíveis</a>.",
"startSilentTitle": "Você entrou sem saída de áudio!",
"startSilentDescription": "Volte à reunião para habilitar o áudio",
"suboptimalBrowserWarning": "",
"suboptimalExperienceTitle": "Alerta do navegador",
"unmute": "",
"unmute": "Ativar som",
"newDeviceCameraTitle": "Nova câmera detectada",
"newDeviceAudioTitle": "Novo dispositivo de áudio detectado",
"newDeviceAction": "Usar"
},
"passwordSetRemotely": "Definido por outro participante",
"passwordDigitsOnly": "",
"passwordDigitsOnly": "Até {{number}} dígitos",
"poweredby": "distribuído por",
"presenceStatus": {
"busy": "Ocupado",
@@ -443,7 +447,7 @@
"initializingCall": "Iniciando Chamada...",
"invited": "Convidar",
"rejected": "Rejeitado",
"ringing": "Chamando..."
"ringing": "Tocando..."
},
"profile": {
"setDisplayNameLabel": "Definir seu nome de exibição",
@@ -451,6 +455,7 @@
"setEmailLabel": "Definir seu email de gravatar",
"title": "Perfil"
},
"raisedHand": "Gostaria de falar",
"recording": {
"authDropboxText": "Enviar para o Dropbox.",
"availableSpace": "Espaço disponível: {{spaceLeft}} MB (aproximadamente {{duration}} minutos de gravação)",
@@ -466,12 +471,14 @@
"live": "AOVIVO",
"loggedIn": "Conectado como {{userName}}",
"off": "Gravação parada",
"offBy": "",
"on": "Gravando",
"onBy": "",
"pending": "Preparando para gravar a reunião...",
"rec": "REC",
"serviceDescription": "Sua gravação será salva pelo serviço de gravação",
"serviceName": "Serviço de gravação",
"signIn": "entrar",
"signIn": "Entrar",
"signOut": "Sair",
"unavailable": "Oops! O {{serviceName}} está indisponível. Estamos trabalhando para resolver o problema. Por favor, tente mais tarde.",
"unavailableTitle": "Gravação indisponível"
@@ -518,10 +525,10 @@
"version": "Versão"
},
"share": {
"dialInfoText": "",
"dialInfoText": "\n\n=====\n\nDeseja apenas discar no seu telefone?\n\n{{defaultDialInNumber}}Clique neste link para ver os números de telefone para esta reunião\n{{dialInfoPageUrl}}",
"mainText": "Clique no seguinte link para entrar na reunião:{{roomUrl}}\n"
},
"speaker": "Apresentador",
"speaker": "Alto-falantes",
"speakerStats": {
"hours": "{{count}}h",
"minutes": "{{count}}m",
@@ -543,7 +550,7 @@
"accessibilityLabel": {
"audioOnly": "Alternar para apenas áudio",
"audioRoute": "Selecionar o dispositivo de som",
"callQuality": "Gerenciar qualidade da chamada",
"callQuality": "Gerenciar qualidade do vídeo",
"cc": "Alternar legendas",
"chat": "Alternar para janela de chat",
"document": "Alternar para documento compartilhado",
@@ -567,19 +574,19 @@
"shareRoom": "Convidar alguém",
"shareYourScreen": "Alternar compartilhamento de tela",
"shortcuts": "Alternar atalhos",
"show": "",
"show": "Mostrar no palco",
"speakerStats": "Alternar estatísticas do apresentador",
"tileView": "Alternar visualização em blocos",
"toggleCamera": "Alternar câmera",
"videomute": "Alternar mudo do vídeo",
"videoblur": ""
"videoblur": "Alternar desfoque de vídeo"
},
"addPeople": "Adicionar pessoas à sua chamada",
"audioOnlyOff": "Desativar modo somente áudio",
"audioOnlyOn": "Desativar modo somente áudio",
"audioOnlyOff": "",
"audioOnlyOn": "",
"audioRoute": "Selecionar o dispositivo de som",
"authenticate": "Autenticar",
"callQuality": "Gerenciar qualidade da chamada",
"callQuality": "Gerenciar qualidade do vídeo",
"chat": "Abrir ou fechar o bate-papo",
"closeChat": "Fechar chat",
"documentClose": "Fechar documento compartilhado",
@@ -615,19 +622,19 @@
"tileViewToggle": "Alternar visualização em blocos",
"toggleCamera": "Alternar câmera",
"videomute": "Iniciar ou parar a câmera",
"startvideoblur": "",
"stopvideoblur": ""
"startvideoblur": "Desfocar meu plano de fundo",
"stopvideoblur": "Desativar desfoque de fundo"
},
"transcribing": {
"ccButtonTooltip": "Iniciar/parar legendas",
"error": "Transcrição falhou. Tente novamente.",
"expandedLabel": "Transcrição ligada",
"expandedLabel": "Transcrição ativada",
"failedToStart": "Transcrição falhou ao iniciar",
"labelToolTip": "A reunião esta sendo transcrita",
"off": "Transcrição parada",
"pending": "Preparando a transcrição da reunião...",
"start": "Iniciar / Parar de mostrar as legendas",
"stop": "Iniciar / Parar de mostrar as legendas",
"start": "Exibir legendas",
"stop": "Não exibir legendas",
"tr": "TR"
},
"userMedia": {
@@ -654,20 +661,23 @@
},
"videoStatus": {
"audioOnly": "AUD",
"audioOnlyExpanded": "Você está no modo somente áudio. Esse modo economiza internet mas não permite ver o vídeo dos outros.",
"callQuality": "",
"audioOnlyExpanded": "",
"callQuality": "Qualidade de vídeo",
"hd": "HD",
"hdTooltip": "Ver vídeo em alta definição",
"highDefinition": "Alta definição (HD)",
"labelTooiltipNoVideo": "Sem vídeo",
"labelTooltipAudioOnly": "Modo somente de áudio habilitado",
"labelTooltipAudioOnly": "",
"ld": "LD",
"ldTooltip": "Ver vídeo em baixa definição",
"lowDefinition": "Baixa definição (LD)",
"onlyAudioAvailable": "Somente áudio disponível",
"onlyAudioSupported": "Suportamos somente áudio neste navegador.",
"p2pEnabled": "Ponto-a-ponto habilitada",
"p2pVideoQualityDescription": "",
"p2pVideoQualityDescription": "No modo ponto a ponto, a qualidade do vídeo recebido só pode ser alternada entre alta e apenas áudio. Outras configurações não serão respeitadas até que o ponto a ponto seja encerrado.",
"recHighDefinitionOnly": "Preferência para alta definição",
"sd": "SD",
"sdTooltip": "Ver vídeo em definição padrão",
"standardDefinition": "Definição padrão"
},
"videothumbnail": {
@@ -678,8 +688,8 @@
"mute": "Participante está mudo",
"muted": "Mudo",
"remoteControl": "Controle remoto",
"show": "",
"videomute": ""
"show": "Mostrar no palco",
"videomute": "O participante parou a câmera"
},
"welcomepage": {
"accessibilityLabel": {
@@ -695,6 +705,7 @@
"connectCalendarButton": "Conectar seu calendário",
"connectCalendarText": "Conecte seu calendário para ver todas as reuniões em {{app}}. Além disso, adicione reuniões de {{provider}} ao seu calendário e inicie-as com apenas um clique.",
"enterRoomTitle": "Iniciar uma nova reunião",
"onlyAsciiAllowed": "",
"go": "IR",
"join": "Entrar",
"info": "Informações",
@@ -702,7 +713,7 @@
"recentList": "Recente",
"recentListDelete": "Remover",
"recentListEmpty": "Sua lista recente está vazia. As reuniões que você realizar serão exibidas aqui.",
"reducedUIText": "",
"reducedUIText": "Bem-vindo ao {{app}}!",
"roomname": "Digite o nome da sala",
"roomnameHint": "Digite o nome ou a URL da sala que você deseja entrar. Você pode digitar um nome, e apenas deixe para as pessoas que você quer se reunir digitem o mesmo nome.",
"sendFeedback": "Enviar comentários",

View File

@@ -46,13 +46,16 @@
"today": "Today"
},
"chat": {
"error": "Error: your message \"{{originalText}}\" was not sent. Reason: {{error}}",
"error": "Error: your message was not sent. Reason: {{error}}",
"messagebox": "Type a message",
"messageTo": "Private message to {{recipient}}",
"nickname": {
"popover": "Choose a nickname",
"title": "Enter a nickname to use chat"
},
"title": "Chat"
"privateNotice": "Private message to {{recipient}}",
"title": "Chat",
"you": "you"
},
"connectingOverlay": {
"joiningRoom": "Connecting you to your meeting..."
@@ -235,6 +238,10 @@
"screenSharingFirefoxPermissionDeniedError": "Something went wrong while we were trying to share your screen. Please make sure that you have given us permission to do so. ",
"screenSharingFirefoxPermissionDeniedTitle": "Oops! We werent able to start screen sharing!",
"screenSharingPermissionDeniedError": "Oops! Something went wrong with your screen sharing extension permissions. Please reload and try again.",
"sendPrivateMessage": "You recently received a private message. Did you intend to reply to that privately, or you want to send your message to the group?",
"sendPrivateMessageCancel": "Send to the group",
"sendPrivateMessageOk": "Send privately",
"sendPrivateMessageTitle": "Send privately?",
"serviceUnavailable": "Service unavailable",
"sessTerminated": "Call terminated",
"Share": "Share",
@@ -268,6 +275,9 @@
"dialOut": {
"statusMessage": "is now {{status}}"
},
"documentSharing" : {
"title": "Shared Document"
},
"feedback": {
"average": "Average",
"bad": "Bad",
@@ -362,7 +372,9 @@
"getStreamKeyManually": "We werent able to fetch any live streams. Try getting your live stream key from YouTube.",
"invalidStreamKey": "Live stream key may be incorrect.",
"off": "Live Streaming stopped",
"offBy": "{{name}} stopped the live streaming",
"on": "Live Streaming",
"onBy": "{{name}} started the live streaming",
"pending": "Starting Live Stream...",
"serviceName": "Live Streaming service",
"signedInAs": "You are currently signed in as:",
@@ -475,7 +487,9 @@
"live": "LIVE",
"loggedIn": "Logged in as {{userName}}",
"off": "Recording stopped",
"offBy": "{{name}} stopped the recording",
"on": "Recording",
"onBy": "{{name}} started the recording",
"pending": "Preparing to record the meeting...",
"rec": "REC",
"serviceDescription": "Your recording will be saved by the recording service",
@@ -556,9 +570,11 @@
"cc": "Toggle subtitles",
"chat": "Toggle chat window",
"document": "Toggle shared document",
"download": "Download our apps",
"feedback": "Leave feedback",
"fullScreen": "Toggle full screen",
"hangup": "Leave the call",
"help": "Help",
"invite": "Invite people",
"kick": "Kick participant",
"localRecording": "Toggle local recording controls",
@@ -567,6 +583,7 @@
"moreActionsMenu": "More actions menu",
"mute": "Toggle mute audio",
"pip": "Toggle Picture-in-Picture mode",
"privateMessage": "Send private message",
"profile": "Edit your profile",
"raiseHand": "Toggle raise hand",
"recording": "Toggle recording",
@@ -593,12 +610,14 @@
"closeChat": "Close chat",
"documentClose": "Close shared document",
"documentOpen": "Open shared document",
"download": "Download our apps",
"enterFullScreen": "View full screen",
"enterTileView": "Enter tile view",
"exitFullScreen": "Exit full screen",
"exitTileView": "Exit tile view",
"feedback": "Leave feedback",
"hangup": "Leave",
"help": "Help",
"invite": "Invite people",
"login": "Login",
"logout": "Logout",
@@ -607,6 +626,7 @@
"mute": "Mute / Unmute",
"openChat": "Open chat",
"pip": "Enter Picture-in-Picture mode",
"privateMessage": "Send private message",
"profile": "Edit your profile",
"raiseHand": "Raise / Lower your hand",
"raiseYourHand": "Raise your hand",
@@ -707,7 +727,7 @@
"connectCalendarButton": "Connect your calendar",
"connectCalendarText": "Connect your calendar to view all your meetings in {{app}}. Plus, add {{provider}} meetings to your calendar and start them with one click.",
"enterRoomTitle": "Start a new meeting",
"onlyAsciiAllowed": "Meeting name should only contain latin characters and numbers.",
"roomNameAllowedChars": "Meeting name should not contain any of these characters: ?, &, :, ', \", %, #.",
"go": "GO",
"join": "JOIN",
"info": "Info",

View File

@@ -15,7 +15,7 @@ import Filmstrip from './videolayout/Filmstrip';
import { getLocalParticipant } from '../../react/features/base/participants';
import { toggleChat } from '../../react/features/chat';
import { setEtherpadHasInitialzied } from '../../react/features/etherpad';
import { setDocumentUrl } from '../../react/features/etherpad';
import { setFilmstripVisible } from '../../react/features/filmstrip';
import { setNotificationsEnabled } from '../../react/features/notifications';
import {
@@ -240,10 +240,12 @@ UI.initEtherpad = name => {
return;
}
logger.log('Etherpad is enabled');
etherpadManager
= new EtherpadManager(config.etherpad_base, name, eventEmitter);
APP.store.dispatch(setEtherpadHasInitialzied());
etherpadManager = new EtherpadManager(eventEmitter);
const url = new URL(name, config.etherpad_base);
APP.store.dispatch(setDocumentUrl(url.toString()));
};
/**

View File

@@ -1,22 +1,12 @@
/* global $, APP, interfaceConfig */
import { setDocumentEditingState } from '../../../react/features/etherpad';
import { getSharedDocumentUrl, setDocumentEditingState } from '../../../react/features/etherpad';
import { getToolboxHeight } from '../../../react/features/toolbox';
import VideoLayout from '../videolayout/VideoLayout';
import LargeContainer from '../videolayout/LargeContainer';
import Filmstrip from '../videolayout/Filmstrip';
/**
* Etherpad options.
*/
const options = $.param({
showControls: true,
showChat: false,
showLineNumbers: true,
useMonospaceFont: false
});
/**
*
*/
@@ -70,13 +60,13 @@ class Etherpad extends LargeContainer {
/**
* Creates new Etherpad object
*/
constructor(domain, name) {
constructor(url) {
super();
const iframe = document.createElement('iframe');
iframe.id = 'etherpadIFrame';
iframe.src = `${domain + name}?${options}`;
iframe.src = url;
iframe.frameBorder = 0;
iframe.scrolling = 'no';
iframe.width = DEFAULT_WIDTH;
@@ -199,13 +189,7 @@ export default class EtherpadManager {
/**
*
*/
constructor(domain, name, eventEmitter) {
if (!domain || !name) {
throw new Error('missing domain or name');
}
this.domain = domain;
this.name = name;
constructor(eventEmitter) {
this.eventEmitter = eventEmitter;
this.etherpad = null;
}
@@ -228,7 +212,7 @@ export default class EtherpadManager {
* Create new Etherpad frame.
*/
openEtherpad() {
this.etherpad = new Etherpad(this.domain, this.name);
this.etherpad = new Etherpad(getSharedDocumentUrl(APP.store.getState));
VideoLayout.addLargeVideoContainer(
ETHERPAD_CONTAINER_TYPE,
this.etherpad

View File

@@ -273,7 +273,7 @@ LocalVideo.prototype._updateVideoElement = function() {
// case video does not autoplay.
const video = this.container.querySelector('video');
video && video.play();
video && !config.testing?.noAutoPlayVideo && video.play();
};
export default LocalVideo;

View File

@@ -7,6 +7,7 @@ import { Provider } from 'react-redux';
import { I18nextProvider } from 'react-i18next';
import { AtlasKitThemeProvider } from '@atlaskit/theme';
import { createThumbnailOffsetParentIsNullEvent, sendAnalytics } from '../../../react/features/analytics';
import { i18next } from '../../../react/features/base/i18n';
import {
JitsiParticipantConnectionStatus
@@ -486,6 +487,8 @@ RemoteVideo.prototype.hasVideoStarted = function() {
RemoteVideo.prototype.addRemoteStreamElement = function(stream) {
if (!this.container) {
logger.debug('Not attaching remote stream due to no container');
return;
}
@@ -498,6 +501,8 @@ RemoteVideo.prototype.addRemoteStreamElement = function(stream) {
}
if (!stream.getOriginalStream()) {
logger.debug('Remote video stream has no original stream');
return;
}
@@ -508,11 +513,31 @@ RemoteVideo.prototype.addRemoteStreamElement = function(stream) {
$(streamElement).hide();
// If the container is currently visible
// we attach the stream to the element.
if (!isVideo || (this.container.offsetParent !== null && isVideo)) {
this.waitForPlayback(streamElement, stream);
stream.attach(streamElement);
this.waitForPlayback(streamElement, stream);
stream.attach(streamElement);
// TODO: Remove once we verify that this.container.offsetParent === null was the reason for not attached video
// streams to the thumbnail.
if (isVideo && this.container.offsetParent === null) {
sendAnalytics(createThumbnailOffsetParentIsNullEvent(this.id));
const parentNodesDisplayProps = [
'#filmstripRemoteVideosContainer',
'#filmstripRemoteVideos',
'#remoteVideos',
'.filmstrip',
'#videospace',
'#videoconference_page',
'#react'
].map(selector => `${selector} - ${$(selector).css('display')}`);
const videoConferencePageParent = $('#videoconference_page').parent();
const reactDiv = document.getElementById('react');
parentNodesDisplayProps.push(
`${videoConferencePageParent.attr('class')} - ${videoConferencePageParent.css('display')}`);
parentNodesDisplayProps.push(`this.container - ${this.$container.css('display')}`);
logger.debug(`this.container.offsetParent is null [user: ${this.id}, ${
parentNodesDisplayProps.join(', ')}, #react.offsetParent - ${
reactDiv && reactDiv.offsetParent !== null ? 'not null' : 'null'}]`);
}
if (!isVideo) {

View File

@@ -199,7 +199,7 @@ SmallVideo.createStreamElement = function(stream) {
element.muted = true;
}
element.autoplay = true;
element.autoplay = !config.testing?.noAutoPlayVideo;
element.id = SmallVideo.getStreamElementID(stream);
return element;
@@ -511,7 +511,7 @@ SmallVideo.prototype.isCurrentlyOnLargeVideo = function() {
* or <tt>false</tt> otherwise.
*/
SmallVideo.prototype.isVideoPlayable = function() {
return this.videoStream && !this.isVideoMuted && !this.videoStream.isMuted();
return this.videoStream && !this.isVideoMuted && !APP.conference.isAudioOnly();
};
/**
@@ -520,40 +520,33 @@ SmallVideo.prototype.isVideoPlayable = function() {
* @return {number} one of <tt>DISPLAY_VIDEO</tt>,<tt>DISPLAY_AVATAR</tt>
* or <tt>DISPLAY_BLACKNESS_WITH_NAME</tt>.
*/
SmallVideo.prototype.selectDisplayMode = function() {
const isAudioOnly = APP.conference.isAudioOnly();
const tileViewEnabled = shouldDisplayTileView(APP.store.getState());
const isVideoPlayable = this.isVideoPlayable();
const hasVideo = Boolean(this.selectVideoElement().length);
SmallVideo.prototype.selectDisplayMode = function(input) {
// Display name is always and only displayed when user is on the stage
if (this.isCurrentlyOnLargeVideo() && !tileViewEnabled) {
return isVideoPlayable && !isAudioOnly ? DISPLAY_BLACKNESS_WITH_NAME : DISPLAY_AVATAR_WITH_NAME;
} else if (isVideoPlayable && hasVideo && !isAudioOnly) {
if (input.isCurrentlyOnLargeVideo && !input.tileViewEnabled) {
return input.isVideoPlayable && !input.isAudioOnly ? DISPLAY_BLACKNESS_WITH_NAME : DISPLAY_AVATAR_WITH_NAME;
} else if (input.isVideoPlayable && input.hasVideo && !input.isAudioOnly) {
// check hovering and change state to video with name
return this._isHovered() ? DISPLAY_VIDEO_WITH_NAME : DISPLAY_VIDEO;
return input.isHovered ? DISPLAY_VIDEO_WITH_NAME : DISPLAY_VIDEO;
}
// check hovering and change state to avatar with name
return this._isHovered() ? DISPLAY_AVATAR_WITH_NAME : DISPLAY_AVATAR;
return input.isHovered ? DISPLAY_AVATAR_WITH_NAME : DISPLAY_AVATAR;
};
/**
* Prints information about the current display mode.
* Computes information that determine the display mode.
*
* @param {string} mode - The current mode.
* @returns {void}
* @returns {Object}
*/
SmallVideo.prototype._printDisplayModeInfo = function(mode) {
const isAudioOnly = APP.conference.isAudioOnly();
const tileViewEnabled = shouldDisplayTileView(APP.store.getState());
const isVideoPlayable = this.isVideoPlayable();
const hasVideo = Boolean(this.selectVideoElement().length);
const displayModeInfo = {
isAudioOnly,
tileViewEnabled,
isVideoPlayable,
hasVideo,
SmallVideo.prototype.computeDisplayModeInput = function() {
return {
isCurrentlyOnLargeVideo: this.isCurrentlyOnLargeVideo(),
isHovered: this._isHovered(),
isAudioOnly: APP.conference.isAudioOnly(),
tileViewEnabled: shouldDisplayTileView(APP.store.getState()),
isVideoPlayable: this.isVideoPlayable(),
hasVideo: Boolean(this.selectVideoElement().length),
connectionStatus: APP.conference.getParticipantConnectionStatus(this.id),
mutedWhileDisconnected: this.mutedWhileDisconnected,
wasVideoPlayed: this.wasVideoPlayed,
@@ -561,8 +554,6 @@ SmallVideo.prototype._printDisplayModeInfo = function(mode) {
isVideoMuted: this.isVideoMuted,
videoStreamMuted: this.videoStream ? this.videoStream.isMuted() : 'no stream'
};
logger.debug(`Displaying ${mode} for ${this.id}, reason: [${JSON.stringify(displayModeInfo)}]`);
};
/**
@@ -596,8 +587,10 @@ SmallVideo.prototype.updateView = function() {
const oldDisplayMode = this.displayMode;
let displayModeString = '';
const displayModeInput = this.computeDisplayModeInput();
// Determine whether video, avatar or blackness should be displayed
this.displayMode = this.selectDisplayMode();
this.displayMode = this.selectDisplayMode(displayModeInput);
switch (this.displayMode) {
case DISPLAY_AVATAR_WITH_NAME:
@@ -624,7 +617,7 @@ SmallVideo.prototype.updateView = function() {
}
if (this.displayMode !== oldDisplayMode) {
this._printDisplayModeInfo(displayModeString);
logger.debug(`Displaying ${displayModeString} for ${this.id}, data: [${JSON.stringify(displayModeInput)}]`);
}
};

View File

@@ -200,7 +200,11 @@ const VideoLayout = {
const id = stream.getParticipantId();
const remoteVideo = remoteVideos[id];
logger.debug(`Received a new ${stream.getType()} stream for ${id}`);
if (!remoteVideo) {
logger.debug('No remote video element to add stream');
return;
}

4179
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -35,10 +35,11 @@
"@atlaskit/tooltip": "12.1.13",
"@microsoft/microsoft-graph-client": "1.1.0",
"@react-native-community/async-storage": "1.3.4",
"@react-native-community/google-signin": "3.0.1",
"@react-native-community/netinfo": "4.1.5",
"@svgr/webpack": "4.3.2",
"@tensorflow-models/body-pix": "^1.0.1",
"@tensorflow/tfjs": "^1.1.2",
"@tensorflow-models/body-pix": "1.1.2",
"@tensorflow/tfjs": "1.2.9",
"@webcomponents/url": "0.7.1",
"amplitude-js": "4.5.2",
"bc-css-flags": "3.0.0",
@@ -48,7 +49,7 @@
"i18next-browser-languagedetector": "3.0.1",
"i18next-xhr-backend": "3.0.0",
"jQuery-Impromptu": "github:trentrichardson/jQuery-Impromptu#v6.0.0",
"jitsi-meet-logger": "github:jitsi/jitsi-meet-logger#a885cc98688ef2c3972284bda901596a26ffee52",
"jitsi-meet-logger": "github:jitsi/jitsi-meet-logger#5ec92357570dc8f0b7ffc1528820721c84c6af8b",
"jquery": "3.4.0",
"jquery-contextmenu": "2.4.5",
"jquery-i18next": "1.2.1",
@@ -56,22 +57,21 @@
"js-utils": "github:jitsi/js-utils#192b1c996e8c05530eb1f19e82a31069c3021e31",
"jsrsasign": "8.0.12",
"jwt-decode": "2.2.0",
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#f43c0c4bbfeb09ed816356eb5088bd61d40b91d5",
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#cdd2029b4b6b3626658f9834c324e1ffb7474795",
"libflacjs": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d",
"lodash": "4.17.13",
"moment": "2.19.4",
"moment-duration-format": "2.2.2",
"postis": "2.2.0",
"react": "16.8.6",
"react-dom": "16.8.6",
"react": "16.9",
"react-dom": "16.9",
"react-emoji-render": "1.0.0",
"react-i18next": "10.11.4",
"react-linkify": "1.0.0-alpha",
"react-native": "0.60.5",
"react-native": "0.61.1",
"react-native-background-timer": "2.1.1",
"react-native-calendar-events": "github:jitsi/react-native-calendar-events#902e6e92d6bae450a6052f76ba4d02f977ffd8f2",
"react-native-callstats": "3.61.0",
"react-native-google-signin": "2.0.0",
"react-native-immersive": "2.0.0",
"react-native-keep-awake": "4.0.0",
"react-native-linear-gradient": "2.5.6",
@@ -80,13 +80,14 @@
"react-native-svg-transformer": "0.13.0",
"react-native-swipeout": "2.3.6",
"react-native-watch-connectivity": "0.2.0",
"react-native-webrtc": "github:react-native-webrtc/react-native-webrtc#b1275ccf1e0e083d2a5c238e7d21c37657766463",
"react-native-webview": "5.8.1",
"react-native-webrtc": "github:react-native-webrtc/react-native-webrtc#a12a6cdfdefe53d03b388394e4cf10966bd99fca",
"react-native-webview": "7.4.1",
"react-redux": "7.1.0",
"react-textarea-autosize": "7.1.0",
"react-transition-group": "2.4.0",
"redux": "4.0.4",
"redux-thunk": "2.2.0",
"rnnoise-wasm": "github:jitsi/rnnoise-wasm.git#db96d11f175a22ef56c7db1ba9550835b716e615",
"styled-components": "3.4.9",
"util": "0.12.1",
"uuid": "3.1.0",
@@ -117,18 +118,18 @@
"eslint-plugin-react": "7.11.1",
"eslint-plugin-react-native": "3.3.0",
"expose-loader": "0.7.5",
"flow-bin": "0.98.0",
"flow-bin": "0.104.0",
"imports-loader": "0.7.1",
"jetifier": "1.6.4",
"metro-react-native-babel-preset": "0.56.0",
"node-sass": "4.10.0",
"node-sass": "4.12.0",
"precommit-hook": "3.0.0",
"string-replace-loader": "2.1.1",
"style-loader": "0.19.0",
"webpack": "4.26.1",
"webpack": "4.27.1",
"webpack-bundle-analyzer": "3.4.1",
"webpack-cli": "3.1.2",
"webpack-dev-server": "3.1.14"
"webpack-dev-server": "3.8.2"
},
"engines": {
"node": ">=8.0.0",

View File

@@ -692,6 +692,21 @@ export function createSyncTrackStateEvent(mediaType, muted) {
};
}
/**
* Creates an event that indicates the thumbnail offset parent is null.
*
* @param {string} id - The id of the user related to the thumbnail.
* @returns {Object} The event in a format suitable for sending via sendAnalytics.
*/
export function createThumbnailOffsetParentIsNullEvent(id) {
return {
action: 'OffsetParentIsNull',
attributes: {
id
}
};
}
/**
* Creates an event associated with a toolbar button being clicked/pressed. By
* convention, where appropriate an attribute named 'enable' should be used to

View File

@@ -15,6 +15,7 @@ import { connect, disconnect, setLocationURL } from '../base/connection';
import { loadConfig } from '../base/lib-jitsi-meet';
import { createDesiredLocalTracks } from '../base/tracks';
import {
getBackendSafeRoomName,
getLocationContextRoot,
parseURIString,
toURLString
@@ -85,7 +86,7 @@ export function appNavigate(uri: ?string) {
let url = `${baseURL}config.js`;
// XXX In order to support multiple shards, tell the room to the deployment.
room && (url += `?room=${room.toLowerCase()}`);
room && (url += `?room=${getBackendSafeRoomName(room)}`);
let config;

View File

@@ -16,7 +16,7 @@ import {
} from '../../base/dialog';
import { translate } from '../../base/i18n';
import { JitsiConnectionErrors } from '../../base/lib-jitsi-meet';
import { StyleType } from '../../base/styles';
import type { StyleType } from '../../base/styles';
import { authenticateAndUpgradeRole, cancelLogin } from '../actions';
import styles from './styles';

View File

@@ -42,6 +42,6 @@ export default class AbstractStatelessAvatar<P: Props> extends PureComponent<P>
* @returns {boolean}
*/
_isIcon(iconProp: ?string | ?Object): boolean {
return Boolean(iconProp) && typeof iconProp === 'object';
return Boolean(iconProp) && (typeof iconProp === 'object' || typeof iconProp === 'function');
}
}

View File

@@ -153,6 +153,8 @@ class ColorSchemeRegistry {
const colorScheme = toState(stateful)['features/base/color-scheme'];
return {
...defaultScheme._defaultTheme,
...colorScheme._defaultTheme,
...defaultScheme[componentName],
...colorScheme[componentName]
}[colorDefinition];

View File

@@ -6,18 +6,26 @@ import { ColorPalette, getRGBAFormat } from '../styles';
* The default color scheme of the application.
*/
export default {
'BottomSheet': {
'_defaultTheme': {
// Generic app theme colors that are used accross the entire app.
// All scheme definitions below inherit these values.
background: 'rgb(255, 255, 255)',
icon: '#1c2025',
label: '#1c2025'
icon: 'rgb(28, 32, 37)',
text: 'rgb(28, 32, 37)'
},
'Chat': {
displayName: 'rgb(94, 109, 121)',
localMsgBackground: 'rgb(215, 230, 249)',
privateMsgBackground: 'rgb(250, 219, 219)',
privateMsgNotice: 'rgb(186, 39, 58)',
remoteMsgBackground: 'rgb(241, 242, 246)',
replyBorder: 'rgb(219, 197, 200)',
replyIcon: 'rgb(94, 109, 121)'
},
'Dialog': {
background: 'rgb(255, 255, 255)',
border: 'rgba(0, 3, 6, 0.6)',
buttonBackground: ColorPalette.blue,
buttonLabel: ColorPalette.white,
icon: '#1c2025',
text: '#1c2025'
buttonLabel: ColorPalette.white
},
'Header': {
background: ColorPalette.blue,
@@ -30,8 +38,7 @@ export default {
background: 'rgb(42, 58, 75)'
},
'LoadConfigOverlay': {
background: 'rgb(249, 249, 249)',
text: 'rgb(28, 32, 37)'
background: 'rgb(249, 249, 249)'
},
'Thumbnail': {
activeParticipantHighlight: 'rgb(81, 214, 170)',

View File

@@ -23,7 +23,10 @@ import {
participantUpdated
} from '../participants';
import { getLocalTracks, trackAdded, trackRemoved } from '../tracks';
import { getJitsiMeetGlobalNS } from '../util';
import {
getBackendSafeRoomName,
getJitsiMeetGlobalNS
} from '../util';
import {
AUTH_STATUS_CHANGED,
@@ -74,6 +77,11 @@ declare var APP: Object;
* @returns {void}
*/
function _addConferenceListeners(conference, dispatch) {
// A simple logger for conference errors received through
// the listener. These errors are not handled now, but logged.
conference.on(JitsiConferenceEvents.CONFERENCE_ERROR,
error => logger.error('Conference error.', error));
// Dispatches into features/base/conference follow:
conference.on(
@@ -388,8 +396,7 @@ export function createConference() {
const conference
= connection.initJitsiConference(
// XXX Lib-jitsi-meet does not accept uppercase letters.
room.toLowerCase(), {
getBackendSafeRoomName(room), {
...state['features/base/config'],
applicationName: getName(),
getWiFiStatsMethod: getJitsiMeetGlobalNS().getWiFiStats,

View File

@@ -0,0 +1,137 @@
/**
* The config keys to whitelist, the keys that can be overridden.
* Currently we can only whitelist the first part of the properties, like
* 'p2p.useStunTurn' and 'p2p.enabled' we whitelist all p2p options.
* The whitelist is used only for config.js.
*
* @type Array
*/
export default [
'_desktopSharingSourceDevice',
'_peerConnStatusOutOfLastNTimeout',
'_peerConnStatusRtcMuteTimeout',
'abTesting',
'analytics.disabled',
'autoRecord',
'autoRecordToken',
'avgRtpStatsN',
'callFlowsEnabled',
'callStatsConfIDNamespace',
'callStatsID',
'callStatsSecret',
/**
* The display name of the CallKit call representing the conference/meeting
* associated with this config.js including while the call is ongoing in the
* UI presented by CallKit and in the system-wide call history. The property
* is meant for use cases in which the room name is not desirable as a
* display name for CallKit purposes and the desired display name is not
* provided in the form of a JWT callee. As the value is associated with a
* conference/meeting, the value makes sense not as a deployment-wide
* configuration, only as a runtime configuration override/overwrite
* provided by, for example, Jitsi Meet SDK for iOS.
*
* @type string
*/
'callDisplayName',
/**
* The handle
* ({@link https://developer.apple.com/documentation/callkit/cxhandle}) of
* the CallKit call representing the conference/meeting associated with this
* config.js. The property is meant for use cases in which the room URL is
* not desirable as the handle for CallKit purposes. As the value is
* associated with a conference/meeting, the value makes sense not as a
* deployment-wide configuration, only as a runtime configuration
* override/overwrite provided by, for example, Jitsi Meet SDK for iOS.
*
* @type string
*/
'callHandle',
/**
* The UUID of the CallKit call representing the conference/meeting
* associated with this config.js. The property is meant for use cases in
* which Jitsi Meet is to work with a CallKit call created outside of Jitsi
* Meet and to be adopted by Jitsi Meet such as, for example, an incoming
* and/or outgoing CallKit call created by Jitsi Meet SDK for iOS
* clients/consumers prior to giving control to Jitsi Meet. As the value is
* associated with a conference/meeting, the value makes sense not as a
* deployment-wide configuration, only as a runtime configuration
* override/overwrite provided by, for example, Jitsi Meet SDK for iOS.
*
* @type string
*/
'callUUID',
'channelLastN',
'constraints',
'debug',
'debugAudioLevels',
'defaultLanguage',
'desktopSharingChromeDisabled',
'desktopSharingChromeExtId',
'desktopSharingChromeMinExtVersion',
'desktopSharingChromeSources',
'desktopSharingFrameRate',
'desktopSharingFirefoxDisabled',
'desktopSharingSources',
'disable1On1Mode',
'disableAEC',
'disableAGC',
'disableAP',
'disableAudioLevels',
'disableDeepLinking',
'disableH264',
'disableHPF',
'disableNS',
'disableRemoteControl',
'disableRtx',
'disableSuspendVideo',
'displayJids',
'e2eping',
'enableDisplayNameInStats',
'enableLayerSuspension',
'enableLipSync',
'disableLocalVideoFlip',
'enableRemb',
'enableStatsID',
'enableTalkWhileMuted',
'enableTcc',
'etherpad_base',
'failICE',
'fileRecordingsEnabled',
'firefox_fake_device',
'forceJVB121Ratio',
'gatherStats',
'googleApiApplicationClientID',
'hiddenDomain',
'hosts',
'iAmRecorder',
'iAmSipGateway',
'iceTransportPolicy',
'ignoreStartMuted',
'liveStreamingEnabled',
'localRecording',
'minParticipants',
'nick',
'openBridgeChannel',
'p2p',
'preferH264',
'requireDisplayName',
'resolution',
'startAudioMuted',
'startAudioOnly',
'startBitrate',
'startSilent',
'startScreenSharing',
'startVideoMuted',
'startWithVideoMuted',
'subject',
'testing',
'useIPv6',
'useNicks',
'useStunTurn',
'webrtcIceTcpDisable',
'webrtcIceUdpDisable'
];

View File

@@ -2,152 +2,12 @@
import _ from 'lodash';
import CONFIG_WHITELIST from './configWhitelist';
import { _CONFIG_STORE_PREFIX } from './constants';
import INTERFACE_CONFIG_WHITELIST from './interfaceConfigWhitelist';
import parseURLParams from './parseURLParams';
import logger from './logger';
declare var $: Object;
/**
* The config keys to whitelist, the keys that can be overridden.
* Currently we can only whitelist the first part of the properties, like
* 'p2p.useStunTurn' and 'p2p.enabled' we whitelist all p2p options.
* The whitelist is used only for config.js.
*
* @private
* @type Array
*/
const WHITELISTED_KEYS = [
'_desktopSharingSourceDevice',
'_peerConnStatusOutOfLastNTimeout',
'_peerConnStatusRtcMuteTimeout',
'abTesting',
'analytics.disabled',
'autoRecord',
'autoRecordToken',
'avgRtpStatsN',
'callFlowsEnabled',
'callStatsConfIDNamespace',
'callStatsID',
'callStatsSecret',
/**
* The display name of the CallKit call representing the conference/meeting
* associated with this config.js including while the call is ongoing in the
* UI presented by CallKit and in the system-wide call history. The property
* is meant for use cases in which the room name is not desirable as a
* display name for CallKit purposes and the desired display name is not
* provided in the form of a JWT callee. As the value is associated with a
* conference/meeting, the value makes sense not as a deployment-wide
* configuration, only as a runtime configuration override/overwrite
* provided by, for example, Jitsi Meet SDK for iOS.
*
* @type string
*/
'callDisplayName',
/**
* The handle
* ({@link https://developer.apple.com/documentation/callkit/cxhandle}) of
* the CallKit call representing the conference/meeting associated with this
* config.js. The property is meant for use cases in which the room URL is
* not desirable as the handle for CallKit purposes. As the value is
* associated with a conference/meeting, the value makes sense not as a
* deployment-wide configuration, only as a runtime configuration
* override/overwrite provided by, for example, Jitsi Meet SDK for iOS.
*
* @type string
*/
'callHandle',
/**
* The UUID of the CallKit call representing the conference/meeting
* associated with this config.js. The property is meant for use cases in
* which Jitsi Meet is to work with a CallKit call created outside of Jitsi
* Meet and to be adopted by Jitsi Meet such as, for example, an incoming
* and/or outgoing CallKit call created by Jitsi Meet SDK for iOS
* clients/consumers prior to giving control to Jitsi Meet. As the value is
* associated with a conference/meeting, the value makes sense not as a
* deployment-wide configuration, only as a runtime configuration
* override/overwrite provided by, for example, Jitsi Meet SDK for iOS.
*
* @type string
*/
'callUUID',
'channelLastN',
'constraints',
'debug',
'debugAudioLevels',
'defaultLanguage',
'desktopSharingChromeDisabled',
'desktopSharingChromeExtId',
'desktopSharingChromeMinExtVersion',
'desktopSharingChromeSources',
'desktopSharingFrameRate',
'desktopSharingFirefoxDisabled',
'desktopSharingSources',
'disable1On1Mode',
'disableAEC',
'disableAGC',
'disableAP',
'disableAudioLevels',
'disableDeepLinking',
'disableH264',
'disableHPF',
'disableNS',
'disableRemoteControl',
'disableRtx',
'disableSuspendVideo',
'displayJids',
'e2eping',
'enableDisplayNameInStats',
'enableLayerSuspension',
'enableLipSync',
'disableLocalVideoFlip',
'enableRemb',
'enableStatsID',
'enableTalkWhileMuted',
'enableTcc',
'etherpad_base',
'failICE',
'fileRecordingsEnabled',
'firefox_fake_device',
'forceJVB121Ratio',
'gatherStats',
'googleApiApplicationClientID',
'hiddenDomain',
'hosts',
'iAmRecorder',
'iAmSipGateway',
'iceTransportPolicy',
'ignoreStartMuted',
'liveStreamingEnabled',
'localRecording',
'minParticipants',
'nick',
'openBridgeChannel',
'p2p',
'preferH264',
'requireDisplayName',
'resolution',
'startAudioMuted',
'startAudioOnly',
'startBitrate',
'startSilent',
'startScreenSharing',
'startVideoMuted',
'startWithAudioMuted',
'startWithVideoMuted',
'subject',
'testing',
'useIPv6',
'useNicks',
'useStunTurn',
'webrtcIceTcpDisable',
'webrtcIceUdpDisable'
];
// XXX The functions getRoomName and parseURLParams are split out of
// functions.js because they are bundled in both app.bundle and
// do_external_connect, webpack 1 does not support tree shaking, and we don't
@@ -178,69 +38,6 @@ export function createFakeConfig(baseURL: string) {
};
}
/**
* Promise wrapper on obtain config method. When HttpConfigFetch will be moved
* to React app it's better to use load config instead.
*
* @param {string} location - URL of the domain from which the config is to be
* obtained.
* @param {string} room - Room name.
* @private
* @returns {Promise<void>}
*/
export function obtainConfig(location: string, room: string): Promise<void> {
return new Promise((resolve, reject) =>
_obtainConfig(location, room, (success, error) => {
success ? resolve() : reject(error);
})
);
}
/**
* Sends HTTP POST request to specified {@code endpoint}. In request the name
* of the room is included in JSON format:
* {
* "rooomName": "someroom12345"
* }.
*
* @param {string} endpoint - The name of HTTP endpoint to which to send
* the HTTP POST request.
* @param {string} roomName - The name of the conference room for which config
* is requested.
* @param {Function} complete - The callback to invoke upon success or failure.
* @returns {void}
*/
function _obtainConfig(endpoint: string, roomName: string, complete: Function) {
logger.info(`Send config request to ${endpoint} for room: ${roomName}`);
$.ajax(
endpoint,
{
contentType: 'application/json',
data: JSON.stringify({ roomName }),
dataType: 'json',
method: 'POST',
error(jqXHR, textStatus, errorThrown) {
logger.error('Get config error: ', jqXHR, errorThrown);
complete(false, `Get config response status: ${textStatus}`);
},
success(data) {
const { config, interfaceConfig, loggingConfig } = window;
try {
overrideConfigJSON(
config, interfaceConfig, loggingConfig,
data);
complete(true);
} catch (e) {
logger.error('Parse config error: ', e);
complete(false, e);
}
}
}
);
}
/* eslint-disable max-params, no-shadow */
/**
@@ -306,8 +103,8 @@ export function overrideConfigJSON(
/* eslint-enable max-params, no-shadow */
/**
* Whitelist only config.js, skips this for others configs
* (interfaceConfig, loggingConfig).
* Apply whitelist filtering for configs with whitelists, skips this for others
* configs (loggingConfig).
* Only extracts overridden values for keys we allow to be overridden.
*
* @param {string} configName - The config name, one of config,
@@ -318,11 +115,13 @@ export function overrideConfigJSON(
* that are whitelisted.
*/
function _getWhitelistedJSON(configName, configJSON) {
if (configName !== 'config') {
return configJSON;
if (configName === 'interfaceConfig') {
return _.pick(configJSON, INTERFACE_CONFIG_WHITELIST);
} else if (configName === 'config') {
return _.pick(configJSON, CONFIG_WHITELIST);
}
return _.pick(configJSON, WHITELISTED_KEYS);
return configJSON;
}
/**

View File

@@ -11,8 +11,8 @@ export * from './functions.any';
* @returns {void}
*/
export function _cleanupConfig(config: Object) {
config.analytics.scriptURLs = [];
if (NativeModules.AppInfo.LIBRE_BUILD) {
config.analytics.scriptURLs = [];
delete config.analytics.amplitudeAPPKey;
delete config.analytics.googleAnalyticsTrackingId;
delete config.callStatsID;

View File

@@ -1,6 +1,6 @@
/* @flow */
// @flow
declare var config: Object;
import { getBackendSafeRoomName } from '../util';
/**
* Builds and returns the room name.
@@ -8,22 +8,10 @@ declare var config: Object;
* @returns {string}
*/
export default function getRoomName(): ?string {
const { getroomnode } = config;
const path = window.location.pathname;
let roomName;
// Determine the room node from the URL.
if (getroomnode && typeof getroomnode === 'function') {
roomName = getroomnode.call(config, path);
} else {
// Fall back to the default strategy of making assumptions about how the
// URL maps to the room (name). It currently assumes a deployment in
// which the last non-directory component of the path (name) is the
// room.
roomName
= path.substring(path.lastIndexOf('/') + 1).toLowerCase()
|| undefined;
}
// The last non-directory component of the path (name) is the room.
const roomName = path.substring(path.lastIndexOf('/') + 1) || undefined;
return roomName;
return getBackendSafeRoomName(roomName);
}

View File

@@ -0,0 +1,70 @@
/**
* The interface config keys to whitelist, the keys that can be overridden.
*
* @private
* @type Array
*/
export default [
'ANDROID_APP_PACKAGE',
'APP_NAME',
'APP_SCHEME',
'AUDIO_LEVEL_PRIMARY_COLOR',
'AUDIO_LEVEL_SECONDARY_COLOR',
'AUTHENTICATION_ENABLE',
'AUTO_PIN_LATEST_SCREEN_SHARE',
'BRAND_WATERMARK_LINK',
'CLOSE_PAGE_GUEST_HINT',
'CONNECTION_INDICATOR_AUTO_HIDE_ENABLED',
'CONNECTION_INDICATOR_AUTO_HIDE_TIMEOUT',
'CONNECTION_INDICATOR_DISABLED',
'DEFAULT_BACKGROUND',
'DEFAULT_LOCAL_DISPLAY_NAME',
'DEFAULT_REMOTE_DISPLAY_NAME',
'DISABLE_DOMINANT_SPEAKER_INDICATOR',
'DISABLE_FOCUS_INDICATOR',
'DISABLE_RINGING',
'DISABLE_TRANSCRIPTION_SUBTITLES',
'DISABLE_VIDEO_BACKGROUND',
'DISPLAY_WELCOME_PAGE_CONTENT',
'ENABLE_FEEDBACK_ANIMATION',
'ENFORCE_NOTIFICATION_AUTO_DISMISS_TIMEOUT',
'FILM_STRIP_MAX_HEIGHT',
'GENERATE_ROOMNAMES_ON_WELCOME_PAGE',
'INDICATOR_FONT_SIZES',
'INITIAL_TOOLBAR_TIMEOUT',
'INVITATION_POWERED_BY',
'JITSI_WATERMARK_LINK',
'LANG_DETECTION',
'LIVE_STREAMING_HELP_LINK',
'LOCAL_THUMBNAIL_RATIO',
'MAXIMUM_ZOOMING_COEFFICIENT',
'MOBILE_APP_PROMO',
'MOBILE_DOWNLOAD_LINK_ANDROID',
'MOBILE_DOWNLOAD_LINK_IOS',
'MOBILE_DYNAMIC_LINK',
'NATIVE_APP_NAME',
'OPTIMAL_BROWSERS',
'PHONE_NUMBER_REGEX',
'POLICY_LOGO',
'PROVIDER_NAME',
'RANDOM_AVATAR_URL_PREFIX',
'RANDOM_AVATAR_URL_SUFFIX',
'RECENT_LIST_ENABLED',
'REMOTE_THUMBNAIL_RATIO',
'SETTINGS_SECTIONS',
'SHOW_BRAND_WATERMARK',
'SHOW_DEEP_LINKING_IMAGE',
'SHOW_JITSI_WATERMARK',
'SHOW_POWERED_BY',
'SHOW_WATERMARK_FOR_GUESTS',
'SUPPORT_URL',
'TILE_VIEW_MAX_COLUMNS',
'TOOLBAR_ALWAYS_VISIBLE',
'TOOLBAR_BUTTONS',
'TOOLBAR_TIMEOUT',
'UNSUPPORTED_BROWSERS',
'VERTICAL_FILMSTRIP',
'VIDEO_LAYOUT_FIT',
'VIDEO_QUALITY_LABEL_DISABLED',
'filmStripOnly'
];

View File

@@ -2,6 +2,7 @@
import _ from 'lodash';
import Platform from '../react/Platform';
import { equals, ReducerRegistry, set } from '../redux';
import { CONFIG_WILL_LOAD, LOAD_CONFIG_ERROR, SET_CONFIG } from './actionTypes';
@@ -20,6 +21,15 @@ import { _cleanupConfig } from './functions';
const INITIAL_NON_RN_STATE = {
};
/**
* When we should enable H.264 on mobile. iOS 10 crashes so we disable it there.
* See: https://bugs.chromium.org/p/webrtc/issues/detail?id=11002
* Note that this is only used for P2P calls.
*
* @type {boolean}
*/
const RN_ENABLE_H264 = navigator.product === 'ReactNative' && !(Platform.OS === 'ios' && Platform.Version === 10);
/**
* The initial state of the feature base/config when executing in a React Native
* environment. The mandatory configuration to be passed to JitsiMeetJS#init().
@@ -41,8 +51,8 @@ const INITIAL_RN_STATE = {
disableAudioLevels: true,
p2p: {
disableH264: false,
preferH264: true
disableH264: !RN_ENABLE_H264,
preferH264: RN_ENABLE_H264
}
};

View File

@@ -9,7 +9,10 @@ import {
getCurrentConference
} from '../conference';
import JitsiMeetJS, { JitsiConnectionEvents } from '../lib-jitsi-meet';
import { parseURIString } from '../util';
import {
getBackendSafeRoomName,
parseURIString
} from '../util';
import {
CONNECTION_DISCONNECTED,
@@ -307,10 +310,7 @@ function _constructOptions(state) {
// Append room to the URL's search.
const { room } = state['features/base/conference'];
// XXX The Jitsi Meet deployments require the room argument to be in
// lower case at the time of this writing but, unfortunately, they do
// not ignore case themselves.
room && (bosh += `?room=${room.toLowerCase()}`);
room && (bosh += `?room=${getBackendSafeRoomName(room)}`);
options.bosh = bosh;
}

View File

@@ -6,6 +6,7 @@ declare var APP: Object;
declare var config: Object;
import { configureInitialDevices } from '../devices';
import { getBackendSafeRoomName } from '../util';
export {
connectionEstablished,
@@ -21,8 +22,7 @@ import logger from './logger';
*/
export function connect() {
return (dispatch: Dispatch<any>, getState: Function) => {
// XXX Lib-jitsi-meet does not accept uppercase letters.
const room = getState()['features/base/conference'].room.toLowerCase();
const room = getBackendSafeRoomName(getState()['features/base/conference'].room);
// XXX For web based version we use conference initialization logic
// from the old app (at the moment of writing).

View File

@@ -61,11 +61,7 @@ class BottomSheet extends PureComponent<Props> {
styles.sheetItemContainer,
_styles.sheet
] }>
<ScrollView
bounces = { false }
showsVerticalScrollIndicator = { false }>
{ this._getWrappedContent() }
</ScrollView>
{ this._getWrappedContent() }
</View>
</View>
</SlidingView>
@@ -73,24 +69,32 @@ class BottomSheet extends PureComponent<Props> {
}
/**
* Wraps the content when needed (iOS 11 and above), or just returns the original children.
* Wraps the content when needed (iOS 11 and above), or just returns the original content.
*
* @returns {React$Element}
*/
_getWrappedContent() {
const content = (
<ScrollView
bounces = { false }
showsVerticalScrollIndicator = { false } >
{ this.props.children }
</ScrollView>
);
if (Platform.OS === 'ios') {
const majorVersionIOS = parseInt(Platform.Version, 10);
if (majorVersionIOS > 10) {
return (
<SafeAreaView>
{ this.props.children }
{ content }
</SafeAreaView>
);
}
}
return this.props.children;
return content;
}
}

View File

@@ -147,7 +147,7 @@ ColorSchemeRegistry.register('BottomSheet', {
* Style for the label in a generic item rendered in the menu.
*/
labelStyle: {
color: schemeColor('label'),
color: schemeColor('text'),
flexShrink: 1,
fontSize: MD_FONT_SIZE,
marginLeft: 32,

View File

@@ -73,6 +73,12 @@ const _LANGUAGES = {
main: require('../../../../lang/main-hr')
},
// Hungarian
'hu': {
languages: require('../../../../lang/languages-hu'),
main: require('../../../../lang/main-hu')
},
// Italian
'it': {
languages: require('../../../../lang/languages-it'),

View File

@@ -11,7 +11,7 @@ type Props = {
/**
* Class name for the web platform, if any.
*/
className?: string,
className: string,
/**
* Color of the icon (if not provided by the style object).
@@ -23,6 +23,11 @@ type Props = {
*/
id?: string,
/**
* Function to invoke on click.
*/
onClick?: Function,
/**
* The size of the icon (if not provided by the style object).
*/
@@ -53,6 +58,7 @@ export default function Icon(props: Props) {
className,
color,
id,
onClick,
size,
src: IconComponent,
style
@@ -68,7 +74,8 @@ export default function Icon(props: Props) {
return (
<Container
className = { className }
className = { `jitsi-icon ${className}` }
onClick = { onClick }
style = { restStyle }>
<IconComponent
fill = { calculatedColor }
@@ -79,3 +86,6 @@ export default function Icon(props: Props) {
);
}
Icon.defaultProps = {
className: ''
};

View File

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4 4C4 2.89543 4.89543 2 6 2H14C15.1046 2 16 2.89543 16 4H6V18C4.89543 18 4 17.1046 4 16V4ZM10 8V20H18V8H10ZM10 6H18C19.1046 6 20 6.89543 20 8V20C20 21.1046 19.1046 22 18 22H10C8.89543 22 8 21.1046 8 20V8C8 6.89543 8.89543 6 10 6Z" fill="#5E6D7A"/>
</svg>

After

Width:  |  Height:  |  Size: 401 B

View File

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11 13.3705V5C11 4.44772 11.4477 4 12 4C12.5523 4 13 4.44772 13 5V13.4667L15.631 10.5433C16.0005 10.1328 16.6328 10.0995 17.0433 10.469C17.4538 10.8384 17.4871 11.4707 17.1176 11.8812L12.1064 17.4492C12.0727 17.4867 12.0139 17.4867 11.9802 17.4492L6.96897 11.8812C6.59951 11.4707 6.63278 10.8384 7.04329 10.469C7.4538 10.0995 8.08609 10.1328 8.45555 10.5433L11 13.3705ZM20 15C20 14.4477 20.4477 14 21 14C21.5523 14 22 14.4477 22 15V21C22 21.5523 21.5523 22 21 22H3C2.96548 22 2.93137 21.9983 2.89776 21.9948C2.3935 21.9436 2 21.5178 2 21V15C2 14.4477 2.44772 14 3 14C3.55228 14 4 14.4477 4 15V20H20V15Z" fill="#A4B8D1"/>
</svg>

After

Width:  |  Height:  |  Size: 773 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11 18h2v-2h-2v2zm1-16C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm0-14c-2.21 0-4 1.79-4 4h2c0-1.1.9-2 2-2s2 .9 2 2c0 2-3 1.75-3 5h2c0-2.25 3-2.5 3-5 0-2.21-1.79-4-4-4z"/></svg>

After

Width:  |  Height:  |  Size: 381 B

View File

@@ -18,16 +18,19 @@ export { default as IconClose } from './close.svg';
export { default as IconClosedCaption } from './closed_caption.svg';
export { default as IconConnectionActive } from './gsm-bars.svg';
export { default as IconConnectionInactive } from './ninja.svg';
export { default as IconCopy } from './copy.svg';
export { default as IconDeviceBluetooth } from './bluetooth.svg';
export { default as IconDeviceEarpiece } from './phone-talk.svg';
export { default as IconDeviceHeadphone } from './headset.svg';
export { default as IconDeviceSpeaker } from './volume.svg';
export { default as IconDominantSpeaker } from './dominant-speaker.svg';
export { default as IconDownload } from './download.svg';
export { default as IconEventNote } from './event_note.svg';
export { default as IconExitFullScreen } from './exit-full-screen.svg';
export { default as IconFeedback } from './feedback.svg';
export { default as IconFullScreen } from './full-screen.svg';
export { default as IconHangup } from './hangup.svg';
export { default as IconHelp } from './help.svg';
export { default as IconInfo } from './info.svg';
export { default as IconInvite } from './invite.svg';
export { default as IconKick } from './kick.svg';
@@ -36,6 +39,7 @@ export { default as IconMenu } from './menu.svg';
export { default as IconMenuDown } from './menu-down.svg';
export { default as IconMenuThumb } from './thumb-menu.svg';
export { default as IconMenuUp } from './menu-up.svg';
export { default as IconMessage } from './message.svg';
export { default as IconMicDisabled } from './mic-disabled.svg';
export { default as IconMicrophone } from './microphone.svg';
export { default as IconModerator } from './star.svg';
@@ -48,6 +52,7 @@ export { default as IconRaisedHand } from './raised-hand.svg';
export { default as IconRec } from './rec.svg';
export { default as IconRemoteControlStart } from './play.svg';
export { default as IconRemoteControlStop } from './stop.svg';
export { default as IconReply } from './reply.svg';
export { default as IconRestore } from './restore.svg';
export { default as IconRoomLock } from './security.svg';
export { default as IconRoomUnlock } from './security-locked.svg';

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"/><path d="M0 0h24v24H0z" fill="none"/></svg>

After

Width:  |  Height:  |  Size: 256 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 9V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z"/><path d="M0 0h24v24H0z" fill="none"/></svg>

After

Width:  |  Height:  |  Size: 194 B

View File

@@ -1,12 +1,7 @@
// @flow
import { toState } from '../redux';
import { loadScript } from '../util';
import JitsiMeetJS from './_';
import logger from './logger';
declare var APP: Object;
const JitsiConferenceErrors = JitsiMeetJS.errors.conference;
const JitsiConnectionErrors = JitsiMeetJS.errors.connection;
@@ -97,42 +92,3 @@ export function isFatalJitsiConnectionError(error: Object | string) {
|| error === JitsiConnectionErrors.OTHER_ERROR
|| error === JitsiConnectionErrors.SERVER_ERROR);
}
/**
* Loads config.js from a specific remote server.
*
* @param {string} url - The URL to load.
* @returns {Promise<Object>}
*/
export function loadConfig(url: string): Promise<Object> {
let promise;
if (typeof APP === 'undefined') {
promise
= loadScript(url, 2.5 * 1000 /* Timeout in ms */)
.then(() => {
const { config } = window;
// We don't want to pollute the global scope.
window.config = undefined;
if (typeof config !== 'object') {
throw new Error('window.config is not an object');
}
return config;
})
.catch(err => {
logger.error(`Failed to load config from ${url}`, err);
throw err;
});
} else {
// Return "the config.js file" from the global scope - that is how the
// Web app on both the client and the server was implemented before the
// React Native app was even conceived.
promise = Promise.resolve(window.config);
}
return promise;
}

View File

@@ -0,0 +1,36 @@
// @flow
import { NativeModules } from 'react-native';
import { loadScript } from '../util';
import logger from './logger';
export * from './functions.any';
const { JavaScriptSandbox } = NativeModules;
/**
* Loads config.js from a specific remote server.
*
* @param {string} url - The URL to load.
* @returns {Promise<Object>}
*/
export async function loadConfig(url: string): Promise<Object> {
try {
const configTxt = await loadScript(url, 2.5 * 1000 /* Timeout in ms */, true /* skipeval */);
const configJson = await JavaScriptSandbox.evaluate(`${configTxt}\nJSON.stringify(config);`);
const config = JSON.parse(configJson);
if (typeof config !== 'object') {
throw new Error('config is not an object');
}
logger.info(`Config loaded from ${url}`);
return config;
} catch (err) {
logger.error(`Failed to load config from ${url}`, err);
throw err;
}
}

View File

@@ -0,0 +1,16 @@
// @flow
export * from './functions.any';
/**
* Loads config.js from a specific remote server.
*
* @param {string} url - The URL to load.
* @returns {Promise<Object>}
*/
export async function loadConfig(url: string): Promise<Object> { // eslint-disable-line no-unused-vars
// Return "the config.js file" from the global scope - that is how the
// Web app on both the client and the server was implemented before the
// React Native app was even conceived.
return window.config;
}

View File

@@ -63,13 +63,13 @@ export default class JitsiMeetLogStorage {
for (let i = 0, len = logEntries.length; i < len; i++) {
const logEntry = logEntries[i];
if (typeof logEntry === 'object') {
// Aggregated message
logMessage += `(${logEntry.count}) ${logEntry.text}\n`;
} else {
// Regular message
logMessage += `${logEntry}\n`;
if (logEntry.timestamp) {
logMessage += `${logEntry.timestamp} `;
}
if (logEntry.count > 1) {
logMessage += `(${logEntry.count}) `;
}
logMessage += `${logEntry.text}\n`;
}
logMessage += '"}';

View File

@@ -39,7 +39,8 @@ function buildTransport() {
'warn',
'error'
].reduce((logger, logName) => {
logger[logName] = (...args: Array<string>) => {
logger[logName] = (timestamp: string, ...args: Array<string>) => {
// It ignores the timestamp argument, because LogBridge will add it on the native side anyway
const nargs = args.map(arg => {
if (arg instanceof Error) {
const errorBody = {

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