Compare commits

...

385 Commits

Author SHA1 Message Date
damencho
029ca1753f Fixes renewing let's encrypt certificates when using jetty.
Uses webroot for obtaining certificate, avoids stopping jitsi-videobridge before obtaining certificate.
Adds a renew hook, where we reload apache or nginx and try to graceful shutdown jvb and restart it.
Before merging this we need to make sure graceful shutdown is enabled by default and also pubsub is enabled by default so after restarting jvb, jicofo will discover it.
2017-03-30 13:57:47 -05:00
virtuacoplenny
2301732e2d style: catalog all z-indexes and move toolbar down
All z-indexes found in css files have been moved into css
variables. If the z-index is used only once, the variable
name will be the same as the selector it is used in. If
the z-index is used multiple times, then the plain name
of $zindex# was used. This allowed a more confident
moving down of the toolbar so that the new modal dialog,
with z-index 500, could display on top of it.

#1436
2017-03-30 18:13:00 +01:00
virtuacoplenny
24ee8eb16a electron: add desktop picker
#1411
2017-03-30 17:58:31 +01:00
Lyubo Marinov
57065bb274 Update NPM dependencies/packages 2017-03-30 09:11:02 -05:00
Saúl Ibarra Corretgé
08531ee675 Merge pull request #1443 from ibc/master
edge: Add userMedia.edgeGrantPermissions in lang/main.json
2017-03-29 13:35:51 +02:00
Iñaki Baz Castillo
e7140ffec7 edge: Add userMedia.edgeGrantPermissions in lang/main.json 2017-03-29 13:03:57 +02:00
damencho
c58c4b7938 Commit from translate.jitsi.org by user damencho.: 306 of 318 strings translated (0 fuzzy). 2017-03-28 21:29:17 +00:00
Lyubo Marinov
4e276471e5 Comply w/ coding style: consistency 2017-03-28 11:43:33 -05:00
Saúl Ibarra Corretgé
c5eac63da1 [RN] Move all mobile only features to a subdirectory 2017-03-28 09:36:00 -05:00
Saúl Ibarra Corretgé
866c6d0cf9 Merge pull request #1378 from saghul/doc-api-params
doc: improve docs on external API constructor parameters
2017-03-28 11:26:14 +02:00
Lyubo Marinov
165294bfb1 Comply w/ coding style 2017-03-27 22:50:47 -05:00
Saúl Ibarra Corretgé
2d5f0479bd [RN] Disable remote video while in the background
Set the video channel "last N" property to 0, thus making the client not receive
any remote video.
2017-03-27 22:11:13 -05:00
yanas
e8068cf5ac Merge pull request #1393 from jitsi/filmstrip_overlays
Filmstrip overlays
2017-03-27 14:54:45 -05:00
yanas
d0171cf386 Merge pull request #1435 from jitsi/fix-settings-translation
Fixes settings panel translation.
2017-03-27 14:52:01 -05:00
hristoterezov
3ae99ea0b9 feat(overlays): for filmstrip only mode 2017-03-27 14:20:25 -05:00
damencho
4e9450f200 Fixes settings panel translation.
Strings are not translated when opening the settings side panel. It was that we were creating settings panel html after i18n library had loaded and had translated the rest of the html.
The element selecting the current language was also not translated, which end up with no selection in the UI for the current language.
2017-03-27 13:54:14 -05:00
Saúl Ibarra Corretgé
dc2c49f4a9 doc: improve docs on external API constructor parameters 2017-03-27 12:17:32 +02:00
hristoterezov
c461e8b63c ref(overlays): Replace the abstract class for overlays with overlay frame component
In this case makes more sense to have overlay frame included in every overlay instead
of abstract class that implements the overlay frame and have to be extended by every
overlay. In addition, mapStateToProps isn't working well with inheritance.
2017-03-24 13:16:14 -05:00
Saúl Ibarra Corretgé
f47bc1163b Merge pull request #1432 from jitsi/speaker-stats-analytics-event
Sends analytics event every time speaker stats is open.
2017-03-24 16:35:59 +01:00
Дамян Минков
851be2d76e Merge pull request #1385 from saghul/make-update-deps
build: remove no longer needed Makefile rule
2017-03-24 10:13:47 -05:00
damencho
63034e6cba Sends analytics event everytime speaker stats is open. 2017-03-24 10:07:46 -05:00
Lyubo Marinov
84b9c5f5fd Coding style 2017-03-24 09:06:54 -05:00
Saúl Ibarra Corretgé
43c8fc6847 [RN] Fix mirroring video views on platforms with native support 2017-03-24 09:02:32 -05:00
Saúl Ibarra Corretgé
bc60bd23b2 build: remove no longer needed Makefile rule
- we now use pinned dependencies, so there is no need to run npm update
- AFAICT the node-sass workaround is no longer needed
2017-03-24 11:02:09 +01:00
damencho
e29120a9c1 Changes lastN event params to leaving and entering endpoint IDs.
Uses leavingIDs to more efficiently iterate over remote videos.
2017-03-23 09:32:27 -05:00
damencho
d383230532 Removes unused code. 2017-03-23 09:32:27 -05:00
bbaldino
9a46896600 Merge pull request #1402 from jitsi/p2p_ver2
P2P ver2
2017-03-22 16:10:13 -07:00
paweldomas
fba086134d add default STUN servers to config.js 2017-03-22 11:23:30 -05:00
paweldomas
2973364c02 feat(stats - show more): local p2p transport indication
Will show (direct) next to the UPD or TCP transport type if we're
running on P2P connection.
2017-03-22 11:23:30 -05:00
paweldomas
542bb7caed doc: add FIXME 2017-03-22 11:23:29 -05:00
paweldomas
fb47b6ae21 feat: add test P2P methods 2017-03-22 11:23:29 -05:00
hristoterezov
aeb301c8d5 feat(iframe_api): Add jwt token parameter 2017-03-21 22:34:44 +01:00
yanas
704e14f008 Handle last n in the client (#1389)
* Handle last n in the client

* fix(LargeVideoManager.js): Fixes check for low bandwidth. Needs more work

* fix(LargeVideoManager.js): Fixes the Shared Video test.

* fix(LargeVideoManager): Fix shared video view and remove last n checks.

* fix(LargeVideoManager): Fixes jsdoc comment

* fix(RemoteVideo): Fix connection status check

* fix(LargeVideoManager,RemoteVideo): Syntax errors
2017-03-21 12:14:13 -05:00
Lyubo Marinov
d1050d6b02 Update NPM dependencies/packages 2017-03-21 09:22:53 -05:00
Aaron van Meerten
afc96808e8 added support of static directory in debian install and Makefile for source package 2017-03-20 19:22:06 -05:00
Aaron van Meerten
dc2bae4ae1 Merge pull request #1420 from jitsi/static-content-folder
Moves all static content/files in a new folder.
2017-03-20 17:13:10 -05:00
damencho
1d7da21e48 Moves all static content/files in a new folder.
Also clears debian package from including *.js files from source roote folder, files which were not used.
2017-03-20 16:05:11 -05:00
Ilya Daynatovich
affd965d5d Remove an unnecessary file 2017-03-20 14:42:54 -05:00
Leonard Kim
989161159d Modal dialog for displaying dominant speaker times 2017-03-20 12:47:20 -05:00
Ilya Daynatovich
59a74153dc Toolbar notice as React Component 2017-03-20 11:27:08 -05:00
yanas
6690c269ef Merge pull request #1413 from jitsi/fix-missing-translation
Fixes wrong i18n key for somebody.
2017-03-20 11:03:45 -05:00
George Politis
b7fd10b905 Merge pull request #1412 from jitsi/framerate-update
Updates framerate using local statistics.
2017-03-17 17:17:24 -05:00
damencho
08e1cf1b7e Fixes wrong i18n key for somebody. 2017-03-17 16:43:43 -05:00
damencho
54d891afa7 Updates framerate using local statistics. 2017-03-17 16:10:45 -05:00
Aaron van Meerten
ae41782cd4 Merge pull request #1410 from jitsi/letsencrypt-script
Adds a script which install certificates from let's encrypt.
2017-03-17 15:53:52 -05:00
damencho
8591fe00b6 Adds a script which install certificates from let's encrypt.
The script looks for nginx, apache2 or jetty configuration and edits the first one found. Nginx and apache2 will be reloaded, while jvb will be stopped, configured and started again.
2017-03-17 14:49:10 -05:00
Saúl Ibarra Corretgé
92f58cb3c1 doc: add information about how to contribute
Inspired by the document at jitsi/jitsi.
2017-03-17 08:35:56 -05:00
Saúl Ibarra Corretgé
4ad98ca505 doc: fix typo 2017-03-17 10:48:38 +01:00
yanas
b9374bde6b Merge pull request #1383 from jitsi/fix-wrong-pass-on-auth
Fix incorrect password dialog message when using authentication.
2017-03-16 14:13:18 -05:00
pierreozoux
1ff29384b3 Add a network schemas
This is to help understanding how things are wired.
2017-03-16 11:30:28 -05:00
Saúl Ibarra Corretgé
4fc714ff10 lang: don't use " " for the default policy text
Firefox (at least) renders it verbatim.
2017-03-16 11:16:14 -05:00
damencho
51f0c8a388 Adds base dialog implementation. 2017-03-15 16:33:04 -05:00
damencho
d01a65f73d Fixes stats, using wrong object members in latest update. 2017-03-15 15:48:13 -05:00
damencho
65239f9ffe Adds frame rate to statistics bubble. 2017-03-15 13:31:42 -05:00
damencho
e5cefcce70 Updates transport type.
Updates transport type to show multiple values as we do for addresses and ports.
2017-03-14 15:51:11 -05:00
Ingo Bauersachs
8002b5ec6a Add Esperanto 2017-03-14 20:36:09 +01:00
jitsi-pootle
a575f5cc77 New files added from translate.jitsi.org based on templates 2017-03-14 19:44:37 +00:00
ibauersachs
ab3a80e076 Commit from translate.jitsi.org by user ibauersachs.: 317 of 317 strings translated (0 fuzzy). 2017-03-14 19:44:07 +00:00
ibauersachs
dda3798ba9 Commit from translate.jitsi.org by user ibauersachs.: 317 of 317 strings translated (0 fuzzy). 2017-03-14 19:43:50 +00:00
Lyubo Marinov
e6f906b9ca [RN] Fix undefined.avatarID in ParticipantView 2017-03-08 17:05:55 -06:00
hristoterezov
d74e43ddcc [RN] fix(Avatar): Match the implementation for web 2017-03-08 13:21:34 -06:00
Lyubo Marinov
23ddce122b Comply w/ coding style 2017-03-07 21:54:37 -06:00
hristoterezov
814bd26c07 feat(Avatar): Implement Avatar for web 2017-03-07 21:54:37 -06:00
damencho
2e4b39c19c Fixes loading jquery-i18next. 2017-03-07 17:30:20 -06:00
Дамян Минков
3ee65748bb Merge pull request #1382 from jitsi/load_error_handler_placeholder
Post load error handler
2017-03-07 17:29:30 -06:00
damencho
5f387737a1 Fix incorrect password dialog message when using authentication. 2017-03-07 16:42:36 -06:00
paweldomas
4fa800b87a feat(index.html): post load error handler
Adds a placeholder which allows to write a plugin for executing some
code after the "load error handler" is triggered. A function named
"postLoadErrorHandler" should be defined in one of
the "#include virtual" files.
2017-03-07 16:29:50 -06:00
Emil Ivov
9338b3cf94 Adds links to mobile builds 2017-03-07 15:44:10 -06:00
Lyubo Marinov
45e09af692 react-native 0.42.0 2017-03-07 15:09:39 -06:00
yanas
9d32f48ab8 [IOS Assets] Fixes launch screen 480x3 image 2017-03-07 13:12:26 -06:00
Lyubo Marinov
290e7baead Stick to the exact package versions for the direct dependencies 2017-03-02 21:46:43 -06:00
Любомир Маринов
e780ae00d0 Merge pull request #1360 from jitsi/move_avatar
ref(avatar): Move Avatar and ParticipantView to base/participants
2017-03-02 21:17:41 -06:00
hristoterezov
9ea224412d ref(avatar): Move Avatar and Participant view to base/participants 2017-03-02 16:57:43 -06:00
ibauersachs
cd8ae07698 Commit from translate.jitsi.org by user ibauersachs.: 317 of 317 strings translated (0 fuzzy). 2017-03-02 21:36:45 +00:00
Ingo Bauersachs
433a73e13d Add Norwegian Bokmal 2017-03-02 22:14:06 +01:00
jitsi-pootle
1e558f4da6 New files added from translate.jitsi.org based on templates 2017-03-02 21:21:41 +00:00
Lyubo Marinov
aef6e33c91 [RN] Fix remote JS debugging 2017-03-01 21:33:49 -06:00
Lyubo Marinov
acd83ede2f [RN] Third-party ES6 Symbol ponyfill 2017-03-01 21:31:43 -06:00
Lyubo Marinov
bd51613e62 [RN] Support the for...of statement in lib-jitsi-meet 2017-03-01 21:30:21 -06:00
ibauersachs
246cb39003 Commit from translate.jitsi.org by user ibauersachs.: 306 of 306 strings translated (0 fuzzy). 2017-03-01 21:07:11 +00:00
Lyubo Marinov
3b54c527b6 Remove obsolete source code 2017-02-28 23:22:03 -06:00
Lyubo Marinov
18368fefaa Comply w/ coding style 2017-02-28 23:22:02 -06:00
damencho
c361e1e31a Translate react strings.
Split language detectors to be web/native dependent. Take care of strings that contain html.
2017-02-28 13:16:42 -06:00
damencho
e3d4152e32 Adds react-i18next and its provider to react.
Adds translate function with default namespaces and options.
2017-02-28 13:13:47 -06:00
damencho
d861ba1876 Moves translation to react and use i18next language detectors. 2017-02-28 13:13:47 -06:00
George Politis
c942017b73 Merge pull request #1341 from saghul/doc-disableRtx
config: switch default disableRtx to false
2017-02-28 08:52:33 -06:00
Lyubo Marinov
743d12e326 Default to mobile app promotion 2017-02-28 00:18:52 -06:00
Lyubo Marinov
d371a3d5fd Fix TypeError: undefined is not an object 2017-02-28 00:18:52 -06:00
Lyubo Marinov
e1056126e6 Fix TypeError: undefined is not an object 2017-02-28 00:18:51 -06:00
Lyubo Marinov
72c267fbf3 Fix the human-readable text 2017-02-28 00:18:51 -06:00
Lyubo Marinov
0ed85b9d25 Replace features/unsupported-browser SET_UNSUPPORTED_BROWSER with features/base/lib-jitsi-meet SET_WEBRTC_READY
The error raised by JitsiMeetJS.init() is already in the state of
features/base/lib-jitsi-meet so it's not a good design to store the same
error in the state of features/unsupported-browser.
2017-02-28 00:18:51 -06:00
Ilya Daynatovich
a8877d82b6 Rename style component; Use of status codes instead of flags in conference init 2017-02-28 00:18:51 -06:00
Ilya Daynatovich
8896b0adf3 Fix problem with dialogs 2017-02-28 00:18:50 -06:00
Ilya Daynatovich
60b14e9b45 Some fixes mentioned in the PR 2017-02-28 00:18:50 -06:00
Ilya Daynatovich
631e853b40 Update register/unregister listeners logic of some components in the old app 2017-02-28 00:18:50 -06:00
Ilya Daynatovich
b409c8cc2f Fix reload regression 2017-02-27 21:50:21 -06:00
Ilya Daynatovich
905212b109 Enable flow for written code 2017-02-27 21:50:20 -06:00
Ilya Daynatovich
05b7df26e6 Add no mobile app component 2017-02-27 21:50:20 -06:00
Ilya Daynatovich
1268afd3f8 Added unsuported browser and plugin required pages 2017-02-27 21:50:20 -06:00
Lyubo Marinov
c1b9b7a623 Prevent undefined JitsiMeetJS 2017-02-27 21:35:34 -06:00
Lyubo Marinov
0b9160fb75 LIB_DID_DISPOSE, LIB_DID_INIT, LIB_WILL_DISPOSE, LIB_WILL_INIT 2017-02-27 16:45:53 -06:00
George Politis
93c9419392 Merge pull request #1362 from bgrozev/no-extension-on-ff-52
config: Don't require an extension for firefox >=52.
2017-02-27 16:36:31 -06:00
Boris Grozev
6121bcf171 config: Don't require an extension for firefox >=52.
Starting with firefox 52, no extension is required for screensharing.
See https://wiki.mozilla.org/Screensharing
2017-02-27 16:08:13 -06:00
Lyubo Marinov
702144180c Be consistent, simplify the source code 2017-02-25 19:00:35 -06:00
Lyubo Marinov
d2b2f98941 Fix typo 2017-02-25 18:58:23 -06:00
Lyubo Marinov
ec95956e25 [RN] Prepare for modifications to unsupported-browser 2017-02-24 13:08:49 -06:00
Lyubo Marinov
d6d7ce1b67 [RN] Move preferH264 where it will be in effect (in the future) 2017-02-24 12:59:30 -06:00
bgrozev
4cb36b0a5d Merge pull request #1337 from saghul/cleanup-adaptive-simulcast
cleanup: remove old adaptive simulcast config option
2017-02-24 11:43:22 -06:00
George Politis
2b3aea76a9 doc: Nukes influxdb.md because influx support has been nuked. 2017-02-23 17:22:06 -06:00
Lyubo Marinov
f50a31b4e8 [RN] Simplify the source code 2017-02-23 17:14:04 -06:00
Saúl Ibarra Corretgé
b226c3aca3 [RN] Fix loading config.js from URLs with a non-standard port
`host` contains the hostname:port portion, whereas `hostname` is just the
hostname, not including the port.
2017-02-23 17:14:04 -06:00
yanas
4979666a89 Merge pull request #1342 from jitsi/filmstriponly_transparent
fix(filmstriponly): Set the background to transparent
2017-02-23 16:11:35 -06:00
yanas
c9636f85b9 Merge pull request #1314 from virtuacoplenny/lenny/audio-slider
Volume slider for remote participant audio elements
2017-02-23 15:48:52 -06:00
hristoterezov
436bc87a86 fix(overlay): comments after review 2017-02-23 13:50:09 -06:00
Lyubo Marinov
e89c2b242d Android plugin for Gradle 2.2.3
Recent versions of the Android plugin for Gradle started to automatically
download the SDK build tools dependency if it is not installed already.
So it is no longer necessary to have the developer of the Android app
install the SDK build tools dependency in advance.
2017-02-23 13:14:19 -06:00
Leonard Kim
02b26a65bb Volume slider for remote participant audio elements 2017-02-23 09:01:40 -08:00
Дамян Минков
6a3e4bb59f Merge pull request #1311 from saghul/resources
Move miscellaneous files to resources
2017-02-23 06:42:15 -08:00
Saúl Ibarra Corretgé
b01ad360da Move miscellaneous files to resources 2017-02-23 10:01:19 +01:00
Ilya Daynatovich
c7f3740099 Fix IE redirect problem 2017-02-22 23:36:06 -06:00
Дамян Минков
554595acd7 Merge pull request #1348 from jitsi/restyle-range-inputs
Re-styles range inputs for Chrome and FF.
2017-02-22 21:44:46 -06:00
yanas
ee4ddd5446 Fixes indentation 2017-02-22 17:14:09 -06:00
yanas
ebab617a12 Re-styles range inputs for Chrome and FF. 2017-02-22 16:49:56 -06:00
Lyubo Marinov
bc5d92a452 [RN] Prefer H.264 2017-02-22 08:28:19 -06:00
Saúl Ibarra Corretgé
2f388dfb6a Fix warning about missing key prop
When rendering using a for loop each child whould have a key prop.
2017-02-22 12:08:12 +01:00
Boris Grozev
73a0197eb2 doc: Adds a note on installing ios-deploy on MacOS 10.11. 2017-02-21 14:43:59 -06:00
hristoterezov
b6990e9e5d fix(filmstriponly): Set the background to transparent 2017-02-21 13:45:46 -06:00
Lyubo Marinov
26e119bfc2 Comply w/ coding style 2017-02-21 13:33:25 -06:00
Saúl Ibarra Corretgé
9f866ae608 config: switch default disableRtx to false 2017-02-21 20:02:55 +01:00
Saúl Ibarra Corretgé
023359b9d2 [RN] Avoid rendering Container if not visible
This solves the issue of view clipping on Android, plus it seems to be the RN
convention unless the views are very large and memory hungry.
2017-02-21 11:13:36 -06:00
bgrozev
2128d047e1 Merge pull request #1339 from saghul/fix-doc-links
doc: fix markdown link syntax in mobile docs
2017-02-21 10:49:27 -06:00
Saúl Ibarra Corretgé
a89349c5b9 doc: fix markdown link syntax in mobile docs 2017-02-21 17:37:56 +01:00
Lyubo Marinov
d109b8beb6 Comply w/ coding style 2017-02-21 09:39:59 -06:00
Saúl Ibarra Corretgé
9b40572921 [RN] Fix Android immersive mode when coming from the background
Fixes an issue where immersive mode would be enabled when coming back from the
background on the welcome screen.

Re-fixes c57e713, which was not correct.
2017-02-21 09:13:30 -06:00
Lyubo Marinov
aaf7a38cce Detail comment 2017-02-21 09:09:07 -06:00
Saúl Ibarra Corretgé
1ed0759a50 [RN] Temporarily disable camera toggling button
It doesn't work properly and gives a very bad user experience. Disble it until
all underlying issues in react-native-webrtc are ironed out.
2017-02-21 08:33:31 -06:00
Saúl Ibarra Corretgé
213b73da6e cleanup: remove old adaptive simulcast config option 2017-02-20 15:46:41 +01:00
Saúl Ibarra Corretgé
5b6985fc5c [RN] Fix use of undefined APP
On RN we don't use the global APP object, so don't save the store there unless
it's defined, which is the case in the current web version. Also, check for
undefined explicitly, since a "if (!APP)" check will throw a ReferenceError.
2017-02-20 11:16:01 +01:00
Lyubomir Marinov
538af01bf5 Comply w/ coding style 2017-02-18 21:57:38 -06:00
hristoterezov
92d0589a37 ref(overlay): The overlays to use React 2017-02-18 17:03:50 -06:00
Lyubomir Marinov
f3269070b2 [iOS] iPad support 2017-02-18 11:36:14 -06:00
Lyubomir Marinov
d93bd3eda7 [RN] Use a default host when only a room name is specified
The mobile app remembers the domain which hosted the last conference. If
the user specified a full URL first and specified a room name only the
second time, it was not obvious that the second conference would be
hosted on the domain of the first conference.
2017-02-18 10:04:08 -06:00
Yana Stamcheva
0dbbc5d8b6 [Android] Circular app/launcher icon(s) 2017-02-17 13:54:01 -06:00
George Politis
08efd5ecab Merge pull request #1327 from saghul/doc-resolution
doc: document resolution config option and set it to 720 by default
2017-02-17 11:33:04 -06:00
Lyubomir Marinov
dba1bcb0e3 [RN] Increment short app version from 1.2 to 1.3
Now that Apple have approved build 1.2.199 for release in the App Store,
the short app version needs to be incremented; otherwise, no new builds
can be uploaded to TestFlight and, respectively, for release in the App
Store.
2017-02-17 09:32:24 -06:00
yanas
348403abff Merge pull request #1326 from jitsi/fix-manual-tooltips
Fixes manual triggered tooltips text and no hover.
2017-02-17 09:26:58 -06:00
Paweł Domas
c290cf45b7 Merge pull request #1328 from saghul/cleanup-adaptive-lastn
cleanup: remove adaptive las N config option
2017-02-17 09:14:47 -06:00
Saúl Ibarra Corretgé
175c8e6e50 cleanup: remove adaptive las N config option
The feature has been replaced so the option no longer applies.
2017-02-17 15:33:20 +01:00
Saúl Ibarra Corretgé
f90667b23c doc: document resolution config option and set it to 720 by default 2017-02-17 13:53:41 +01:00
damencho
cf69d591e4 Fixes manual triggered tooltips text and no hover. 2017-02-17 00:14:58 +02:00
Lyubomir Marinov
e599491583 Remove duplication 2017-02-16 15:17:05 -06:00
Lyubomir Marinov
d1520773cf Improve consistency 2017-02-16 15:16:17 -06:00
Saúl Ibarra Corretgé
573ca97b6c [RN] Add workaround for Android view clipping
Looks like Android gets confused as to what surface to blit when we hide or
show toolbars. Setting a border on the container, seems to force the entire
area to blit properly.

Other attempted approaches, with no success:
- zIndex of -100
- width and height of 0
- opacity of 0 and setting 'disabled' on touch containers

This patch applies the workaround in the welcome page and conference containers.
2017-02-16 14:37:42 -06:00
Lyubomir Marinov
0d97f14a1a flow 2017-02-16 13:59:28 -06:00
Lyubomir Marinov
b8f28abfdf [RN] Fix incorrect JitsiMeetJS.init error handling 2017-02-16 13:59:12 -06:00
Lyubomir Marinov
9ac7c97e67 [RN] Enforce mandatory mobile app-specific config 2017-02-16 13:58:39 -06:00
Lyubomir Marinov
52b3eaacb5 [RN] Fix passing config.js to JitsiMeetJS.init 2017-02-16 13:51:01 -06:00
ibauersachs
9b01ae6db9 Commit from translate.jitsi.org by user ibauersachs.: 306 of 306 strings translated (0 fuzzy). 2017-02-16 06:55:14 +00:00
Ingo Bauersachs
469487ad36 Add Chinese (China) 2017-02-16 07:39:57 +01:00
jitsi-pootle
176c3c1601 New files added from translate.jitsi.org based on templates 2017-02-16 06:46:38 +00:00
yanas
94391234cc Merge pull request #1322 from jitsi/livestream_help_link
livestream link help link
2017-02-15 22:35:57 -06:00
yanas
d84901f196 Font size adjustment and moving link to config param 2017-02-15 17:57:57 -06:00
yanas
c6b117565d Merge branch 'livestream_help_link' of https://github.com/jitsi/jitsi-meet into livestream_help_link 2017-02-15 16:41:49 -06:00
yanas
2a9124acb5 Merge pull request #1316 from jitsi/custom-button-tooltips
Uses tooltip to show custom popups for mute mic button.
2017-02-15 16:20:36 -06:00
Lyubomir Marinov
401a783d6a Coding style consistency
Includes automatic recommended Xcode project file fixes.
2017-02-15 13:48:56 -06:00
Lyubomir Marinov
39483a30b6 Polyfill Element.innerHTML
Lib-jitsi-meet uses jQuery's .append method to manipulate Jingle. The
method in question invokes the getter and setter of Element.innerHTML.
Unfortunately, xmldom which we use in React Native to polyfill DOM does
not polyfill Element.innerHTML. So polyfill it ourselves.
2017-02-15 13:18:21 -06:00
Lyubomir Marinov
0e2a07f8d7 Stick to react-native-background-timer 1.0.0
Recently expose-loader broke us when it updated from 0.7.1 to 0.7.2 and
we decided to stick to exact versions.
2017-02-15 13:18:20 -06:00
Saúl Ibarra Corretgé
36f5b0218d [RN] Fix running timers in the background
Turns out React Native's timers (setTimeout / setInterval) don't run while the
app is in the background: https://github.com/facebook/react-native/issues/167

This patch replaces the global timer functions with those from the
react-native-background-timer package, which work in the background.

These timers won't magically make an application work in the background, but
they will run if an application already happens to run in the background. That's
our case while in a conference, so these timers will run, allowing XMPP pings to
be sent and the conference to stay up as long as the user desires.
2017-02-15 11:50:54 -06:00
damencho
a1b3c56de7 Uses tooltip to show custom popups for mute mic button/shared video button. 2017-02-15 11:29:26 +02:00
Aaron van Meerten
6d664f133e Cosmetic fixes for column length lint errors 2017-02-14 17:11:31 -06:00
Aaron van Meerten
732a433ec1 livestream link to provide more context to users on where to retrieve their stream key 2017-02-14 16:07:12 -06:00
Lyubomir Marinov
f7dcd1ba2c Stick to expose-loader 0.7.1
0.7.2 causes a ReferenceError: jQuery is not defined in autosize.
2017-02-14 08:07:49 -06:00
Lyubomir Marinov
55a8b44224 Consistent middleware and reducer imports 2017-02-10 11:04:40 -06:00
Lyubomir Marinov
e29db31d91 Comply w/ coding style 2017-02-10 10:13:39 -06:00
Lyubomir Marinov
183d3c3ca4 Fix a possible undefined state usage 2017-02-10 00:47:55 -06:00
Saúl Ibarra Corretgé
c57e713696 [RN] Fix full-screen mode when coming back from the background
On Android the status and navigation bars are shown again after coming back from
the background, so enter full-screen mode again if needed.
2017-02-10 00:44:37 -06:00
Saúl Ibarra Corretgé
4519f26adf [RN] Mute local video when app is in the background 2017-02-10 00:44:37 -06:00
bgrozev
c26f9cc01f Merge pull request #1301 from jitsi/video-thumbnail-margin
Lower the margin between video thumbnails
2017-02-09 11:43:55 -06:00
yanas
53e784094a Merge pull request #1308 from jitsi/ss_resize_remote
Fix for the size of remote desktop sharing videos
2017-02-08 15:31:06 -06:00
hristoterezov
0e92e48376 fix(ss): resize for remote videos 2017-02-08 14:58:42 -06:00
Lyubomir Marinov
4c9943ac38 Fix an image path on the mobile landing page 2017-02-08 12:41:51 -06:00
Дамян Минков
4bd0fd145d Merge pull request #1293 from jitsi/prosody_plugin_muc_all_owners
prosody plugin to make all users owners/moderators
2017-02-08 13:17:42 +02:00
Lyubomir Marinov
01ae82eb28 No Temasys alert on mobile Web 2017-02-07 21:54:08 -06:00
Lyubomir Marinov
e21eae0933 Prepare for webpack 2 2017-02-07 15:44:37 -06:00
Lyubomir Marinov
2f047c50dc Revert "No Temasys alert on mobile Web"
This reverts commit b09e86352f.
2017-02-07 15:21:34 -06:00
yanas
e397e1a80c Merge pull request #1303 from jitsi/no-temasys-alert-on-mobile
No Temasys alert on mobile (Web)
2017-02-07 15:11:09 -06:00
Lyubomir Marinov
b09e86352f No Temasys alert on mobile Web 2017-02-07 15:08:38 -06:00
Lyubomir Marinov
8687b69167 Consistency
Be consistent about formatting within 1 and the same file.
2017-02-07 08:29:40 -06:00
Lyubomir Marinov
6c5468d904 Simplify the source code
If half the file is written in ES6, it is easier to read if the rest of
the file is in ES6 as well. If ES6 is used, then const is better than
let. If source code is shorter yet as readable as the long version, then
prefer the short version.
2017-02-07 08:29:40 -06:00
Lyubomir Marinov
d6b0f8d4c5 Use functions, do not re-implement them
We have the functions reload and redirect which modify window.location.
Use them and do not directly modify window.location so that we have
fewer places of direct window.location modifications and it is easier to
refactor them.
2017-02-07 08:29:40 -06:00
Lyubomir Marinov
a8cd4ff12c 1, not 2 names for 1 and the same abstraction
window.location calls it reload so util/helpers shouldn't call it
redirect because UI/util/UIUtil has it is own redirect which is the
assign of window.location.
2017-02-07 08:29:40 -06:00
Lyubomir Marinov
8509efc8af Make the Web app aware of its context root 2017-02-07 08:27:23 -06:00
Saúl Ibarra Corretgé
23a0053dad doc: add section about embedding to the README 2017-02-06 17:41:19 -06:00
Saúl Ibarra Corretgé
5849980092 external_api: fix jsdoc 2017-02-06 17:41:19 -06:00
Saúl Ibarra Corretgé
e81fc2b254 doc: fix external API documentation
- use proper punctuation
- fix markdown syntax
- always use syntax highlighting
- document missing commands
- miscellaneous grammar fixes
2017-02-06 17:41:19 -06:00
yanas
f6f730b994 Lower the margin between video thumbnails 2017-02-06 15:34:05 -06:00
Lyubomir Marinov
2ad869a036 Comply w/ coding style
- Use 1 name for 1 abstraction. Instead of useFullScreen and enabled use
  fullScreen.
- Comments are correct English sentences so no double spaces between
  senteces, no capitalization of the work On midsentence.
- Write as little source code as possible if readability is preserved.
- Utilize Facebook's Flow.
- The name of a private function must start with _ and the jsdoc should
  state that the function is private.
2017-02-06 15:32:03 -06:00
Saúl Ibarra Corretgé
7a8c84e990 [RN] Implement full screen mode while in a conference
The implementation varies across platforms, with the same goal: allow the app to
use the entire screen real state while in a conference.

On Android we use immersive mode, which  will hide the status and navigation bars.

https://developer.android.com/training/system-ui/immersive.html

On iOS the status bar is hidden, with a slide effect.
2017-02-06 13:51:17 -06:00
Lyubomir Marinov
0de01e93dd react-native 0.41.2 2017-02-06 12:24:38 -06:00
Lyubomir Marinov
6fa93e5b44 file-loader 0.10.0 2017-02-06 12:24:38 -06:00
Lyubomir Marinov
2144ec1e3f eslint 3.15.0 2017-02-06 12:24:38 -06:00
bgrozev
68d2f60ace Merge pull request #1276 from jitsi/respect-disable-rtx
fix: Respect the disableRtx config option.
2017-02-06 11:52:03 -06:00
George Politis
3d671ae71f docs: Documents the disableRtx config option. 2017-02-06 11:19:33 -06:00
Lyubomir Marinov
8ed47f9d99 [flow] Lint with Flow (in addition to JSHint and ESLint) 2017-02-03 16:36:14 -06:00
Lyubomir Marinov
b50f858556 [flow] Expand the coverage of flow-monitored files 2017-02-03 16:36:14 -06:00
Lyubomir Marinov
5de1a74429 [flow] Take advantage of flow-typed 2017-02-03 16:36:14 -06:00
Lyubomir Marinov
2063ad467d flow-typed 2017-02-03 16:36:14 -06:00
Lyubomir Marinov
679acbae16 Use babel-eslint in the whole project 2017-02-03 16:36:14 -06:00
Aaron van Meerten
a5b706a99e Added a prosody plugin for making all users into muc owners in prosody
Included a patch to prosody-trunk which allows owners to kick each other
2017-02-03 11:41:08 -06:00
yanas
542e61357e Adds new combined camera and mic icon 2017-02-02 17:10:02 -06:00
Lyubomir Marinov
3743602c67 [RN] Fix the parsing of the domain out of a URL 2017-02-02 13:40:49 -06:00
Lyubomir Marinov
ee651840bf Fixes related to coding style 2017-02-02 10:54:24 -06:00
damencho
0765c60d77 Moves feedback button as a component.
When callstats is not configured hide the button.
2017-02-02 10:06:17 -06:00
Lyubomir Marinov
7fa17322a1 Consistency in naming and jsdocs 2017-02-02 09:46:09 -06:00
Lyubomir Marinov
cfa3047330 [flow] Type annotations 2017-02-02 09:45:34 -06:00
Lyubomir Marinov
9e033deb7b Remove unnecessary source code 2017-02-02 09:42:14 -06:00
Lyubomir Marinov
f6c914f6f0 [flow] A minimal demonstration of flow in action 2017-02-01 13:38:37 -06:00
Lyubomir Marinov
06ff02c2a5 [flow] Ignore packages in node_modules that cause errors and we do not want to fix 2017-02-01 13:38:37 -06:00
Lyubomir Marinov
63fd263890 flow 0.36.0
The first step towards enabling Facbook's flow in the project. The flow
configuration is pristine as generated by react-native upgrade.
2017-02-01 13:38:37 -06:00
Lyubomir Marinov
94f3d4b279 [RN] Expand domains supported by Universal Links 2017-01-31 22:47:47 -06:00
Lyubomir Marinov
fdc96044ad [RN] App-specific URL scheme 2017-01-31 22:47:47 -06:00
Lyubomir Marinov
91487ffc94 Fix a case of endless recursion 2017-01-31 22:47:47 -06:00
Saúl Ibarra Corretgé
7a57dcc08a doc: add documentation on how to build the mobile apps 2017-01-31 22:32:15 -06:00
Дамян Минков
913a54713d Adds testing repo to readme. 2017-01-31 21:42:45 -06:00
damencho
39a8681e8e Improves safe checks for missing stats. 2017-01-30 17:01:25 -06:00
George Politis
a7015b0d1a fix: Respect the disableRtx config option. 2017-01-30 16:20:23 +00:00
Lyubomir Marinov
5305f23332 Consistent naming of functions
Until we make a decision on access modifier hints and adopt a respective
coding style, consistency is king.
2017-01-28 20:15:10 -06:00
Lyubomir Marinov
acbf3adab7 Simplify: Remove react/features/base/react-native 2017-01-28 20:13:54 -06:00
Lyubomir Marinov
366b2f1374 Simplify: Remove react/features/base/navigator 2017-01-28 19:56:35 -06:00
Lyubomir Marinov
2189ab7ee6 Consistent naming of react-redux's mapStateToProps
Until we make a decision on access modifier hints and adopt a respective
coding style, consistency is king.
2017-01-28 17:34:57 -06:00
Lyubomir Marinov
349c04d8d1 Consistent naming of functions
Until we make a decision on access modifier hints and adopt a respective
coding style, consistency is king.
2017-01-28 17:28:13 -06:00
Lyubomir Marinov
c7c6249ad7 [RN] Fix room name case sensitivity
It turns out that it is not enough to give lib-jitsi-meet the room name
in lower case. BOSH also needs the room name in lower case.
2017-01-28 17:26:09 -06:00
Lyubomir Marinov
5319227a8f Fix jsdocs 2017-01-28 12:11:24 -06:00
Lyubomir Marinov
3aff812ee2 Consistent naming of Component props mapped from the Redux state
Until we make a decision on access modifier hints and adopt a respective
coding style, consistency is king.
2017-01-27 21:36:20 -06:00
Lyubomir Marinov
88eabf23f4 Remove obsolete UnsupportedMobileBrowser functionality
The desired behavior of the button 'Start a conference' / 'Join the
conversation' is to launch the mobile app if installed; otherwise, do
nothing i.e. continue to display UnsupportedMobileBrowser.

Anyway, we may change our minds about allowing the user to continue in a
supported mobile browser so preserve the source code that enables that
but give it more appropriate naming.
2017-01-27 21:29:09 -06:00
Любомир Маринов
a70beaf7b6 Merge pull request #1265 from jitsi/api
api/api.html -> examples/api.html && rm doc/api
2017-01-27 20:11:23 -06:00
Lyubomir Marinov
c91bffa73c Merge branch 'saghul-android-audiomode' 2017-01-26 23:48:42 -06:00
Lyubomir Marinov
ea163dbbba Merge branch 'deduplicate-index-js' 2017-01-26 23:48:09 -06:00
Lyubomir Marinov
18bc99d6b5 Split long methods into multiple shorter ones 2017-01-26 23:35:56 -06:00
Lyubomir Marinov
bab94a207d Remove unnecessary source code 2017-01-26 21:08:50 -06:00
Lyubomir Marinov
ef39baab47 Comply w/ coding style
- Maximum of 80 characters per line.
- Group first and then sort in alphabetical order.
- Fields should begin with a lowercase letter.
2017-01-26 21:07:35 -06:00
Saúl Ibarra Corretgé
2edaaac7bf [RN] Implement AudioMode module on Android
This module chooses the most appropriate audio default based on the specified
mode.
2017-01-26 19:18:10 -06:00
Saúl Ibarra Corretgé
113e50c074 [RN] Bump Andoroid minimum and target SDK versions
Use a minimum SDK version of 19, that is Anroid 4.4 (KitKat) and a target SDK of
23, that is, Android 6.0 (Marshmallow).
2017-01-26 19:18:10 -06:00
Дамян Минков
900a675864 Merge pull request #1269 from jitsi/border-radius-fix
Fixes border radius.
2017-01-26 17:55:01 -06:00
Lyubomir Marinov
49b3b49f3e Remove duplication
The files react/index.native.js and react/index.web.js ended up having
very similar source code related to initializing the Redux store. Remove
the duplication.

Additionally, I always wanted the App React Component to be consumed
without the need to provide a Redux store to it.
2017-01-26 17:24:11 -06:00
yanas
23935d3d39 Fixes border radius. 2017-01-26 17:04:29 -06:00
Дамян Минков
3fd33d0f50 Merge pull request #1262 from jitsi/ui-fixes
Ui fixes
2017-01-26 10:15:39 -06:00
hristoterezov
8c3317b8e9 doc(iframe_api): api/api.html -> examples/api.html && rm doc/api 2017-01-26 10:02:34 -06:00
Lyubomir Marinov
99a9fc054f eslint 3.14.1 2017-01-26 09:39:47 -06:00
Lyubomir Marinov
967dcfc3d2 react-native-keep-awake 2.0.2 2017-01-26 09:39:20 -06:00
Lyubomir Marinov
0051b3b79c Clean up obsolete file references 2017-01-26 07:58:56 -06:00
Lyubomir Marinov
cbcee201f0 Comply w/ coding style 2017-01-26 07:58:46 -06:00
Ilya Daynatovich
1fa4a53a48 Remove rule 2017-01-26 07:27:31 -06:00
Ilya Daynatovich
6a0b92638c Introduce interceptComponent function 2017-01-26 07:27:31 -06:00
Ilya Daynatovich
2e81b8493e Introduce unsupported browser page 2017-01-26 07:27:31 -06:00
Ilya Daynatovich
57ba702dda Clean up routing logic 2017-01-26 07:27:31 -06:00
Lyubomir Marinov
62bafcaf63 Introduce Platform in React
React Native provides a Platform abstraction which React does not
provide.
2017-01-26 07:27:31 -06:00
Lyubomir Marinov
7de5c9c1d2 Comply w/ coding style 2017-01-26 07:27:31 -06:00
Ilya Daynatovich
8248b14555 Integrate Mobile landing in the Redux app 2017-01-26 07:27:31 -06:00
Ilya Daynatovich
23ef0c8d9d justify text on landing page 2017-01-26 07:27:31 -06:00
Ilya Daynatovich
58a4f59fd8 Implement Landing component 2017-01-26 07:27:31 -06:00
Ilya Daynatovich
0c851934fb layout for mobile landing 2017-01-26 07:27:31 -06:00
Emil Ivov
8d58dbee38 Restores api.md to original location 2017-01-25 19:14:30 -06:00
yanas
cd5e84e4ef Fixes network problem message position 2017-01-25 16:54:51 -06:00
yanas
09ba14eb04 Fixes video thumbnail border and large video background color 2017-01-25 16:53:58 -06:00
Boris Grozev
b22f1965aa doc: Remove obsolete reference to browserify. 2017-01-25 15:48:32 -06:00
Samuel Liard
df6f920b44 Force jquery-ui version to fix pb with beta version we can get with npm
Use Maven in place of ant
Add --host parameter for jicofo
Add build for jitsi Meet

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

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

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

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

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

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

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

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

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

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

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

* move useAudioStream over to new flow

* restore useVideoStream doc

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

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

Additionally, we duplicated watermark-related source code on the Welcome
and Conference pages.
2017-01-17 16:20:13 -06:00
Lyubomir Marinov
eaed9db1e7 Name folders consistently 2017-01-17 08:53:23 -06:00
Lyubomir Marinov
4f8b7a934c Comply w/ coding style 2017-01-17 08:32:20 -06:00
Lyubomir Marinov
71c04936af Merge branch 'actions-rename' of https://github.com/saghul/jitsi-meet into saghul-actions-rename 2017-01-17 08:18:52 -06:00
Любомир Маринов
41da758946 Merge pull request #1242 from saghul/ipad
Enable universal builds
2017-01-16 19:56:29 -06:00
Saúl Ibarra Corretgé
acbfe5cb09 [RN] Keep device screen on while in a conference 2017-01-16 19:12:43 -06:00
Lyubomir Marinov
ba3d65c01f Fix d17cc9fa
A bug was discovered in d17cc9fa which would raise a failure to push
into the browser's history if a base href was defined. Fix the failure
by removing react-router. Anyway, the usage of react-router was
incorrect because the app must hit the server infrastructure when it
enters a room because the server will choose the very app version then.
2017-01-15 18:28:02 -06:00
Lyubomir Marinov
856732abab Preserve URLs 2017-01-15 17:46:34 -06:00
Lyubomir Marinov
5f21e4c5b6 Introduce Platform in React
React Native provides Platform.
2017-01-15 12:09:52 -06:00
Lyubomir Marinov
28b44cf67c Consistency 2017-01-15 12:09:02 -06:00
Дамян Минков
674b0e706c Merge pull request #1241 from jitsi/iframe_api_avatars
feat(iframeAPI): implement avatar change commands
2017-01-12 17:08:13 -06:00
Saúl Ibarra Corretgé
b96ca538e4 [RN][iOS] Make universal builds 2017-01-12 16:24:01 -06:00
Saúl Ibarra Corretgé
3266ace916 [RN][iOS] Set deployment target to 9.0
According to Apple iOS devices with versions < 9.0 are 6%.
https://developer.apple.com/support/app-store/
2017-01-12 16:20:03 -06:00
hristoterezov
f7ce8d028d feat(iframeAPI): implement avatar change commands 2017-01-12 15:53:17 -06:00
Дамян Минков
85e5b0fc31 Merge pull request #1240 from jitsi/ilmstriponly_ui
fix(filmstrip_only): Remove unrelated UI elements
2017-01-12 15:24:32 -06:00
hristoterezov
61f4b52a15 fix(filmstrip_only): Remove unrelated UI elements 2017-01-12 14:51:53 -06:00
Lyubomir Marinov
d17cc9fa86 Merge branch 'BeatC-BeatC-moving-conference-init-to-react-1' 2017-01-12 12:24:25 -06:00
Lyubomir Marinov
1f995cffe9 eslint 3.13.1, react 15.4.1, react-redux 5.0.2 2017-01-12 11:01:12 -06:00
Lyubomir Marinov
0936d54114 Merge branch 'master' into BeatC-BeatC-moving-conference-init-to-react-1 2017-01-12 10:37:36 -06:00
Lyubomir Marinov
0912dbf130 Remove duplication, simplify, comply with coding style 2017-01-12 10:37:01 -06:00
Дамян Минков
7dd566a591 Merge pull request #1238 from jitsi/filmstriponly_jserrors
fix(filmstrip_only): JS errors
2017-01-11 19:18:51 -06:00
hristoterezov
0f9bc766db fix(filmstrip_only): JS errors 2017-01-11 17:16:43 -06:00
Saúl Ibarra Corretgé
e71e6c5b79 Name Redux actions consistently
Redux actions which represent "commands" should be imperative, and those
representing events should use the past tense.
2017-01-11 13:11:11 -06:00
Lyubomir Marinov
4d5f82633b Merge branch 'master' into BeatC-BeatC-moving-conference-init-to-react-1 2017-01-10 13:07:19 -06:00
Lyubomir Marinov
2f01746c55 Remove duplication, simplify, comply with coding style 2017-01-10 13:06:18 -06:00
yanas
7ec5b34548 Merge pull request #1232 from jitsi/fix-adjust-layout
Fixes and adjustments of UI layout
2017-01-10 11:20:34 -06:00
yanas
1604fa6584 Fixes and adjustments of UI layout 2017-01-09 15:32:25 -06:00
Lyubomir Marinov
b67994235e Merge branch 'BeatC-moving-conference-init-to-react-1' of https://github.com/BeatC/jitsi-meet into BeatC-BeatC-moving-conference-init-to-react-1 2017-01-09 07:44:02 -06:00
Lyubomir Marinov
ee1358fae3 Merge branch 'saghul-no-welcome-autofocus' 2017-01-06 13:19:33 -06:00
Lyubomir Marinov
9fae5aa02f Merge branch 'no-welcome-autofocus' of https://github.com/saghul/jitsi-meet into saghul-no-welcome-autofocus 2017-01-06 13:19:12 -06:00
Lyubomir Marinov
a887beed3a [RN] Increment short app version from 1.0 to 1.1
Now that Apple have approved build 1.0.178 for release in the App Store,
the short app version needs to be incremented; otherwise, no new builds
can be uploaded to TestFlight and, respectively, for release in the App
Store.
2017-01-06 10:34:46 -06:00
Saúl Ibarra Corretgé
8a30d44042 [RN] Disable autofocus on the welcome screen
This prevents the keyboard from showing up right when the app opens.
2017-01-06 16:08:01 +01:00
Lyubomir Marinov
4fef8a3b79 [RN] Prevent unhandled JS errors from killing the process in Release 2017-01-05 15:06:41 -06:00
Ilya Daynatovich
ad9bdf4dd2 Fix url params stripping 2017-01-04 19:01:25 +02:00
hristoterezov
29001c3ab0 Merge pull request #1228 from jitsi/fix-menu-icon
Fix(RemoteVideo): Fixes remote video menu icon
2017-01-04 10:18:41 -06:00
yanas
a5387b054a Fix(RemoteVideo): Fixes remote video menu icon 2017-01-04 10:14:53 -06:00
Ilya Daynatovich
c2757469a5 Merge branch 'master' into BeatC-moving-conference-init-to-react-1 2017-01-04 17:53:13 +02:00
Ilya Daynatovich
ed1aa700d0 remove asterisk symbol from jsdoc 2017-01-04 17:47:27 +02:00
Ilya Daynatovich
58b5e1748f editions after rebase 2017-01-04 17:47:27 +02:00
Ilya Daynatovich
a99bbe67ab Clean up Conference component 2017-01-04 17:47:27 +02:00
Ilya Daynatovich
f53fb3d814 Introduced new actions and functions for app initialization 2017-01-04 17:46:47 +02:00
Ilya Daynatovich
e716c1738c Fix lint errs 2017-01-04 17:46:47 +02:00
Ilya Daynatovich
3190bfa058 Move redundant code from app.js 2017-01-04 17:45:52 +02:00
Ilya Daynatovich
c570b80d7b moved app initialization to react app 2017-01-04 17:45:52 +02:00
yanas
2f9887245a Merge pull request #1226 from jitsi/guests-watermark
Adds an option to show watermark only for guests.
2017-01-04 09:43:25 -06:00
damencho
6006333ccf Adds an option to show watermark only for guests. 2017-01-03 17:30:57 -06:00
Lyubomir Marinov
fd6c91715f Merge branch 'fix-mobile-toolbar-initial-timeout' 2017-01-03 15:27:22 -06:00
Lyubomir Marinov
a40b6a9df8 Merge branch 'master' into fix-mobile-toolbar-initial-timeout 2017-01-03 15:12:53 -06:00
yanas
d67b7c7f49 Fix(React/conference): Fix jsdocs 2017-01-03 15:09:52 -06:00
yanas
616ab0f635 Fix(mobile/conference): Move the initial call to the componentDidMount method 2017-01-03 15:06:47 -06:00
yanas
930e65da66 Fix(React/conference): Sets an initial toolbar view timeout 2017-01-03 14:53:52 -06:00
yanas
414a978b10 Merge pull request #1224 from jitsi/fix-close-page-redirect
Removes guest parameter when navigating to close page.
2017-01-03 14:37:54 -06:00
damencho
4ebefb17e9 Removes guest parameter when navigating to close page.
Using sessionStorage to save whether user is guest or not.
2017-01-03 14:15:32 -06:00
Дамян Минков
c46772015b Merge pull request #1217 from BeatC/fix-watermarks
Fixes issue with watermarks and interface configs.
2016-12-30 16:34:39 -06:00
Дамян Минков
677eef12dd Updates use of showJitsiWatermark. 2016-12-30 12:07:54 -06:00
hristoterezov
cd03b29ece Merge pull request #1219 from jitsi/guest-hint
Adds an option for guest only hint
2016-12-30 11:41:23 -06:00
damencho
63aa60f2d6 Adds an option for a hint message shown only to guests. 2016-12-30 10:59:21 -06:00
damencho
282defc54c Pass parameter to close page about current participant is it guest. 2016-12-30 10:58:21 -06:00
damencho
593de63d49 Adds utils to the close page and an id to the hint question div. 2016-12-30 10:19:58 -06:00
Ilya Daynatovich
5bb53ba036 Fix issue with watermarks 2016-12-30 13:34:03 +02:00
damencho
3c369a4c67 Fixes missing ssi for logging_config.js when meet served from jetty. 2016-12-29 11:18:39 -06:00
damencho
83aeb99b95 Commit from translate.jitsi.org by user damencho.: 202 of 298 strings translated (21 fuzzy). 2016-12-27 19:49:38 +00:00
ibauersachs
188d53ef94 Commit from translate.jitsi.org by user ibauersachs.: 298 of 298 strings translated (0 fuzzy). 2016-12-24 10:48:32 +00:00
395 changed files with 16164 additions and 5253 deletions

View File

@@ -3,6 +3,7 @@ build/*
# Third-party source code which we (1) do not want to modify or (2) try to
# modify as little as possible.
flow-typed/*
libs/*
# ESLint will by default ignore its own configuration file. However, there does

View File

@@ -4,7 +4,10 @@ module.exports = {
'commonjs': true,
'es6': true
},
'extends': 'eslint:recommended',
'extends': [
'eslint:recommended',
'plugin:flowtype/recommended'
],
'globals': {
// The globals that (1) are accessed but not defined within many of our
// files, (2) are certainly defined, and (3) we would like to use
@@ -12,12 +15,16 @@ module.exports = {
// files.
'__filename': false
},
'parser': 'babel-eslint',
'parserOptions': {
'ecmaFeatures': {
'experimentalObjectRestSpread': true
},
'sourceType': 'module'
},
'plugins': [
'flowtype'
],
'rules': {
'new-cap': [
'error',

52
.flowconfig Normal file
View File

@@ -0,0 +1,52 @@
[ignore]
; We fork some components by platform
.*/*[.]android.js
; Ignore "BUCK" generated dirs
<PROJECT_ROOT>/\.buckd/
; Ignore unexpected extra "@providesModule"
.*/node_modules/.*/node_modules/fbjs/.*
; Ignore duplicate module providers
; For RN Apps installed via npm, "Libraries" folder is inside
; "node_modules/react-native" but in the source repo it is in the root
.*/Libraries/react-native/React.js
.*/Libraries/react-native/ReactNative.js
; Ignore packages in node_modules which we (i.e. the jitsi-meet project) have
; seen to cause errors and we have chosen not to fix.
.*/node_modules/babel-core/.*
.*/node_modules/bower/.*
.*/node_modules/jsonlint/.*
[include]
[libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/flow
flow/
[options]
emoji=true
module.system=haste
experimental.strict_type_args=true
munge_underscores=true
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FixMe
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(3[0-8]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(3[0-8]\\|1[0-9]\\|[1-2][0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
unsafe.enable_getters_and_setters=true
[version]
^0.38.0

1
.gitattributes vendored
View File

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

21
.gitignore vendored
View File

@@ -4,7 +4,6 @@ deploy-local.sh
libs/
all.css
*css.map
unsupported_browser.css
.remote-sync.json
.sync-config.cson
@@ -36,21 +35,33 @@ DerivedData
*.xcuserstate
project.xcworkspace
# Android/IJ
# Android/IntelliJ
#
*.iml
build/
.idea
.gradle
local.properties
*.iml
# node.js
#
node_modules/
npm-debug.log
yarn-error.log
# BUCK
#
buck-out/
\.buckd/
android/app/libs
android/keystores/debug.keystore
*.keystore
# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use
# fastlane to re-generate the screenshots whenever they are needed. For more
# information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
#
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots

View File

@@ -1,7 +1,18 @@
# The following do not need to be checked because they do not represent JS
# source code.
build/
debian/
libs/
node_modules/
# The following are checked by ESLint with the maximum configuration which
# supersedes JSHint.
flow-typed/
react/
# The following are checked by ESLint with the minimum configuration which does
# not supersede JSHint but take advantage of advanced language features such as
# Facebook Flow which are not supported by JSHint.
modules/translation/translation.js
analytics.js
webpack.config.babel.js

33
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,33 @@
# How to contribute
We would love to have your help. Before you start working however, please read
and follow this short guide.
# Reporting Issues
Before you open an issue on GitHub, please discuss it on one of our
[mailing lists](https://jitsi.org/Development/MailingLists) and wait for
confirmation from one of the committers. Once you have that confirmation,
please proceed to reporting the issue on GitHub, while providing as much
information as possible. Mention the version of Jitsi Meet, Jicofo and JVB
you are using, and explain (as detailed as you can) how the problem can
be reproduced.
# Code contributions
Found a bug and know how to fix it? Great! Please read on.
## Contributor License Agreement
While the Jitsi projects are released under the
[Apache License 2.0](https://github.com/jitsi/jitsi-meet/blob/master/LICENSE), the copyright
holder and principal creator is [Atlassian](https://www.atlassian.com/). To
ensure that we can continue making these projects available under an Open Source license,
we need you to sign our Apache-based contributor
license agreement as either a [corporation](https://jitsi.org/ccla) or an
[individual](https://jitsi.org/icla). If you cannot accept the terms laid out
in the agreement, unfortunately, we cannot accept your contribution.
## Creating Pull Requests
- Make sure your code passes the linter rules beforehand. The linter is exeuted
automatically when committing code.
- Perform **one** logical change per pull request.
- Maintain a clean list of commits, squash them if necessary.
- Rebase your topic branch on top of the master branch before creating the pull
request.

4
ConferenceEvents.js Normal file
View File

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

View File

@@ -8,16 +8,9 @@ OUTPUT_DIR = .
STYLES_BUNDLE = css/all.bundle.css
STYLES_DESTINATION = css/all.css
STYLES_MAIN = css/main.scss
STYLES_UNSUPPORTED_BROWSER = css/unsupported_browser.scss
WEBPACK = ./node_modules/.bin/webpack
all: update-deps compile deploy clean
# FIXME: there is a problem with node-sass not correctly installed (compiled)
# a quick fix to make sure it is installed on every update
# the problem appears on linux and not on macosx
update-deps:
$(NPM) update && $(NPM) install node-sass
all: compile deploy clean
compile:
$(WEBPACK) -p
@@ -47,7 +40,6 @@ deploy-lib-jitsi-meet:
$(DEPLOY_DIR)
deploy-css:
$(NODE_SASS) css/unsupported_browser.scss css/unsupported_browser.css ; \
$(NODE_SASS) $(STYLES_MAIN) $(STYLES_BUNDLE) && \
$(CLEANCSS) $(STYLES_BUNDLE) > $(STYLES_DESTINATION) ; \
rm $(STYLES_BUNDLE)
@@ -57,8 +49,7 @@ deploy-local:
source-package:
mkdir -p source_package/jitsi-meet/css && \
cp -r *.js *.html connection_optimization favicon.ico fonts images libs sounds LICENSE lang source_package/jitsi-meet && \
cp -r *.js *.html connection_optimization favicon.ico fonts images libs static sounds LICENSE lang source_package/jitsi-meet && \
cp css/all.css source_package/jitsi-meet/css && \
cp css/unsupported_browser.css source_package/jitsi-meet/css && \
(cd source_package ; tar cjf ../jitsi-meet.tar.bz2 jitsi-meet) && \
rm -rf source_package

View File

@@ -1,5 +1,5 @@
Jitsi Meet - Secure, Simple and Scalable Video Conferences
====
# Jitsi Meet - Secure, Simple and Scalable Video Conferences
Jitsi Meet is an open-source (Apache) WebRTC JavaScript application that uses [Jitsi Videobridge](https://jitsi.org/videobridge) to provide high quality, scalable video conferences. You can see [Jitsi Meet in action](http://youtu.be/7vFUVClsNh0) here at the session #482 of the VoIP Users Conference.
You can also try it out yourself at https://meet.jit.si .
@@ -16,8 +16,13 @@ For other systems, or if you wish to install all components manually, see the [d
You can download Debian/Ubuntu binaries:
* [stable](https://download.jitsi.org/stable/) ([instructions](https://jitsi.org/Main/InstallJitsiMeetDebianStableRepository))
* [testing](https://download.jitsi.org/testing/) ([instructions](https://jitsi.org/Main/InstallJitsiMeetDebianTestingRepository))
* [nightly](https://download.jitsi.org/unstable/) ([instructions](https://jitsi.org/Main/InstallJitsiMeetDebianNightlyRepository))
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
Jitsi Meet uses [Browserify](http://browserify.org). If you want to make changes in the code you need to [install Browserify](http://browserify.org/#install). Browserify requires [nodejs](http://nodejs.org).
@@ -34,7 +39,7 @@ To build the Jitsi Meet application, just type
make
```
## Working with the library sources(lib-jitsi-meet).
## 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
@@ -81,6 +86,19 @@ npm unlink lib-jitsi-meet
npm install
```
## Contributing
If you are looking to contribute to Jitsi Meet, first of all, thank you! Please
see our [guidelines for contributing](CONTRIBUTING.md).
## Embedding in external applications
Jitsi Meet provides a very flexible way of embedding it in external applications by using the [Jitsi Meet API](doc/api.md).
## Mobile app
Jitsi Meet is also available as a React Native application for Android and iOS.
Instructions on how to build it can be found [here](doc/mobile.md).
## Discuss
Please use the [Jitsi dev mailing list](http://lists.jitsi.org/pipermail/dev/) to discuss feature requests before opening an issue on Github.

View File

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

View File

@@ -3,9 +3,12 @@
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><!-- WebRTC -->
<!-- XXX: ACCESS_NETWORK_STATE is required by WebRTC. -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
@@ -13,8 +16,8 @@
<uses-feature android:name="android.hardware.camera.autofocus"/>
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="22" />
android:minSdkVersion="19"
android:targetSdkVersion="23" />
<application
android:allowBackup="true"
@@ -26,7 +29,8 @@
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTask"
android:name=".MainActivity">
android:name=".MainActivity"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@@ -35,16 +39,21 @@
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:host="beta.hipchat.me" android:scheme="https" />
<data android:host="beta.meet.jit.si" android:scheme="https" />
<data android:host="chaos.hipchat.me" android:scheme="https" />
<data android:host="enso.me" android:scheme="https" />
<data android:host="hipchat.me" android:scheme="https" />
<data android:host="meet.jit.si" android:scheme="https" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="org.jitsi.meet" />
</intent-filter>
</activity>
<activity
android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<meta-data
android:name="io.fabric.ApiKey"
android:value="a8ae24a58302ba79da1d312138e941f6b86e3242" />
</application>
</manifest>

View File

@@ -1,11 +1,8 @@
package org.jitsi.meet;
import android.os.Bundle;
import com.crashlytics.android.Crashlytics;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import io.fabric.sdk.android.Fabric;
public class MainActivity extends ReactActivity {
/**
@@ -46,11 +43,4 @@ public class MainActivity extends ReactActivity {
protected String getMainComponentName() {
return "App";
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Fabric.with(this, new Crashlytics());
}
}

View File

@@ -1,39 +1,64 @@
package org.jitsi.meet;
import android.app.Application;
import android.util.Log;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.oblador.vectoricons.VectorIconsPackage;
import com.oney.WebRTCModule.WebRTCModulePackage;
import com.facebook.soloader.SoLoader;
import java.util.Arrays;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
/**
* {@inheritDoc}
*/
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
/**
* {@inheritDoc}
*/
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new com.corbt.keepawake.KCKeepAwakePackage(),
new com.facebook.react.shell.MainReactPackage(),
new com.oblador.vectoricons.VectorIconsPackage(),
new com.ocetnik.timer.BackgroundTimerPackage(),
new com.oney.WebRTCModule.WebRTCModulePackage(),
new com.rnimmersive.RNImmersivePackage(),
new org.jitsi.meet.audiomode.AudioModePackage()
);
}
};
/**
* {@inheritDoc}
*/
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
/**
* {@inheritDoc}
*/
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new VectorIconsPackage(),
new WebRTCModulePackage()
);
}
};
public void onCreate() {
super.onCreate();
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
SoLoader.init(this, /* native exopackage */ false);
if (!getReactNativeHost()
.getReactInstanceManager()
.getDevSupportManager()
.getDevSupportEnabled()) {
// TODO Auto-generated method stub
}
}
}

View File

@@ -0,0 +1,322 @@
package org.jitsi.meet.audiomode;
import android.annotation.TargetApi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
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 java.util.HashMap;
import java.util.Map;
/**
* Module implementing a simple API to select the appropriate audio device for a
* conference call.
*
* Audio calls should use <tt>AudioModeModule.AUDIO_CALL</tt>, which uses the
* builtin earpiece, wired headset or bluetooth headset. The builtin earpiece is
* the default audio device.
*
* Video calls should should use <tt>AudioModeModule.VIDEO_CALL</tt>, which uses
* the builtin speaker, earpiece, wired headset or bluetooth headset. The
* builtin speaker is the default audio device.
*
* Before a call has started and after it has ended the
* <tt>AudioModeModule.DEFAULT</tt> mode should be used.
*/
public class AudioModeModule extends ReactContextBaseJavaModule {
/**
* Constants representing the audio mode.
* - DEFAULT: Used before and after every call. It represents the default
* audio routing scheme.
* - AUDIO_CALL: Used for audio only calls. It will use the earpiece by
* default, unless a wired or Bluetooth headset is connected.
* - VIDEO_CALL: Used for video calls. It will use the speaker by default,
* unless a wired or Bluetooth headset is connected.
*/
private static final int DEFAULT = 0;
private static final int AUDIO_CALL = 1;
private static final int VIDEO_CALL = 2;
/**
*
*/
private static final String ACTION_HEADSET_PLUG
= (Build.VERSION.SDK_INT >= 21)
? AudioManager.ACTION_HEADSET_PLUG
: Intent.ACTION_HEADSET_PLUG;
/**
* React Native module name.
*/
private static final String MODULE_NAME = "AudioMode";
/**
* Tag used when logging messages.
*/
static final String TAG = MODULE_NAME;
/**
* {@link AudioManager} instance used to interact with the Android audio
* subsystem.
*/
private final AudioManager audioManager;
/**
* {@link BluetoothHeadsetMonitor} for detecting Bluetooth device changes in
* old (< M) Android versions.
*/
private BluetoothHeadsetMonitor bluetoothHeadsetMonitor;
/**
* {@link Handler} for running all operations on the main thread.
*/
private final Handler mainThreadHandler
= new Handler(Looper.getMainLooper());
/**
* {@link Runnable} for running update operation on the main thread.
*/
private final Runnable mainThreadRunner
= new Runnable() {
@Override
public void run() {
if (mode != -1) {
updateAudioRoute(mode);
}
}
};
/**
* Audio mode currently in use.
*/
private int mode = -1;
/**
* Initializes a new module instance. There shall be a single instance of
* this module throughout the lifetime of the application.
*
* @param reactContext the {@link ReactApplicationContext} where this module
* is created.
*/
public AudioModeModule(ReactApplicationContext reactContext) {
super(reactContext);
audioManager
= (AudioManager)
reactContext.getSystemService(Context.AUDIO_SERVICE);
// Setup runtime device change detection.
setupAudioRouteChangeDetection();
}
/**
* Gets a mapping with the constants this module is exporting.
*
* @return a {@link Map} mapping the constants to be exported with their
* values.
*/
@Override
public Map<String, Object> getConstants() {
Map<String, Object> constants = new HashMap<>();
constants.put("AUDIO_CALL", AUDIO_CALL);
constants.put("DEFAULT", DEFAULT);
constants.put("VIDEO_CALL", VIDEO_CALL);
return constants;
}
/**
* Gets the name for this module, to be used in the React Native bridge.
*
* @return a string with the module name.
*/
@Override
public String getName() {
return MODULE_NAME;
}
/**
* Helper method to trigger an audio route update when devices change. It
* makes sure the operation is performed on the main thread.
*/
void onAudioDeviceChange() {
mainThreadHandler.post(mainThreadRunner);
}
/**
* Helper method to set the output route to a Bluetooth device.
*
* @param enabled true if Bluetooth should use used, false otherwise.
*/
private void setBluetoothAudioRoute(boolean enabled) {
if (enabled) {
audioManager.startBluetoothSco();
audioManager.setBluetoothScoOn(true);
} else {
audioManager.setBluetoothScoOn(false);
audioManager.stopBluetoothSco();
}
}
/**
* Public method to set the current audio mode.
*
* @param mode the desired audio mode.
* @param promise a {@link Promise} which will be resolved if the audio mode
* could be updated successfully, and it will be rejected otherwise.
*/
@ReactMethod
public void setMode(final int mode, final Promise promise) {
if (mode != DEFAULT && mode != AUDIO_CALL && mode != VIDEO_CALL) {
promise.reject("setMode", "Invalid audio mode " + mode);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
if (updateAudioRoute(mode)) {
AudioModeModule.this.mode = mode;
promise.resolve(null);
} else {
promise.reject(
"setMode",
"Failed to set the requested audio mode");
}
}
};
mainThreadHandler.post(r);
}
/**
* Setup the audio route change detection mechanism. We use the
* {@link android.media.AudioDeviceCallback} API on Android >= 23 only.
*/
private void setupAudioRouteChangeDetection() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setupAudioRouteChangeDetectionM();
} else {
setupAudioRouteChangeDetectionPreM();
}
}
/**
* Audio route change detection mechanism for Android API >= 23.
*/
@TargetApi(Build.VERSION_CODES.M)
private void setupAudioRouteChangeDetectionM() {
android.media.AudioDeviceCallback audioDeviceCallback =
new android.media.AudioDeviceCallback() {
@Override
public void onAudioDevicesAdded(
AudioDeviceInfo[] addedDevices) {
Log.d(TAG, "Audio devices added");
onAudioDeviceChange();
}
@Override
public void onAudioDevicesRemoved(
AudioDeviceInfo[] removedDevices) {
Log.d(TAG, "Audio devices removed");
onAudioDeviceChange();
}
};
audioManager.registerAudioDeviceCallback(audioDeviceCallback, null);
}
/**
* Audio route change detection mechanism for Android API < 23.
*/
private void setupAudioRouteChangeDetectionPreM() {
Context context = getReactApplicationContext();
// Detect changes in wired headset connections.
IntentFilter wiredHeadSetFilter = new IntentFilter(ACTION_HEADSET_PLUG);
BroadcastReceiver wiredHeadsetReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Wired headset added / removed");
onAudioDeviceChange();
}
};
context.registerReceiver(wiredHeadsetReceiver, wiredHeadSetFilter);
// Detect Bluetooth device changes.
bluetoothHeadsetMonitor = new BluetoothHeadsetMonitor(this, context);
}
/**
* Updates the audio route for the given mode.
*
* @param mode the audio mode to be used when computing the audio route.
* @return true if the audio route was updated successfully, false
* otherwise.
*/
private boolean updateAudioRoute(int mode) {
Log.d(TAG, "Update audio route for mode: " + mode);
if (mode == DEFAULT) {
audioManager.setMode(AudioManager.MODE_NORMAL);
audioManager.abandonAudioFocus(null);
audioManager.setSpeakerphoneOn(false);
audioManager.setMicrophoneMute(true);
setBluetoothAudioRoute(false);
return true;
}
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
audioManager.setMicrophoneMute(false);
if (audioManager.requestAudioFocus(
null,
AudioManager.STREAM_VOICE_CALL,
AudioManager.AUDIOFOCUS_GAIN)
== AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
Log.d(TAG, "Audio focus request failed");
return false;
}
boolean useSpeaker = (mode == VIDEO_CALL);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// On Android >= M we use the AudioDeviceCallback API, so turn on
// Bluetooth SCO from the start.
if (audioManager.isBluetoothScoAvailableOffCall()) {
audioManager.startBluetoothSco();
}
} else {
// On older Android versions we must set the Bluetooth route
// manually. Also disable the speaker in that case.
setBluetoothAudioRoute(
bluetoothHeadsetMonitor.isHeadsetAvailable());
if (bluetoothHeadsetMonitor.isHeadsetAvailable()) {
useSpeaker = false;
}
}
// XXX: isWiredHeadsetOn is not deprecated when used just for knowing if
// there is a wired headset connected, regardless of audio being routed
// to it.
audioManager.setSpeakerphoneOn(
useSpeaker
&& !(audioManager.isWiredHeadsetOn()
|| audioManager.isBluetoothScoOn()));
return true;
}
}

View File

@@ -0,0 +1,48 @@
package org.jitsi.meet.audiomode;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Implements {@link ReactPackage} for {@link AudioModeModule}.
*/
public class AudioModePackage implements ReactPackage {
/**
* {@inheritDoc}
*/
@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
/**
* {@inheritDoc}
*
* @return List of native modules to be exposed by React Native.
*/
@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new AudioModeModule(reactContext));
return modules;
}
/**
* {@inheritDoc}
*/
@Override
public List<ViewManager> createViewManagers(
ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}

View File

@@ -0,0 +1,189 @@
package org.jitsi.meet.audiomode;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
/**
* Helper class to detect and handle Bluetooth device changes. It monitors
* Bluetooth headsets being connected / disconnected and notifies the module
* about device changes when this occurs.
*/
public class BluetoothHeadsetMonitor {
/**
* {@link AudioModeModule} where this monitor reports.
*/
private final AudioModeModule audioModeModule;
/**
* The {@link Context} in which {@link #audioModeModule} executes.
*/
private final Context context;
/**
* Reference to a proxy object which allows us to query connected devices.
*/
private BluetoothHeadset headset;
/**
* Flag indicating if there are any Bluetooth headset devices currently
* available.
*/
private boolean headsetAvailable = false;
/**
* {@link Handler} for running all operations on the main thread.
*/
private final Handler mainThreadHandler
= new Handler(Looper.getMainLooper());
/**
* Helper for running Bluetooth operations on the main thread.
*/
private final Runnable updateDevicesRunnable
= new Runnable() {
@Override
public void run() {
headsetAvailable
= (headset != null)
&& !headset.getConnectedDevices().isEmpty();
audioModeModule.onAudioDeviceChange();
}
};
public BluetoothHeadsetMonitor(
AudioModeModule audioModeModule,
Context context) {
this.audioModeModule = audioModeModule;
this.context = context;
AudioManager audioManager
= (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
if (!audioManager.isBluetoothScoAvailableOffCall()) {
Log.w(AudioModeModule.TAG, "Bluetooth SCO is not available");
return;
}
if (getBluetoothHeadsetProfileProxy()) {
registerBluetoothReceiver();
// Initial detection.
updateDevices();
}
}
private boolean getBluetoothHeadsetProfileProxy() {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter == null) {
Log.w(AudioModeModule.TAG, "Device doesn't support Bluetooth");
return false;
}
// XXX: The profile listener listens for system services of the given
// type being available to the application. That is, if our Bluetooth
// adapter has the "headset" profile.
BluetoothProfile.ServiceListener listener
= new BluetoothProfile.ServiceListener() {
@Override
public void onServiceConnected(
int profile,
BluetoothProfile proxy) {
if (profile == BluetoothProfile.HEADSET) {
headset = (BluetoothHeadset) proxy;
updateDevices();
}
}
@Override
public void onServiceDisconnected(int profile) {
// The logic is the same as the logic of onServiceConnected.
onServiceConnected(profile, /* proxy */ null);
}
};
return
adapter.getProfileProxy(
context,
listener,
BluetoothProfile.HEADSET);
}
/**
* Returns the current headset availability.
*
* @return true if there is a Bluetooth headset connected, false otherwise.
*/
public boolean isHeadsetAvailable() {
return headsetAvailable;
}
private void onBluetoothReceiverReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
// XXX: This action will be fired when a Bluetooth headset is
// connected or disconnected to the system. This is not related to
// audio routing.
int state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, -99);
switch (state) {
case BluetoothHeadset.STATE_CONNECTED:
case BluetoothHeadset.STATE_DISCONNECTED:
Log.d(
AudioModeModule.TAG,
"BT headset connection state changed: " + state);
updateDevices();
break;
}
} else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)) {
// XXX: This action will be fired when the connection established
// with a Bluetooth headset (called a SCO connection) changes state.
// When the SCO connection is active we route audio to it.
int state
= intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -99);
switch (state) {
case AudioManager.SCO_AUDIO_STATE_CONNECTED:
case AudioManager.SCO_AUDIO_STATE_DISCONNECTED:
Log.d(
AudioModeModule.TAG,
"BT SCO connection state changed: " + state);
updateDevices();
break;
}
}
}
private void registerBluetoothReceiver() {
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
onBluetoothReceiverReceive(context, intent);
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
context.registerReceiver(receiver, filter);
}
/**
* Detects if there are new devices connected / disconnected and fires the
* {@link AudioModeModule#onAudioDeviceChange()} callback.
*/
private void updateDevices() {
mainThreadHandler.post(updateDevicesRunnable);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

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

View File

@@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.1'
classpath 'com.android.tools.build:gradle:2.2.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

View File

@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip

View File

@@ -1,6 +1,12 @@
rootProject.name = 'jitsi-meet-react'
include ':app'
include ':react-native-background-timer'
project(':react-native-background-timer').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-background-timer/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'
project(':react-native-keep-awake').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-keep-awake/android')
include ':react-native-vector-icons'
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')
include ':react-native-webrtc'

258
app.js
View File

@@ -1,6 +1,4 @@
/* global $, config, getRoomName, loggingConfig, JitsiMeetJS */
/* application specific logic */
const logger = require("jitsi-meet-logger").getLogger(__filename);
import "babel-polyfill";
import "jquery";
@@ -18,103 +16,13 @@ import 'aui-experimental-css';
window.toastr = require("toastr");
const Logger = require("jitsi-meet-logger");
const LogCollector = Logger.LogCollector;
import JitsiMeetLogStorage from "./modules/util/JitsiMeetLogStorage";
import URLProcessor from "./modules/config/URLProcessor";
import {
generateRoomWithoutSeparator
} from './react/features/base/util/roomnameGenerator';
import UI from "./modules/UI/UI";
import settings from "./modules/settings/Settings";
import conference from './conference';
import ConferenceUrl from './modules/URL/ConferenceUrl';
import API from './modules/API/API';
import UIEvents from './service/UI/UIEvents';
import getTokenData from "./modules/tokendata/TokenData";
import translation from "./modules/translation/translation";
const ConferenceEvents = JitsiMeetJS.events.conference;
/**
* Tries to push history state with the following parameters:
* 'VideoChat', `Room: ${roomName}`, URL. If fail, prints the error and returns
* it.
*/
function pushHistoryState(roomName, URL) {
try {
window.history.pushState(
'VideoChat', `Room: ${roomName}`, URL
);
} catch (e) {
logger.warn("Push history state failed with parameters:",
'VideoChat', `Room: ${roomName}`, URL, e);
return e;
}
return null;
}
/**
* Replaces current history state(replaces the URL displayed by the browser).
* @param {string} newUrl the URL string which is to be displayed by the browser
* to the user.
*/
function replaceHistoryState (newUrl) {
if (window.history
&& typeof window.history.replaceState === 'function') {
window.history.replaceState({}, document.title, newUrl);
}
}
/**
* Builds and returns the room name.
*/
function buildRoomName () {
let roomName = getRoomName();
if(!roomName) {
let word = generateRoomWithoutSeparator();
roomName = word.toLowerCase();
let historyURL = window.location.href + word;
//Trying to push state with current URL + roomName
pushHistoryState(word, historyURL);
}
return roomName;
}
/**
* Adjusts the logging levels.
* @private
*/
function configureLoggingLevels () {
// NOTE The library Logger is separated from the app loggers, so the levels
// have to be set in two places
// Set default logging level
const defaultLogLevel
= loggingConfig.defaultLogLevel || JitsiMeetJS.logLevels.TRACE;
Logger.setLogLevel(defaultLogLevel);
JitsiMeetJS.setLogLevel(defaultLogLevel);
// NOTE console was used on purpose here to go around the logging
// and always print the default logging level to the console
console.info("Default logging level set to: " + defaultLogLevel);
// Set log level for each logger
if (loggingConfig) {
Object.keys(loggingConfig).forEach(function(loggerName) {
if ('defaultLogLevel' !== loggerName) {
const level = loggingConfig[loggerName];
Logger.setLogLevelById(level, loggerName);
JitsiMeetJS.setLogLevelById(level, loggerName);
}
});
}
}
import remoteControl from "./modules/remotecontrol/RemoteControl";
const APP = {
// Used by do_external_connect.js if we receive the attach data after
@@ -153,163 +61,15 @@ const APP = {
ConferenceUrl : null,
connection: null,
API,
init () {
this.initLogging();
this.keyboardshortcut =
require("./modules/keyboardshortcut/keyboardshortcut");
this.configFetch = require("./modules/config/HttpConfigFetch");
this.tokenData = getTokenData();
},
initLogging () {
// Adjust logging level
configureLoggingLevels();
// Create the LogCollector and register it as the global log transport.
// It is done early to capture as much logs as possible. Captured logs
// will be cached, before the JitsiMeetLogStorage gets ready (statistics
// module is initialized).
if (!this.logCollector && !loggingConfig.disableLogCollector) {
this.logCollector = new LogCollector(new JitsiMeetLogStorage());
Logger.addGlobalTransport(this.logCollector);
JitsiMeetJS.addGlobalLogTransport(this.logCollector);
}
}
remoteControl
};
/**
* If JWT token data it will be used for local user settings
*/
function setTokenData() {
let localUser = APP.tokenData.caller;
if(localUser) {
APP.settings.setEmail((localUser.getEmail() || "").trim(), true);
APP.settings.setAvatarUrl((localUser.getAvatarUrl() || "").trim());
APP.settings.setDisplayName((localUser.getName() || "").trim(), true);
}
}
function init() {
setTokenData();
// Initialize the conference URL handler
APP.ConferenceUrl = new ConferenceUrl(window.location);
// Clean up the URL displayed by the browser
replaceHistoryState(APP.ConferenceUrl.getInviteUrl());
// TODO The execution of the mobile app starts from react/index.native.js.
// Similarly, the execution of the Web app should start from
// react/index.web.js for the sake of consistency and ease of understanding.
// Temporarily though because we are at the beginning of introducing React
// into the Web app, allow the execution of the Web app to start from app.js
// in order to reduce the complexity of the beginning step.
require('./react');
const isUIReady = APP.UI.start();
if (isUIReady) {
APP.conference.init({roomName: buildRoomName()}).then(() => {
if (APP.logCollector) {
// Start the LogCollector's periodic "store logs" task only if
// we're in the conference and not on the welcome page. This is
// determined by the value of "isUIReady" const above.
APP.logCollector.start();
APP.logCollectorStarted = true;
// Make an attempt to flush in case a lot of logs have been
// cached, before the collector was started.
APP.logCollector.flush();
// This event listener will flush the logs, before
// the statistics module (CallStats) is stopped.
//
// NOTE The LogCollector is not stopped, because this event can
// be triggered multiple times during single conference
// (whenever statistics module is stopped). That includes
// the case when Jicofo terminates the single person left in the
// room. It will then restart the media session when someone
// eventually join the room which will start the stats again.
APP.conference.addConferenceListener(
ConferenceEvents.BEFORE_STATISTICS_DISPOSED,
() => {
if (APP.logCollector) {
APP.logCollector.flush();
}
}
);
}
APP.UI.initConference();
APP.UI.addListener(UIEvents.LANG_CHANGED, language => {
APP.translation.setLanguage(language);
APP.settings.setLanguage(language);
});
APP.keyboardshortcut.init();
}).catch(err => {
APP.UI.hideRingOverLay();
APP.API.notifyConferenceLeft(APP.conference.roomName);
logger.error(err);
});
}
}
/**
* If we have an HTTP endpoint for getting config.json configured we're going to
* read it and override properties from config.js and interfaceConfig.js.
* If there is no endpoint we'll just continue with initialization.
* Keep in mind that if the endpoint has been configured and we fail to obtain
* the config for any reason then the conference won't start and error message
* will be displayed to the user.
*/
function obtainConfigAndInit() {
let roomName = APP.conference.roomName;
if (config.configLocation) {
APP.configFetch.obtainConfig(
config.configLocation, roomName,
// Get config result callback
function(success, error) {
if (success) {
var now = APP.connectionTimes["configuration.fetched"] =
window.performance.now();
logger.log("(TIME) configuration fetched:\t", now);
init();
} else {
// Show obtain config error,
// pass the error object for report
APP.UI.messageHandler.openReportDialog(
null, "dialog.connectError", error);
}
});
} else {
require("./modules/config/BoshAddressChoice").chooseAddress(
config, roomName);
init();
}
}
$(document).ready(function () {
var now = APP.connectionTimes["document.ready"] = window.performance.now();
logger.log("(TIME) document ready:\t", now);
URLProcessor.setConfigParametersFromUrl();
APP.init();
APP.translation.init(settings.getLanguage());
APP.API.init(APP.tokenData.externalAPISettings);
obtainConfigAndInit();
});
$(window).bind('beforeunload', function () {
// Stop the LogCollector
if (APP.logCollectorStarted) {
APP.logCollector.stop();
APP.logCollectorStarted = false;
}
APP.API.dispose();
});
// TODO The execution of the mobile app starts from react/index.native.js.
// Similarly, the execution of the Web app should start from react/index.web.js
// for the sake of consistency and ease of understanding. Temporarily though
// because we are at the beginning of introducing React into the Web app, allow
// the execution of the Web app to start from app.js in order to reduce the
// complexity of the beginning step.
require('./react');
module.exports = APP;

View File

@@ -10,13 +10,43 @@ import Recorder from './modules/recorder/Recorder';
import mediaDeviceHelper from './modules/devices/mediaDeviceHelper';
import {reportError} from './modules/util/helpers';
import { reload, reportError } from './modules/util/helpers';
import UIEvents from './service/UI/UIEvents';
import UIUtil from './modules/UI/util/UIUtil';
import * as JitsiMeetConferenceEvents from './ConferenceEvents';
import analytics from './modules/analytics/analytics';
import EventEmitter from "events";
import {
AVATAR_ID_COMMAND,
AVATAR_URL_COMMAND,
conferenceFailed,
conferenceJoined,
conferenceLeft,
EMAIL_COMMAND
} from './react/features/base/conference';
import {
isFatalJitsiConnectionError
} from './react/features/base/lib-jitsi-meet';
import {
changeParticipantAvatarID,
changeParticipantAvatarURL,
changeParticipantEmail,
participantJoined,
participantLeft,
participantRoleChanged
} from './react/features/base/participants';
import {
showDesktopPicker
} from './react/features/desktop-picker';
import {
mediaPermissionPromptVisibilityChanged,
suspendDetected
} from './react/features/overlay';
const ConnectionEvents = JitsiMeetJS.events.connection;
const ConnectionErrors = JitsiMeetJS.errors.connection;
@@ -28,6 +58,8 @@ const TrackErrors = JitsiMeetJS.errors.track;
const ConnectionQualityEvents = JitsiMeetJS.events.connectionQuality;
const eventEmitter = new EventEmitter();
let room, connection, localAudio, localVideo;
/**
@@ -37,16 +69,26 @@ let DSExternalInstallationInProgress = false;
import {VIDEO_CONTAINER_TYPE} from "./modules/UI/videolayout/VideoContainer";
/*
* Logic to open a desktop picker put on the window global for
* lib-jitsi-meet to detect and invoke
*/
window.JitsiMeetScreenObtainer = {
openDesktopPicker(onSourceChoose) {
APP.store.dispatch(showDesktopPicker(onSourceChoose));
}
};
/**
* Known custom conference commands.
*/
const commands = {
EMAIL: "email",
AVATAR_URL: "avatar-url",
AVATAR_ID: "avatar-id",
AVATAR_ID: AVATAR_ID_COMMAND,
AVATAR_URL: AVATAR_URL_COMMAND,
CUSTOM_ROLE: "custom-role",
EMAIL: EMAIL_COMMAND,
ETHERPAD: "etherpad",
SHARED_VIDEO: "shared-video",
CUSTOM_ROLE: "custom-role"
SHARED_VIDEO: "shared-video"
};
/**
@@ -86,7 +128,10 @@ function createInitialLocalTracksAndConnect(roomName) {
JitsiMeetJS.mediaDevices.addEventListener(
JitsiMeetJS.events.mediaDevices.PERMISSION_PROMPT_IS_SHOWN,
browser => APP.UI.showUserMediaPermissionsGuidanceOverlay(browser));
browser =>
APP.store.dispatch(
mediaPermissionPromptVisibilityChanged(true, browser))
);
// First try to retrieve both audio and video.
let tryCreateLocalTracks = createLocalTracks(
@@ -104,8 +149,7 @@ function createInitialLocalTracksAndConnect(roomName) {
return Promise.all([ tryCreateLocalTracks, connect(roomName) ])
.then(([tracks, con]) => {
APP.UI.hideUserMediaPermissionsGuidanceOverlay();
APP.store.dispatch(mediaPermissionPromptVisibilityChanged(false));
if (audioAndVideoError) {
if (audioOnlyError) {
// If both requests for 'audio' + 'video' and 'audio' only
@@ -134,6 +178,29 @@ function sendData (command, value) {
room.sendCommand(command, {value: value});
}
/**
* Sets up initially the properties of the local participant - email, avatarID,
* avatarURL, displayName, etc.
*/
function _setupLocalParticipantProperties() {
const email = APP.settings.getEmail();
email && sendData(commands.EMAIL, email);
const avatarUrl = APP.settings.getAvatarUrl();
avatarUrl && sendData(commands.AVATAR_URL, avatarUrl);
if (!email && !avatarUrl) {
sendData(commands.AVATAR_ID, APP.settings.getAvatarId());
}
let nick = APP.settings.getDisplayName();
if (config.useNicks && !nick) {
nick = APP.UI.askForNickname();
APP.settings.setDisplayName(nick);
}
nick && room.setDisplayName(nick);
}
/**
* Get user nickname by user id.
* @param {string} id user id
@@ -195,10 +262,11 @@ function muteLocalVideo (muted) {
function maybeRedirectToWelcomePage(options) {
// if close page is enabled redirect to it, without further action
if (config.enableClosePage) {
if (options.feedbackSubmitted)
window.location.pathname = "close.html";
else
window.location.pathname = "close2.html";
// save whether current user is guest or not, before navigating
// to close page
window.sessionStorage.setItem('guest', APP.tokenData.isGuest);
assignWindowLocationPathname('static/'
+ (options.feedbackSubmitted ? "close.html" : "close2.html"));
return;
}
@@ -211,11 +279,42 @@ function maybeRedirectToWelcomePage(options) {
if (config.enableWelcomePage) {
setTimeout(() => {
APP.settings.setWelcomePageEnabled(true);
window.location.pathname = "/";
assignWindowLocationPathname('./');
}, 3000);
}
}
/**
* Assigns a specific pathname to window.location.pathname taking into account
* the context root of the Web app.
*
* @param {string} pathname - The pathname to assign to
* window.location.pathname. If the specified pathname is relative, the context
* root of the Web app will be prepended to the specified pathname before
* assigning it to window.location.pathname.
* @return {void}
*/
function assignWindowLocationPathname(pathname) {
const windowLocation = window.location;
if (!pathname.startsWith('/')) {
// XXX To support a deployment in a sub-directory, assume that the room
// (name) is the last non-directory component of the path (name).
let contextRoot = windowLocation.pathname;
contextRoot
= contextRoot.substring(0, contextRoot.lastIndexOf('/') + 1);
// A pathname equal to ./ specifies the current directory. It will be
// fine but pointless to include it because contextRoot is the current
// directory.
pathname.startsWith('./') && (pathname = pathname.substring(2));
pathname = contextRoot + pathname;
}
windowLocation.pathname = pathname;
}
/**
* Create local tracks of specified types.
* @param {Object} options
@@ -260,22 +359,6 @@ function createLocalTracks (options, checkForPermissionPrompt) {
'failed to create local tracks', options.devices, err);
return Promise.reject(err);
});
}
/**
* Changes the email for the local user
* @param email {string} the new email
*/
function changeLocalEmail(email = '') {
email = email.trim();
if (email === APP.settings.getEmail()) {
return;
}
APP.settings.setEmail(email);
APP.UI.setUserEmail(room.myUserId(), email);
sendData(commands.EMAIL, email);
}
/**
@@ -313,6 +396,7 @@ class ConferenceConnector {
this._reject(err);
}
_onConferenceFailed(err, ...params) {
APP.store.dispatch(conferenceFailed(room, err, ...params));
logger.error('CONFERENCE FAILED:', err, ...params);
APP.UI.hideRingOverLay();
switch (err) {
@@ -331,7 +415,7 @@ class ConferenceConnector {
case ConferenceErrors.NOT_ALLOWED_ERROR:
{
// let's show some auth not allowed page
window.location.pathname = "authError.html";
assignWindowLocationPathname('static/authError.html');
}
break;
@@ -387,8 +471,6 @@ class ConferenceConnector {
// the app. Both the errors above are unrecoverable from the library
// perspective.
room.leave().then(() => connection.disconnect());
APP.UI.showPageReloadOverlay(
false /* not a network type of failure */, err);
break;
case ConferenceErrors.CONFERENCE_MAX_USERS:
@@ -396,7 +478,7 @@ class ConferenceConnector {
APP.UI.notifyMaxUsersLimitReached();
break;
case ConferenceErrors.INCOMPATIBLE_SERVER_VERSIONS:
window.location.reload();
reload();
break;
default:
this._handleConferenceFailed(err, ...params);
@@ -445,6 +527,23 @@ function disconnect() {
return Promise.resolve();
}
/**
* Handles CONNECTION_FAILED events from lib-jitsi-meet.
*
* @param {JitsiMeetJS.connection.error} error - The reported error.
* @returns {void}
* @private
*/
function _connectionFailedHandler(error) {
if (isFatalJitsiConnectionError(error)) {
APP.connection.removeEventListener(
ConnectionEvents.CONNECTION_FAILED,
_connectionFailedHandler);
if (room)
room.leave();
}
}
export default {
isModerator: false,
audioMuted: false,
@@ -497,14 +596,19 @@ export default {
return createInitialLocalTracksAndConnect(options.roomName);
}).then(([tracks, con]) => {
logger.log('initialized with %s local tracks', tracks.length);
con.addEventListener(
ConnectionEvents.CONNECTION_FAILED,
_connectionFailedHandler);
APP.connection = connection = con;
this._bindConnectionFailedHandler(con);
this._createRoom(tracks);
this.isDesktopSharingEnabled =
JitsiMeetJS.isDesktopSharingEnabled();
APP.remoteControl.init();
this._createRoom(tracks);
if (UIUtil.isButtonEnabled('contacts'))
if (UIUtil.isButtonEnabled('contacts')
&& !interfaceConfig.filmStripOnly) {
APP.UI.ContactList = new ContactList(room);
}
// if user didn't give access to mic or camera or doesn't have
// them at all, we disable corresponding toolbar buttons
@@ -537,47 +641,6 @@ export default {
isLocalId (id) {
return this.getMyUserId() === id;
},
/**
* Binds a handler that will handle the case when the connection is dropped
* in the middle of the conference.
* @param {JitsiConnection} connection the connection to which the handler
* will be bound to.
* @private
*/
_bindConnectionFailedHandler (connection) {
const handler = function (error, errMsg) {
/* eslint-disable no-case-declarations */
switch (error) {
case ConnectionErrors.CONNECTION_DROPPED_ERROR:
case ConnectionErrors.OTHER_ERROR:
case ConnectionErrors.SERVER_ERROR:
logger.error("XMPP connection error: " + errMsg);
// From all of the cases above only CONNECTION_DROPPED_ERROR
// is considered a network type of failure
const isNetworkFailure
= error === ConnectionErrors.CONNECTION_DROPPED_ERROR;
APP.UI.showPageReloadOverlay(
isNetworkFailure,
"xmpp-conn-dropped:" + errMsg);
connection.removeEventListener(
ConnectionEvents.CONNECTION_FAILED, handler);
// FIXME it feels like the conference should be stopped
// by lib-jitsi-meet
if (room)
room.leave();
break;
}
/* eslint-enable no-case-declarations */
};
connection.addEventListener(
ConnectionEvents.CONNECTION_FAILED, handler);
},
/**
* Simulates toolbar button click for audio mute. Used by shortcuts and API.
* @param mute true for mute and false for unmute.
@@ -652,7 +715,7 @@ export default {
* false.
*/
isCallstatsEnabled () {
return room.isCallstatsEnabled();
return room && room.isCallstatsEnabled();
},
/**
* Sends the given feedback through CallStats if enabled.
@@ -664,6 +727,18 @@ export default {
sendFeedback (overallFeedback, detailedFeedback) {
return room.sendFeedback (overallFeedback, detailedFeedback);
},
/**
* Get speaker stats that track total dominant speaker time.
*
* @returns {object} A hash with keys being user ids and values being the
* library's SpeakerStats model used for calculating time as dominant
* speaker.
*/
getSpeakerStats() {
return room.getSpeakerStats();
},
/**
* Returns the connection times stored in the library.
*/
@@ -679,6 +754,39 @@ export default {
return this._room
&& this._room.getConnectionState();
},
/**
* Obtains current P2P ICE connection state.
* @return {string|null} ICE connection state or <tt>null</tt> if there's no
* P2P connection
*/
getP2PConnectionState () {
return this._room
&& this._room.getP2PConnectionState();
},
/**
* Starts P2P (for tests only)
* @private
*/
_startP2P () {
try {
this._room && this._room.startP2PSession();
} catch (error) {
logger.error("Start P2P failed", error);
throw error;
}
},
/**
* Stops P2P (for tests only)
* @private
*/
_stopP2P () {
try {
this._room && this._room.stopP2PSession();
} catch (error) {
logger.error("Stop P2P failed", error);
throw error;
}
},
/**
* Checks whether or not our connection is currently in interrupted and
* reconnect attempts are in progress.
@@ -863,21 +971,7 @@ export default {
this.invite = new Invite(room);
this._room = room; // FIXME do not use this
let email = APP.settings.getEmail();
email && sendData(this.commands.defaults.EMAIL, email);
let avatarUrl = APP.settings.getAvatarUrl();
avatarUrl && sendData(this.commands.defaults.AVATAR_URL,
avatarUrl);
!email && sendData(
this.commands.defaults.AVATAR_ID, APP.settings.getAvatarId());
let nick = APP.settings.getDisplayName();
if (config.useNicks && !nick) {
nick = APP.UI.askForNickname();
APP.settings.setDisplayName(nick);
}
nick && room.setDisplayName(nick);
_setupLocalParticipantProperties();
this._setupListeners();
},
@@ -912,43 +1006,40 @@ export default {
return options;
},
/**
* Start using provided video stream.
* Stops previous video stream.
* @param {JitsiLocalTrack} [stream] new stream to use or null
* @returns {Promise}
*/
useVideoStream (stream) {
let promise = Promise.resolve();
if (localVideo) {
// this calls room.removeTrack internally
// so we don't need to remove it manually
promise = localVideo.dispose();
}
localVideo = stream;
return promise.then(function () {
if (stream) {
return room.addTrack(stream);
}
}).then(() => {
if (stream) {
this.videoMuted = stream.isMuted();
this.isSharingScreen = stream.videoType === 'desktop';
/**
* Start using provided video stream.
* Stops previous video stream.
* @param {JitsiLocalTrack} [stream] new stream to use or null
* @returns {Promise}
*/
useVideoStream (newStream) {
return room.replaceTrack(localVideo, newStream)
.then(() => {
// We call dispose after doing the replace because
// dispose will try and do a new o/a after the
// track removes itself. Doing it after means
// the JitsiLocalTrack::conference member is already
// cleared, so it won't try and do the o/a
if (localVideo) {
localVideo.dispose();
}
localVideo = newStream;
if (newStream) {
this.videoMuted = newStream.isMuted();
this.isSharingScreen = newStream.videoType === 'desktop';
APP.UI.addLocalStream(stream);
APP.UI.addLocalStream(newStream);
stream.videoType === 'camera'
&& APP.UI.setCameraButtonEnabled(true);
} else {
this.videoMuted = false;
this.isSharingScreen = false;
}
APP.UI.setVideoMuted(this.getMyUserId(), this.videoMuted);
APP.UI.updateDesktopSharingButtons();
});
newStream.videoType === 'camera'
&& APP.UI.setCameraButtonEnabled(true);
} else {
this.videoMuted = false;
this.isSharingScreen = false;
}
APP.UI.setVideoMuted(this.getMyUserId(), this.videoMuted);
APP.UI.updateDesktopSharingButtons();
});
},
/**
@@ -957,31 +1048,27 @@ export default {
* @param {JitsiLocalTrack} [stream] new stream to use or null
* @returns {Promise}
*/
useAudioStream (stream) {
let promise = Promise.resolve();
if (localAudio) {
// this calls room.removeTrack internally
// so we don't need to remove it manually
promise = localAudio.dispose();
}
localAudio = stream;
return promise.then(function () {
if (stream) {
return room.addTrack(stream);
}
}).then(() => {
if (stream) {
this.audioMuted = stream.isMuted();
APP.UI.addLocalStream(stream);
} else {
this.audioMuted = false;
}
APP.UI.setMicrophoneButtonEnabled(true);
APP.UI.setAudioMuted(this.getMyUserId(), this.audioMuted);
});
useAudioStream (newStream) {
return room.replaceTrack(localAudio, newStream)
.then(() => {
// We call dispose after doing the replace because
// dispose will try and do a new o/a after the
// track removes itself. Doing it after means
// the JitsiLocalTrack::conference member is already
// cleared, so it won't try and do the o/a
if (localAudio) {
localAudio.dispose();
}
localAudio = newStream;
if (newStream) {
this.audioMuted = newStream.isMuted();
APP.UI.addLocalStream(newStream);
} else {
this.audioMuted = false;
}
APP.UI.setMicrophoneButtonEnabled(true);
APP.UI.setAudioMuted(this.getMyUserId(), this.audioMuted);
});
},
videoSwitchInProgress: false,
@@ -999,7 +1086,7 @@ export default {
let externalInstallation = false;
if (shareScreen) {
createLocalTracks({
this.screenSharingPromise = createLocalTracks({
devices: ['desktop'],
desktopSharingExtensionExternalInstallation: {
interval: 500,
@@ -1088,7 +1175,10 @@ export default {
dialogTitleKey, dialogTxt, false);
});
} else {
createLocalTracks({ devices: ['video'] }).then(
APP.remoteControl.receiver.stop();
this.screenSharingPromise = createLocalTracks(
{ devices: ['video'] })
.then(
([stream]) => this.useVideoStream(stream)
).then(() => {
this.videoSwitchInProgress = false;
@@ -1108,11 +1198,17 @@ export default {
_setupListeners () {
// add local streams when joined to the conference
room.on(ConferenceEvents.CONFERENCE_JOINED, () => {
APP.store.dispatch(conferenceJoined(room));
APP.UI.mucJoined();
APP.API.notifyConferenceJoined(APP.conference.roomName);
APP.UI.markVideoInterrupted(false);
});
room.on(
ConferenceEvents.CONFERENCE_LEFT,
(...args) => APP.store.dispatch(conferenceLeft(room, ...args)));
room.on(
ConferenceEvents.AUTH_STATUS_CHANGED,
function (authEnabled, authLogin) {
@@ -1120,10 +1216,18 @@ export default {
}
);
room.on(ConferenceEvents.PARTCIPANT_FEATURES_CHANGED,
user => APP.UI.onUserFeaturesChanged(user));
room.on(ConferenceEvents.USER_JOINED, (id, user) => {
if (user.isHidden())
return;
APP.store.dispatch(participantJoined({
id,
name: user.getDisplayName(),
role: user.getRole()
}));
logger.log('USER %s connnected', id, user);
APP.API.notifyUserJoined(id);
APP.UI.addUser(user);
@@ -1132,6 +1236,7 @@ export default {
APP.UI.updateUserRole(user);
});
room.on(ConferenceEvents.USER_LEFT, (id, user) => {
APP.store.dispatch(participantLeft(id, user));
logger.log('USER %s LEFT', id, user);
APP.API.notifyUserLeft(id);
APP.UI.removeUser(id, user.getDisplayName());
@@ -1140,6 +1245,7 @@ export default {
room.on(ConferenceEvents.USER_ROLE_CHANGED, (id, role) => {
APP.store.dispatch(participantRoleChanged(id, role));
if (this.isLocalId(id)) {
logger.info(`My role changed, new role: ${role}`);
if (this.isModerator !== room.isModerator()) {
@@ -1207,23 +1313,16 @@ export default {
room.on(ConferenceEvents.TALK_WHILE_MUTED, () => {
APP.UI.showToolbar(6000);
UIUtil.animateShowElement($("#talkWhileMutedPopup"), true, 5000);
APP.UI.showCustomToolbarPopup('#talkWhileMutedPopup', true, 5000);
});
/*
room.on(ConferenceEvents.IN_LAST_N_CHANGED, (inLastN) => {
//FIXME
if (config.muteLocalVideoIfNotInLastN) {
// TODO mute or unmute if required
// mark video on UI
// APP.UI.markVideoMuted(true/false);
}
});
*/
room.on(
ConferenceEvents.LAST_N_ENDPOINTS_CHANGED, (ids, enteringIds) => {
APP.UI.handleLastNEndpoints(ids, enteringIds);
ConferenceEvents.LAST_N_ENDPOINTS_CHANGED,
(leavingIds, enteringIds) => {
APP.UI.handleLastNEndpoints(leavingIds, enteringIds);
});
room.on(
ConferenceEvents.PARTICIPANT_CONN_STATUS_CHANGED,
(id, isActive) => {
@@ -1255,6 +1354,57 @@ export default {
APP.API.notifyReceivedChatMessage(id, nick, text, ts);
APP.UI.addMessage(id, nick, text, ts);
});
APP.UI.addListener(UIEvents.MESSAGE_CREATED, (message) => {
APP.API.notifySendingChatMessage(message);
room.sendTextMessage(message);
});
APP.UI.addListener(UIEvents.SELECTED_ENDPOINT, (id) => {
try {
// do not try to select participant if there is none (we
// are alone in the room), otherwise an error will be
// thrown cause reporting mechanism is not available
// (datachannels currently)
if (room.getParticipants().length === 0)
return;
room.selectParticipant(id);
} catch (e) {
JitsiMeetJS.analytics.sendEvent(
'selectParticipant.failed');
reportError(e);
}
});
APP.UI.addListener(UIEvents.PINNED_ENDPOINT,
(smallVideo, isPinned) => {
let smallVideoId = smallVideo.getId();
let isLocal = APP.conference.isLocalId(smallVideoId);
let eventName
= (isPinned ? "pinned" : "unpinned") + "." +
(isLocal ? "local" : "remote");
let participantCount = room.getParticipantCount();
JitsiMeetJS.analytics.sendEvent(
eventName,
{ value: participantCount });
// FIXME why VIDEO_CONTAINER_TYPE instead of checking if
// the participant is on the large video ?
if (smallVideo.getVideoType() === VIDEO_CONTAINER_TYPE
&& !isLocal) {
// When the library starts supporting multiple pins we
// would pass the isPinned parameter together with the
// identifier, but currently we send null to indicate that
// we unpin the last pinned.
try {
room.pinParticipant(isPinned ? smallVideoId : null);
} catch (e) {
reportError(e);
}
}
});
}
room.on(ConferenceEvents.CONNECTION_INTERRUPTED, () => {
@@ -1291,6 +1441,7 @@ export default {
});
room.on(ConferenceEvents.SUSPEND_DETECTED, () => {
APP.store.dispatch(suspendDetected());
// After wake up, we will be in a state where conference is left
// there will be dialog shown to user.
// We do not want video/audio as we show an overlay and after it
@@ -1304,14 +1455,13 @@ export default {
this.deviceChangeListener);
// stop local video
if (localVideo)
if (localVideo) {
localVideo.dispose();
}
// stop local audio
if (localAudio)
if (localAudio) {
localAudio.dispose();
// show overlay
APP.UI.showSuspendedOverlay();
}
});
room.on(ConferenceEvents.DTMF_SUPPORT_CHANGED, (isDTMFSupported) => {
@@ -1332,13 +1482,6 @@ export default {
APP.UI.addListener(UIEvents.AUDIO_MUTED, muteLocalAudio);
APP.UI.addListener(UIEvents.VIDEO_MUTED, muteLocalVideo);
if (!interfaceConfig.filmStripOnly) {
APP.UI.addListener(UIEvents.MESSAGE_CREATED, (message) => {
APP.API.notifySendingChatMessage(message);
room.sendTextMessage(message);
});
}
room.on(ConnectionQualityEvents.LOCAL_STATS_UPDATED,
(stats) => {
APP.UI.updateLocalStats(stats.connectionQuality, stats);
@@ -1354,19 +1497,24 @@ export default {
APP.UI.initEtherpad(value);
});
APP.UI.addListener(UIEvents.EMAIL_CHANGED, changeLocalEmail);
APP.UI.addListener(UIEvents.EMAIL_CHANGED, this.changeLocalEmail);
room.addCommandListener(this.commands.defaults.EMAIL, (data, from) => {
APP.store.dispatch(changeParticipantEmail(from, data.value));
APP.UI.setUserEmail(from, data.value);
});
room.addCommandListener(
this.commands.defaults.AVATAR_URL,
(data, from) => {
APP.store.dispatch(
changeParticipantAvatarURL(from, data.value));
APP.UI.setUserAvatarUrl(from, data.value);
});
room.addCommandListener(this.commands.defaults.AVATAR_ID,
(data, from) => {
APP.store.dispatch(
changeParticipantAvatarID(from, data.value));
APP.UI.setUserAvatarID(from, data.value);
});
@@ -1406,7 +1554,7 @@ export default {
APP.UI.addListener(UIEvents.LOGOUT, () => {
AuthHandler.logout(room).then(url => {
if (url) {
window.location.href = url;
UIUtil.redirect(url);
} else {
this.hangup(true);
}
@@ -1461,50 +1609,6 @@ export default {
AuthHandler.authenticate(room);
});
APP.UI.addListener(UIEvents.SELECTED_ENDPOINT, (id) => {
try {
// do not try to select participant if there is none (we are
// alone in the room), otherwise an error will be thrown cause
// reporting mechanism is not available (datachannels currently)
if (room.getParticipants().length === 0)
return;
room.selectParticipant(id);
} catch (e) {
JitsiMeetJS.analytics.sendEvent('selectParticipant.failed');
reportError(e);
}
});
APP.UI.addListener(UIEvents.PINNED_ENDPOINT, (smallVideo, isPinned) => {
let smallVideoId = smallVideo.getId();
let isLocal = APP.conference.isLocalId(smallVideoId);
let eventName
= (isPinned ? "pinned" : "unpinned") + "." +
(isLocal ? "local" : "remote");
let participantCount = room.getParticipantCount();
JitsiMeetJS.analytics.sendEvent(
eventName,
{ value: participantCount });
// FIXME why VIDEO_CONTAINER_TYPE instead of checking if
// the participant is on the large video ?
if (smallVideo.getVideoType() === VIDEO_CONTAINER_TYPE
&& !isLocal) {
// When the library starts supporting multiple pins we would
// pass the isPinned parameter together with the identifier,
// but currently we send null to indicate that we unpin the
// last pinned.
try {
room.pinParticipant(isPinned ? smallVideoId : null);
} catch (e) {
reportError(e);
}
}
});
APP.UI.addListener(
UIEvents.VIDEO_DEVICE_CHANGED,
(cameraDeviceId) => {
@@ -1616,12 +1720,23 @@ export default {
},
/**
* Adds any room listener.
* @param eventName one of the ConferenceEvents
* @param callBack the function to be called when the event occurs
* @param {string} eventName one of the ConferenceEvents
* @param {Function} listener the function to be called when the event
* occurs
*/
addConferenceListener(eventName, callBack) {
room.on(eventName, callBack);
addConferenceListener(eventName, listener) {
room.on(eventName, listener);
},
/**
* Removes any room listener.
* @param {string} eventName one of the ConferenceEvents
* @param {Function} listener the listener to be removed.
*/
removeConferenceListener(eventName, listener) {
room.off(eventName, listener);
},
/**
* Inits list of current devices and event listener for device change.
* @private
@@ -1779,6 +1894,7 @@ export default {
* requested
*/
hangup (requestFeedback = false) {
eventEmitter.emit(JitsiMeetConferenceEvents.BEFORE_HANGUP);
APP.UI.hideRingOverLay();
let requestFeedbackPromise = requestFeedback
? APP.UI.requestFeedbackOnHangup()
@@ -1797,5 +1913,83 @@ export default {
APP.API.notifyReadyToClose();
maybeRedirectToWelcomePage(values[0]);
});
},
/**
* Changes the email for the local user
* @param email {string} the new email
*/
changeLocalEmail(email = '') {
email = email.trim();
if (email === APP.settings.getEmail()) {
return;
}
APP.store.dispatch(changeParticipantEmail(room.myUserId(), email));
APP.settings.setEmail(email);
APP.UI.setUserEmail(room.myUserId(), email);
sendData(commands.EMAIL, email);
},
/**
* Changes the avatar url for the local user
* @param url {string} the new url
*/
changeLocalAvatarUrl(url = '') {
url = url.trim();
if (url === APP.settings.getAvatarUrl()) {
return;
}
APP.store.dispatch(changeParticipantAvatarURL(room.myUserId(), url));
APP.settings.setAvatarUrl(url);
APP.UI.setUserAvatarUrl(room.myUserId(), url);
sendData(commands.AVATAR_URL, url);
},
/**
* Sends a message via the data channel.
* @param {string} to the id of the endpoint that should receive the
* message. If "" - the message will be sent to all participants.
* @param {object} payload the payload of the message.
* @throws NetworkError or InvalidStateError or Error if the operation
* fails.
*/
sendEndpointMessage (to, payload) {
room.sendEndpointMessage(to, payload);
},
/**
* Adds new listener.
* @param {String} eventName the name of the event
* @param {Function} listener the listener.
*/
addListener (eventName, listener) {
eventEmitter.addListener(eventName, listener);
},
/**
* Removes listener.
* @param {String} eventName the name of the event that triggers the
* listener
* @param {Function} listener the listener.
*/
removeListener (eventName, listener) {
eventEmitter.removeListener(eventName, listener);
},
/**
* Checks if the participant given by participantId is currently in the
* last N set if there's one supported.
*
* @param participantId the identifier of the participant
* @returns {boolean} {true} if the participant given by the participantId
* is currently in the last N set or if there's no last N set at this point
* and {false} otherwise
*/
isInLastN (participantId) {
return room.isInLastN(participantId);
}
};

View File

@@ -20,10 +20,17 @@ var config = { // eslint-disable-line no-unused-vars
//focusUserJid: 'focus@auth.jitsi-meet.example.com', // The real JID of focus participant - can be overridden here
//defaultSipNumber: '', // Default SIP number
// Desktop sharing method. Can be set to 'ext', 'webrtc' or false to disable.
desktopSharingChromeMethod: 'ext',
// The STUN servers that will be used in the peer to peer connections
p2pStunServers: [
{ urls: "stun:stun.l.google.com:19302" },
{ urls: "stun:stun1.l.google.com:19302" },
{ urls: "stun:stun2.l.google.com:19302" }
],
// The ID of the jidesha extension for Chrome.
desktopSharingChromeExtId: 'diibjkoicjeejcmhdnailmkgecihlobk',
desktopSharingChromeExtId: null,
// Whether desktop sharing should be disabled on Chrome.
desktopSharingChromeDisabled: true,
// The media sources to use when using screen sharing with the Chrome
// extension.
desktopSharingChromeSources: ['screen', 'window', 'tab'],
@@ -40,7 +47,7 @@ var config = { // eslint-disable-line no-unused-vars
// up to and including 41. On Firefox 42 and higher, we will run without the
// extension.
// If set to -1, an extension will be required for all versions of Firefox.
desktopSharingFirefoxMaxVersionExtRequired: -1,
desktopSharingFirefoxMaxVersionExtRequired: 51,
// The URL to the Firefox extension for desktop sharing.
desktopSharingFirefoxExtensionURL: null,
@@ -53,8 +60,6 @@ var config = { // eslint-disable-line no-unused-vars
disableStats: false,
disableAudioLevels: false,
channelLastN: -1, // The default value of the channel attribute last-n.
adaptiveLastN: false,
//disableAdaptiveSimulcast: false,
enableRecording: false,
enableWelcomePage: true,
//enableClosePage: false, // enabling the close page will ignore the welcome
@@ -78,5 +83,18 @@ var config = { // eslint-disable-line no-unused-vars
// edit their profile.
enableUserRolesBasedOnToken: false,
// Suspending video might cause problems with audio playback. Disabling until these are fixed.
disableSuspendVideo: true
disableSuspendVideo: true,
// disables or enables RTX (RFC 4588) (defaults to false).
disableRtx: false,
// Sets the preferred resolution (height) for local video. Defaults to 360.
resolution: 720,
// Enables peer to peer mode. When enabled system will try to establish
// direct connection given that there are exactly 2 participants in
// the room. If that succeeds the conference will stop sending data through
// the JVB and use the peer to peer connection instead. When 3rd participant
// joins the conference will be moved back to the JVB connection.
//enableP2P: true
// How long we're going to wait, before going back to P2P after
// the 3rd participant has left the conference (to filter out page reload)
//backToP2PDelay: 5
};

View File

@@ -4,6 +4,14 @@ const logger = require("jitsi-meet-logger").getLogger(__filename);
import AuthHandler from './modules/UI/authentication/AuthHandler';
import jitsiLocalStorage from './modules/util/JitsiLocalStorage';
import {
connectionEstablished,
connectionFailed
} from './react/features/base/connection';
import {
isFatalJitsiConnectionError
} from './react/features/base/lib-jitsi-meet';
const ConnectionEvents = JitsiMeetJS.events.connection;
const ConnectionErrors = JitsiMeetJS.errors.connection;
@@ -67,6 +75,18 @@ function connect(id, password, roomName) {
connection.addEventListener(
ConnectionEvents.CONNECTION_FAILED, handleConnectionFailed
);
connection.addEventListener(
ConnectionEvents.CONNECTION_FAILED, connectionFailedHandler);
function connectionFailedHandler(error, errMsg) {
APP.store.dispatch(connectionFailed(connection, error, errMsg));
if (isFatalJitsiConnectionError(error)) {
connection.removeEventListener(
ConnectionEvents.CONNECTION_FAILED,
connectionFailedHandler);
}
}
function unsubscribe() {
connection.removeEventListener(
@@ -80,6 +100,7 @@ function connect(id, password, roomName) {
}
function handleConnectionEstablished() {
APP.store.dispatch(connectionEstablished(connection));
unsubscribe();
resolve(connection);
}

View File

@@ -3,21 +3,25 @@
user-select: none;
}
html, body{
margin:0px;
height:100%;
color: $defaultColor;
body {
margin: 0px;
width: 100%;
height: 100%;
font-size: 12px;
font-weight: 400;
background: #000000;
overflow: hidden;
color: $defaultColor;
background: $defaultBackground;
&.filmstrip-only {
background: transparent;
}
}
p {
margin: 0;
}
html, body, input, textarea, keygen, select, button {
body, input, textarea, keygen, select, button {
font-family: $baseFontFamily !important;
}
@@ -80,7 +84,7 @@ form {
height: 74px;
background-size: contain;
background-repeat: no-repeat;
z-index: 2;
z-index: $zindex2;
}
.leftwatermark {
@@ -102,7 +106,7 @@ form {
font-size: 11pt;
color: rgba(255,255,255,.50);
text-decoration: none;
z-index: 100;
z-index: $poweredByZ;
}
.connected {
@@ -122,6 +126,7 @@ form {
z-index: $tooltipsZ;
&-inner {
background-color: $tooltipBg;
max-width: 350px;
}
&-arrow {

View File

@@ -212,24 +212,24 @@
line-height: 30px;
}
::-webkit-scrollbar {
:not(.default-scrollbar)::-webkit-scrollbar {
background: #06a5df;
width: 7px;
}
::-webkit-scrollbar-button {
:not(.default-scrollbar)::-webkit-scrollbar-button {
display: none;
}
::-webkit-scrollbar-track {
:not(.default-scrollbar)::-webkit-scrollbar-track {
background: black;
}
::-webkit-scrollbar-track-piece {
:not(.default-scrollbar)::-webkit-scrollbar-track-piece {
background: black;
}
::-webkit-scrollbar-thumb {
:not(.default-scrollbar)::-webkit-scrollbar-thumb {
background: #06a5df;
border-radius: 4px;
}

View File

@@ -17,7 +17,7 @@
flex-direction: column-reverse;
flex-wrap: nowrap;
position: relative;
z-index: 1; // Set z-index to make element visible
z-index: $zindex1; // Set z-index to make element visible
width: $hideFilmstripButtonWidth;
button {
@@ -50,14 +50,17 @@
position:relative;
height:196px;
padding: 0;
padding-left: 17px;
/*The filmstrip should not be covered by the left toolbar*/
padding-left: $defaultToolbarSize + 5;
bottom: 0;
width:auto;
border: $thumbnailsBorder solid transparent;
z-index: 5;
z-index: $filmstripVideosZ;
transition: bottom 2s;
overflow: visible !important;
font-size: 0pt; /*!!!Removes the gap between the local video container and the remote videos.*/
/*!!!Removes the gap between the local video container and the remote
videos.*/
font-size: 0pt;
&.hidden {
bottom: -196px;
@@ -68,7 +71,7 @@
position: relative;
background-size: contain;
border: $thumbnailVideoBorder solid transparent;
border-radius:1px;
border-radius: $borderRadius;
margin: 0 $thumbnailVideoMargin;
&.videoContainerFocused, &:hover {
@@ -89,7 +92,7 @@
0 0 3px $videoThumbnailSelected !important;
}
.remotevideomenu {
.remotevideomenu > .icon-menu {
display: none;
}
@@ -102,7 +105,7 @@
box-shadow: inset 0 0 3px $videoThumbnailHovered,
0 0 3px $videoThumbnailHovered;
.remotevideomenu {
.remotevideomenu > .icon-menu {
display: inline-block;
}
}
@@ -112,10 +115,10 @@
& > video,
& > object {
cursor: hand;
border-radius:1px;
border-radius: $borderRadius;
object-fit: cover;
overflow: hidden;
}
}
}
}
}

View File

@@ -25,6 +25,9 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-mic-camera-combined:before {
content: "\e903";
}
.icon-feedback:before {
content: "\e91d";
}

View File

@@ -1,6 +1,6 @@
.inlay {
margin-top: 14%;
@include border-radius(3px);
@include border-radius(4px);
padding: 40px 38px 44px;
color: #fff;
background: $inlayColorBg;
@@ -27,7 +27,86 @@
font-size: 50px;
}
&__button {
float: none !important;
&-filmstrip-only {
background-color: $inlayFilmstripOnlyBg;
color: $inlayFilmstripOnlyColor;
margin-left: 20px;
margin-right: 20px;
margin-top: 20px;
bottom: 30px;
position: absolute;
display: flex;
max-height: 120px;
height: 80%;
right: 0px;
border-radius: 4px;
overflow: hidden;
&__content {
padding: 20px;
display: flex;
justify-content: center;
position: relative;
> .button-control {
align-self: center;
}
> #reloadProgressBar {
position: absolute;
left: 0px;
bottom: 0px;
margin-bottom: 0px;
width: 100%;
border-radius: 0px;
> .aui-progress-indicator-value {
border-radius: 0px;
}
}
}
&__title {
font-size: 18px;
font-weight: 600;
}
&__container {
align-self: center;
}
&__text {
margin-top: 10px;
font-size: 14px;
font-weight: 600;
}
&__icon {
font-size: 50px;
align-self: center;
color: $inlayIconColor;
opacity: 0.6;
}
&__icon-container {
text-align: center;
display: flex;
justify-content: center;
position: absolute;
width: 100%;
height: 100%;
top: 0px;
}
&__avatar-container {
position: relative;
> img {
height: 100%;
}
}
&__icon-background {
background: $inlayIconBg;
opacity: 0.6;
position: absolute;
width: 100%;
height: 100%;
top: 0px;
}
}
}
}

View File

@@ -2,7 +2,7 @@
position: absolute;
top: 0;
left: 0;
z-index: 1010;
z-index: $jitsipopoverZ;
display: none;
max-width: 300px;
min-width: 100px;
@@ -10,7 +10,7 @@
color: $popoverFontColor;
background-color: $popoverBg;
background-clip: padding-box;
border-radius: 3px;
border-radius: $borderRadius;
/*-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);*/
/*box-shadow: 0 5px 10px rgba(0, 0, 0, 0.4);*/
white-space: normal;

View File

@@ -1,18 +1,18 @@
@charset "UTF-8";
/*!
* jQuery contextMenu - Plugin for simple contextMenu handling
*
* Version: v2.1.1
*
* Authors: Björn Brala (SWIS.nl), Rodney Rehm, Addy Osmani (patches for FF)
* Web: http://swisnl.github.io/jQuery-contextMenu/
*
* Copyright (c) 2011-2016 SWIS BV and contributors
*
* Licensed under
* MIT License http://www.opensource.org/licenses/mit-license
*
* Date: 2016-02-28T09:53:18.890Z
/*!
* jQuery contextMenu - Plugin for simple contextMenu handling
*
* Version: v2.1.1
*
* Authors: Björn Brala (SWIS.nl), Rodney Rehm, Addy Osmani (patches for FF)
* Web: http://swisnl.github.io/jQuery-contextMenu/
*
* Copyright (c) 2011-2016 SWIS BV and contributors
*
* Licensed under
* MIT License http://www.opensource.org/licenses/mit-license
*
* Date: 2016-02-28T09:53:18.890Z
*/
@font-face {
font-family: "context-menu-icons";
@@ -88,7 +88,7 @@
list-style-type: none;
background: #fff;
border: 1px solid #bebebe;
border-radius: 3px;
border-radius: $borderRadius;
-webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, .5);
box-shadow: 0 2px 5px rgba(0, 0, 0, .5);
}
@@ -143,7 +143,7 @@
position: absolute;
top: 50%;
right: 8px;
z-index: 1;
z-index: $zindex1;
width: 0;
height: 0;
content: '';
@@ -156,8 +156,8 @@
transform: translateY(-50%);
}
/**
* Inputs
/**
* Inputs
*/
.context-menu-item.context-menu-input {
padding: 5px 10px;

View File

@@ -6,7 +6,7 @@
overflow: hidden;
padding: 20px;
margin-left: 10px;
z-index: 10;
z-index: $zindex10;
border-radius: $borderRadius;
background-attachment: scroll;
background-size: auto auto;

View File

@@ -1,34 +1,10 @@
/*Initialize*/
ul.loginmenu {
font-family: $baseFontFamily;
line-height: normal;
display:none;
div.loginmenu {
position: absolute;
margin: 0;
padding: 5px;
padding-bottom: 7px;
top: 45px;
left: -5px;
background-color: rgba(0,0,0,0.9);
border: 1px solid rgba(256, 256, 256, 0.2);
border-radius:8px;
}
ul.loginmenu li {
list-style-type: none;
padding: 7px;
color: #fff;
font-size: 11pt;
cursor: default;
white-space: pre;
}
ul.loginmenu:after {
content: url('../images/dropdownPointer.png');
display: block;
position: absolute;
top: -7px;
left: 18px;
top: 40px;
left: 20px;
}
a.disabled {
@@ -36,23 +12,7 @@ a.disabled {
pointer-events: none;
}
.loginmenuPadding {
width: 50px;
height: 30px;
position: absolute;
top: -30px;
left: 0px;
}
.loginmenu.extendedToolbarPopup {
left: 55px;
top: 0px;
}
ul.loginmenu.extendedToolbarPopup:after {
content: url('../images/leftDropdownPointer.png');
display: block;
position: absolute;
top: 18px;
left: -7px;
top: 20px;
left: 40px;
}

View File

@@ -2,52 +2,52 @@
* Animation mixin.
*/
@mixin animation($animate...) {
$max: length($animate);
$animations: '';
$max: length($animate);
$animations: '';
@for $i from 1 through $max {
$animations: #{$animations + nth($animate, $i)};
@for $i from 1 through $max {
$animations: #{$animations + nth($animate, $i)};
@if $i < $max {
$animations: #{$animations + ", "};
@if $i < $max {
$animations: #{$animations + ", "};
}
}
}
-webkit-animation: $animations;
-moz-animation: $animations;
-o-animation: $animations;
animation: $animations;
-webkit-animation: $animations;
-moz-animation: $animations;
-o-animation: $animations;
animation: $animations;
}
@mixin flex() {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
/**
* Keyframes mixin.
*/
@mixin keyframes($animationName) {
@-webkit-keyframes #{$animationName} {
@content;
}
@-moz-keyframes #{$animationName} {
@content;
}
@-o-keyframes #{$animationName} {
@content;
}
@keyframes #{$animationName} {
@content;
}
@-webkit-keyframes #{$animationName} {
@content;
}
@-moz-keyframes #{$animationName} {
@content;
}
@-o-keyframes #{$animationName} {
@content;
}
@keyframes #{$animationName} {
@content;
}
}
@mixin circle($diameter) {
width: $diameter;
height: $diameter;
border-radius: 50%;
width: $diameter;
height: $diameter;
border-radius: 50%;
}
/**
@@ -60,10 +60,10 @@
}
@mixin absoluteAligning() {
top: 50%;
left: 50%;
position: absolute;
@include transform(translate(-50%, -50%));
top: 50%;
left: 50%;
position: absolute;
@include transform(translate(-50%, -50%));
}
/**
@@ -75,81 +75,115 @@
}
@mixin transform($func) {
-moz-transform: $func;
-ms-transform: $func;
-webkit-transform: $func;
-o-transform: $func;
transform: $func;
-moz-transform: $func;
-ms-transform: $func;
-webkit-transform: $func;
-o-transform: $func;
transform: $func;
}
@mixin transition($transition...) {
-moz-transition: $transition;
-o-transition: $transition;
-webkit-transition: $transition;
transition: $transition;
-moz-transition: $transition;
-o-transition: $transition;
-webkit-transition: $transition;
transition: $transition;
}
/**
* Mixin styling placeholder
**/
* Mixin styling a placeholder.
**/
@mixin placeholder() {
$selectors: (
"::-webkit-input-placeholder",
"::-moz-placeholder",
":-moz-placeholder",
":-ms-input-placeholder"
);
$selectors: (
"::-webkit-input-placeholder",
"::-moz-placeholder",
":-moz-placeholder",
":-ms-input-placeholder"
);
@each $selector in $selectors {
#{$selector} {
@content;
@each $selector in $selectors {
#{$selector} {
@content;
}
}
}
/**
* Mixin styling a slider track for different browsers.
**/
@mixin slider() {
$selectors: (
"input[type=range]::-webkit-slider-runnable-track",
"input[type=range]::-moz-range-track",
"input[type=range]::-ms-track"
);
@each $selector in $selectors {
#{$selector} {
@content;
}
}
}
/**
* Mixin styling a slider thumb for different browsers.
**/
@mixin slider-thumb() {
$selectors: (
"input[type=range]::-webkit-slider-thumb",
"input[type=range]::-moz-range-thumb",
"input[type=range]::-ms-thumb"
);
@each $selector in $selectors {
#{$selector} {
@content;
}
}
}
@mixin box-shadow($h, $y, $blur, $color, $inset: false) {
@if $inset {
-webkit-box-shadow: inset $h $y $blur $color;
-moz-box-shadow: inset $h $y $blur $color;
box-shadow: inset $h $y $blur $color;
} @else {
-webkit-box-shadow: $h $y $blur $color;
-moz-box-shadow: $h $y $blur $color;
box-shadow: $h $y $blur $color;
}
@if $inset {
-webkit-box-shadow: inset $h $y $blur $color;
-moz-box-shadow: inset $h $y $blur $color;
box-shadow: inset $h $y $blur $color;
} @else {
-webkit-box-shadow: $h $y $blur $color;
-moz-box-shadow: $h $y $blur $color;
box-shadow: $h $y $blur $color;
}
}
@mixin no-box-shadow {
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
@mixin box-sizing($box-model) {
-webkit-box-sizing: $box-model; // Safari <= 5
-moz-box-sizing: $box-model; // Firefox <= 19
box-sizing: $box-model;
-webkit-box-sizing: $box-model; // Safari <= 5
-moz-box-sizing: $box-model; // Firefox <= 19
box-sizing: $box-model;
}
@mixin border-radius($radius) {
-webkit-border-radius: $radius;
border-radius: $radius;
/* stops bg color from leaking outside the border: */
background-clip: padding-box;
-webkit-border-radius: $radius;
border-radius: $radius;
/* stops bg color from leaking outside the border: */
background-clip: padding-box;
}
@mixin opacity($opacity) {
opacity: $opacity;
$opacity-ie: $opacity * 100;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=$opacity-ie);
filter: alpha(opacity=$opacity-ie); //IE8
opacity: $opacity;
$opacity-ie: $opacity * 100;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=$opacity-ie);
filter: alpha(opacity=$opacity-ie); //IE8
}
@mixin text-truncate {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/**
@@ -157,5 +191,5 @@
* (opacity) value.
*/
@mixin transparentBg($color, $alpha) {
background-color: rgba(red($color), green($color), blue($color), $alpha);
background-color: rgba(red($color), green($color), blue($color), $alpha);
}

View File

@@ -1,11 +1,12 @@
#notice {
.notice {
position: relative;
z-index: 3;
z-index: $zindex3;
margin-top: 6px;
&__message {
background-color: #000000;
color: white;
padding: 3px;
border-radius: 5px;
}
}
#noticeText {
background-color: #000000;
color: white;
padding: 3px;
border-radius: 5px;
}

View File

@@ -2,7 +2,7 @@
position: absolute;
top: 0;
left: 0;
z-index: 1015;
z-index: $popoverZ;
display: none;
max-width: 300px;
min-width: 100px;

View File

@@ -6,7 +6,6 @@
padding: 0;
margin: 2px 0;
bottom: 0;
width: 100px;
height: auto;
&:first-child {
@@ -24,7 +23,8 @@
}
// Link Appearance
&__link {
&__link,
&__contents {
display: block;
box-sizing: border-box;
text-decoration: none;
@@ -41,11 +41,16 @@
}
}
&__text {
&__text,
&__slider {
display: inline-block;
vertical-align: middle;
}
&__slider {
width: 50px;
}
&__icon {
vertical-align: middle;
position: relative;
@@ -66,4 +71,9 @@
span.remotevideomenu:hover ul.popupmenu, ul.popupmenu:hover {
display:block !important;
}
}
.remote-control-spinner {
top: 6px;
left: 2px;
}

View File

@@ -1,10 +1,3 @@
html, body {
width: 100%;
height:100%;
color: $defaultColor;
background: $defaultBackground;
}
.redirectPageMessage {
width: 30%;
margin: 20% auto;

View File

@@ -10,7 +10,7 @@
position: absolute;
top: 0;
width: 0;
z-index: 800;
z-index: $sideToolbarContainerZ;
/**
* Labels inside the side panel.

View File

@@ -33,7 +33,7 @@
#subject {
position: relative;
z-index: 3;
z-index: $zindex3;
width: auto;
padding: 5px;
margin-left: 40%;
@@ -106,7 +106,7 @@
height: 50px;
cursor: pointer;
text-align: center;
z-index: 1;
z-index: $zindex1;
font-size: $toolbarFontSize !important;
line-height: 50px !important;
vertical-align: middle;

View File

@@ -14,8 +14,8 @@ $defaultToolbarSize: 50px;
// Video layout.
$thumbnailToolbarHeight: 22px;
$thumbnailIndicatorBorder: 0;
$thumbnailIndicatorSize: 3em;
$thumbnailIndicatorBorder: 2px;
$thumbnailIndicatorSize: $thumbnailToolbarHeight;
$thumbnailVideoMargin: 2px;
$thumbnailsBorder: 2px;
$thumbnailVideoBorder: 2px;
@@ -43,14 +43,14 @@ $toolbarBadgeColor: #FFFFFF;
$toolbarToggleBackground: #12499C;
$splitterToolbarButtonMargin: 18px;
/*
/**
* Main controls
* TODO: looks like we don't use it
*/
$inputSemiBackground: rgba(132, 132, 132, .8);
$inputLightBackground: #EBEBEB;
/*
/**
* Video layout
*/
$videoThumbnailHovered: rgba(22, 94, 204, .4);
@@ -95,7 +95,7 @@ $notificationWidth: 215px;
/**
* Misc.
*/
$borderRadius: 3px;
$borderRadius: 4px;
$defaultWatermarkLink: '../images/watermark.png';
$sidebarWidth: 220px;
$popoverMenuPadding: 13px;
@@ -104,13 +104,26 @@ $happySoftwareBackground: transparent;
/**
* Z-indexes. TODO: Replace this by a function.
*/
$tooltipsZ: 901;
$toolbarZ: 900;
$overlayZ: 902;
$notificationZ: 1012;
$ringingZ: 800;
$dropdownZ: 901;
$zindex0: 0;
$zindex1: 1;
$zindex2: 2;
$zindex3: 3;
$filmstripVideosZ: 5;
$zindex10: 10;
$reloadZ: 20;
$poweredByZ: 100;
$ringingZ: 300;
$sideToolbarContainerZ: 300;
$toolbarZ: 400;
$tooltipsZ: 401;
$dropdownMaskZ: 900;
$dropdownZ: 901;
$overlayZ: 902;
$jitsipopoverZ: 1010;
$centeredVideoLabelZ: 1011;
$notificationZ: 1012;
$popoverZ: 1015;
/**
* Font Colors
@@ -126,4 +139,16 @@ $defaultDarkFontColor: #000;
$inputControlEmColor: #f29424;
//buttons
$linkFontColor: #489afe;
$linkHoverFontColor: #287ade;
$linkHoverFontColor: #287ade;
/**
* Unsupported browser
*/
$primaryUnsupportedBrowserButtonBgColor: #17a0db;
$unsupportedBrowserButtonBgColor: #ff9a00;
$unsupportedBrowserTextColor: #4a4a4a;
$unsupportedBrowserTextSmallFontSize: 17px;
$unsupportedBrowserTitleColor: #fff;
$unsupportedBrowserTitleFontSize: 24px;
$unsupportedDesktopBrowserTextColor: rgba(255, 255, 255, 0.7);
$unsupportedDesktopBrowserTextFontSize: 21px;

View File

@@ -18,9 +18,10 @@
&__background {
@include topLeft();
background-color: black;
border-radius: $borderRadius;
width: 100%;
height: 100%;
background-color: black;
}
/**
@@ -30,7 +31,7 @@
&__toptoolbar {
position: absolute;
left: 0;
z-index: 3;
z-index: $zindex3;
width: 100%;
box-sizing: border-box; // Includes the padding in the 100% width.
}
@@ -58,7 +59,7 @@
float: left;
@include circle($thumbnailIndicatorSize);
box-sizing: border-box;
z-index: 3;
z-index: $zindex3;
background: $dominantSpeakerBg;
color: $thumbnailPictogramColor;
border: $thumbnailIndicatorBorder solid $thumbnailPictogramColor;
@@ -106,12 +107,13 @@
}
&__hoverOverlay {
background: rgba(0,0,0,.6);
border-radius: $borderRadius;
position: relative;
width: 100%;
height: 100%;
visibility: hidden;
background: rgba(0,0,0,.6);
z-index: 2;
z-index: $zindex2;
}
}
@@ -128,8 +130,8 @@
#localVideoWrapper>video,
#localVideoWrapper>object {
border-radius: $borderRadius !important;
cursor: hand;
border-radius:1px !important;
object-fit: cover;
}
@@ -159,7 +161,7 @@
position: absolute;
left: 0;
top: 0;
z-index: 1;
z-index: $zindex1;
width: 100%;
height: 100%;
}
@@ -169,7 +171,7 @@
}
#etherpad {
z-index: 0;
z-index: $zindex0;
}
/**
@@ -191,7 +193,7 @@
overflow: hidden;
white-space: nowrap;
line-height: $thumbnailToolbarHeight;
z-index: 2;
z-index: $zindex2;
}
/**
@@ -211,6 +213,7 @@
.videocontainer .displayname {
pointer-events: none;
padding: 0 3px 0 3px;
}
.videocontainer .editdisplayname {
@@ -230,7 +233,7 @@
padding: 3px 5px;
font-size: 9pt;
cursor: pointer;
z-index: 2;
z-index: $zindex2;
}
/**
@@ -280,7 +283,7 @@
top: 0px;
right: 0;
margin: 7px;
z-index: 3;
z-index: $zindex3;
width: 18px;
height: 13px;
color: #FFF;
@@ -298,7 +301,7 @@
margin-top: -17px;
width: 6px;
height: 35px;
z-index: 2;
z-index: $zindex2;
border: none;
.audiodot-top,
@@ -341,13 +344,13 @@
background-clip: padding-box;
-webkit-border-radius: 5px;
-webkit-background-clip: padding-box;
z-index: 20; /*The reload button should appear on top of the header!*/
z-index: $reloadZ; /*The reload button should appear on top of the header!*/
}
.audiolevel {
display: inline-block;
position: absolute;
z-index: 0;
z-index: $zindex0;
border-radius:1px;
pointer-events: none;
}
@@ -405,7 +408,7 @@
.noMic {
position: absolute;
border-radius: 8px;
z-index: 1;
z-index: $zindex1;
width: 100%;
height: 100%;
background-image: url("../images/noMic.png");
@@ -417,7 +420,7 @@
.noVideo {
position: absolute;
border-radius: 8px;
z-index: 1;
z-index: $zindex1;
width: 100%;
height: 100%;
background-image: url("../images/noVideo.png");
@@ -450,7 +453,7 @@
display: none;
position: absolute;
width: auto;
z-index: 2;
z-index: $zindex2;
font-weight: 600;
font-size: 14px;
text-align: center;
@@ -471,9 +474,10 @@
#localConnectionMessage {
display: none;
position: absolute;
left: 0;
width: 100%;
top:50%;
z-index: 2;
z-index: $zindex2;
font-weight: 600;
font-size: 14px;
text-align: center;
@@ -502,7 +506,7 @@
#videoResolutionLabel,
.centeredVideoLabel {
display: none;
z-index: 1011;
z-index: $centeredVideoLabelZ;
}
.centeredVideoLabel {

View File

@@ -22,7 +22,7 @@
font-weight: 500;
font-size: 16px;
color: #acacac;
z-index: 2;
z-index: $zindex2;
}
#disable_welcome:checked + label
@@ -35,7 +35,7 @@
font-weight: 500;
font-size: 16px;
color: #acacac;
z-index: 2;
z-index: $zindex2;
}
#enter_room_form {
@@ -74,7 +74,7 @@
float: left;
background-color: #FFFFFF;
position: relative;
z-index: 2;
z-index: $zindex2;
}
&__reload {
@@ -83,7 +83,7 @@
color: #acacac;
font-size: 1.9em;
line-height: 55px;
z-index: 3;
z-index: $zindex3;
float: left;
cursor: pointer;
text-align: center;
@@ -104,7 +104,7 @@
outline: none;
float:left;
position: relative;
z-index: 2;
z-index: $zindex2;
}
}

View File

@@ -57,6 +57,18 @@
}
}
&_overlay {
color: $primaryButtonColor;
background-color: $overlayButtonBg;
border-radius: 2px;
border: none;
&:hover {
background-color: $primaryButtonBackground;
border: none;
}
}
&_primary {
background-color: $primaryButtonBackground;
border: 1px solid $primaryButtonBackground;
@@ -86,4 +98,4 @@
&_center {
float: none !important;
}
}
}

View File

@@ -0,0 +1,41 @@
/**
* Disable the default webkit styles for range inputs (sliders).
*/
input[type=range]{
-webkit-appearance: none;
background: none;
}
/**
* Disable the default focus styles for webkit range inputs (sliders).
*/
input[type=range]:focus {
outline: none;
}
/**
* Include the mixin for a range input style.
*/
@include slider {
background: $sliderTrackBackground;
border: none;
border-radius: 3px;
cursor: pointer;
height: 6px;
width: 100%;
}
/**
* Include the mixin for a range input thumb style.
*/
@include slider-thumb {
-webkit-appearance: none;
background: white;
border: 1px solid $sliderThumbBackground;
border-radius: 50%;
box-shadow: 0px 0px 1px $sliderThumbBackground;
cursor: pointer;
height: 14px;
margin-top: -4px;
width: 14px;
}

View File

@@ -8,4 +8,13 @@
text-decoration: underline;
@include transition(color .1s ease-in);
}
}
/**
* Helper links are links that are meant to open a documentation page or more
* detailed info.
*/
.helper-link {
@extend .link;
font-size: 12px;
}

View File

@@ -37,8 +37,10 @@
@import 'overlay/overlay';
@import 'inlay';
@import 'reload_overlay/reload_overlay';
@import 'modals/desktop-picker/desktop-picker';
@import 'modals/dialog';
@import 'modals/feedback/feedback';
@import 'modals/speaker_stats/speaker_stats';
@import 'videolayout_default';
@import 'notice';
@import 'popup_menu';
@@ -60,12 +62,14 @@
@import 'components/link';
@import 'shortcuts/main';
@import 'components/button-control';
@import 'components/_input-control.scss';
@import 'components/input-control';
@import 'components/input-slider';
@import "modals/invite/invite";
@import "connection-info";
@import 'aui-components/dropdown';
@import '404';
@import 'policy';
@import 'filmstrip';
@import 'unsupported-browser/main';
/* Modules END */

View File

@@ -0,0 +1,59 @@
.desktop-picker-pane {
height: 320px;
overflow-x: hidden;
overflow-y: auto;
width: 100%;
&.source-type-screen {
.desktop-picker-source {
margin-left: auto;
margin-right: auto;
width: 50%;
}
.desktop-source-preview-thumbnail {
width: 100%;
}
.desktop-source-preview-label {
display: none;
}
}
&.source-type-window {
.desktop-picker-source {
display: inline-block;
width: 30%;
}
}
}
.desktop-picker-source {
color: $defaultDarkFontColor;
margin-top: 10px;
text-align: center;
&.is-selected {
.desktop-source-preview-image-container {
background: rgba(0, 0, 0, 0.1);
border-radius: $borderRadius;
}
}
}
.desktop-source-preview-label {
margin-top: 3px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.desktop-source-preview-thumbnail {
box-shadow: 5px 5px 5px grey;
height: auto;
max-width: 100%;
}
.desktop-source-preview-image-container {
padding: 10px;
}

View File

@@ -0,0 +1,56 @@
.speaker-stats {
list-style: none;
padding: 0;
color: $auiDialogColor;
width: 100%;
font-weight: 500;
.speaker-stats-item__status-dot {
position: relative;
display: block;
width: 9px;
height: 9px;
border-radius: 50%;
margin: 0 auto;
&.status-active {
background: green;
}
&.status-inactive {
background: gray;
}
}
.status-user-left {
color: $placeHolderColor;
}
.speaker-stats-item__status,
.speaker-stats-item__name,
.speaker-stats-item__time {
display: inline-block;
margin: 5px 0;
vertical-align: middle;
}
.speaker-stats-item__status {
width: 5%;
}
.speaker-stats-item__name {
width: 40%;
}
.speaker-stats-item__time {
width: 55%;
}
.speaker-stats-item:nth-child(even) {
background: whitesmoke;
}
.speaker-stats-item__name,
.speaker-stats-item__time {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}

View File

@@ -8,10 +8,16 @@
position: fixed;
z-index: $overlayZ;
background: $defaultBackground;
&.filmstrip-only {
@include transparentBg($filmStripOnlyOverlayBg, 0.8);
}
}
&__container-light {
@include transparentBg($defaultBackground, 0.7);
&.filmstrip-only {
@include transparentBg($filmStripOnlyOverlayBg, 0.2);
}
}
&__content {
@@ -21,6 +27,11 @@
width: 56%;
left: 50%;
@include transform(translateX(-50%));
&.filmstrip-only {
left: 0px;
width: 100%;
@include transform(none);
}
&_bottom {
position: absolute;
@@ -33,4 +44,4 @@
bottom: 24px;
width: 100%;
}
}
}

View File

@@ -4,7 +4,7 @@
line-height: 20px;
}
.reload_overlay_msg {
.reload_overlay_text {
display: block;
font-size: 12px;
line-height: 30px;
@@ -13,4 +13,7 @@
#reloadProgressBar {
width: 180px;
margin: 5px auto;
}
> .aui-progress-indicator-value {
background: $reloadProgressBarBg;
}
}

View File

@@ -8,6 +8,8 @@ $baseLight: #FFFFFF;
*/
$controlBackground: $baseLight;
$controlColor: #333333;
$sliderTrackBackground: #474747;
$sliderThumbBackground: #3572b0;
/**
* Buttons
@@ -33,10 +35,14 @@ $primaryButtonFontWeight: 400;
$buttonShadowColor: #192d4f;
$overlayButtonBg: #0074E0;
/**
* Color variables
**/
$defaultBackground: #474747;
$filmStripOnlyOverlayBg: #000;
$reloadProgressBarBg: #0074E0;
/**
* Connection indicator
@@ -58,6 +64,10 @@ $dialogTitleFontWeight: 400;
**/
$inlayColorBg: lighten($defaultBackground, 20%);
$inlayBorderColor: lighten($auiDialogContentBg, 10%);
$inlayIconBg: #000;
$inlayIconColor: #fff;
$inlayFilmstripOnlyColor: #474747;
$inlayFilmstripOnlyBg: #fff;
// Main controls
$inputBackground: $controlBackground;

View File

@@ -0,0 +1,3 @@
@import 'no-mobile-app';
@import 'unsupported-desktop-browser';
@import 'unsupported-mobile-browser';

View File

@@ -0,0 +1,21 @@
.no-mobile-app {
margin: 30% auto 0;
max-width: 25em;
text-align: center;
width: auto;
&__title {
border-bottom: 1px solid $auiBorderColor;
color: $unsupportedBrowserTitleColor;
font-weight: 400;
letter-spacing: 0.5px;
padding-bottom: em(17, 24);
}
&__description {
font-size: $unsupportedBrowserTextSmallFontSize;
font-weight: 300;
letter-spacing: 1px;
margin-top: 1em;
}
}

View File

@@ -0,0 +1,39 @@
.unsupported-desktop-browser {
@include absoluteAligning();
display: block;
text-align: center;
&__title {
color: $unsupportedBrowserTitleColor;
font-weight: 300;
font-size: $unsupportedBrowserTitleFontSize;
letter-spacing: 1px;
}
&__description {
color: $unsupportedDesktopBrowserTextColor;
font-size: $unsupportedDesktopBrowserTextFontSize;
font-weight: 300;
letter-spacing: 1px;
margin-top: 16px;
&_small {
@extend .unsupported-desktop-browser__description;
font-size: $unsupportedBrowserTextSmallFontSize;
}
}
&__link {
color: $linkFontColor;
@include transition(color .1s ease-out);
&:hover {
color: $linkHoverFontColor;
cursor: pointer;
text-decoration: none;
@include transition(color .1s ease-in);
}
}
}

View File

@@ -0,0 +1,69 @@
.unsupported-mobile-browser {
background-color: #fff;
height: 100vh;
padding: 35px 0;
width: 100vw;
&__body {
color: $unsupportedBrowserTextColor;
margin: auto;
max-width: 40em;
text-align: center;
width: 75%;
a:active {
text-decoration: none;
}
}
&__text {
font-size: 1.8em;
line-height: em(29px, 21px);
margin-bottom: 0.65em;
&_small {
font-size: 1.5em;
margin-bottom: 1em;
margin-top: em(21, 18);
strong {
font-size: em(21, 18);
}
}
}
&__logo {
height: 108px;
width: 77px;
}
&__button {
border: 0;
height: 42px;
margin: 0 auto;
max-width: 300px;
width: 98%;
@include border-radius(8px);
background-color: $unsupportedBrowserButtonBgColor;
font-size: 1.5em;
font-weight: 300;
letter-spacing: 0.5px;
text-shadow: 0px 1px 2px $unsupportedBrowserTextColor;
// Disable standard button effects.
box-shadow: none;
outline: none;
&:active {
background-color: $unsupportedBrowserButtonBgColor;
}
&_primary {
background-color: $primaryUnsupportedBrowserButtonBgColor;
&:active {
background-color: $primaryUnsupportedBrowserButtonBgColor;
}
}
}
}

View File

@@ -1,138 +0,0 @@
@import 'variables';
body {
width:100%;
height:100%;
background-color: white;
color: #424242;
font-family: $baseFontFamily;
font-size: 28px;
margin:0;
padding:0;
}
#wrap{
display: block;
position: absolute;
width:500px;
height: 565px;
overflow:hidden;
text-align: center;
margin: auto;
top: 0; left: 0; bottom: 0; right: 0;
}
.firefox{
font-size: 11pt;
color: #c8c8c8;
width: 468px;
text-align: center;
margin: 30px auto 0px auto;
padding-left: 15px;
}
#text{
display:inline-block;
font-size: 28px;
/* width: 568px; */
vertical-align:middle;
padding-top: 25px;
}
a {
color: #087dba;
text-decoration:none;
}
.browser {
width: 138px;
height: 163px;
margin-top: 5px;
background-color: #e8e8e8;
border: 1px solid #cfcfcf;
border-radius: 10px;
}
.browser_wrapper
{
width: 138px;
/* height: 188px; */
vertical-align: middle;
color: #929391;
font-size: 20px;
float: left;
margin-left: 15px;
margin-top: 5px;
}
.browser_text
{
height: 2em;
}
.supported_browsers
{
margin: 0px auto 0px auto;
/* width: 660px; */
}
.clear
{
clear: both;
}
.button
{
background-color: #62c82a;
border: 1px solid #3c8117;
border-radius: 10px;
color: #FFFFFF;
font-size: 12px;
text-align: center;
width: 115px;
height: 26px;
padding-top: 13px;
margin: 15px auto 0px auto;
}
.logo
{
margin: 20px auto 0px auto;
}
#chrome_logo
{
width: 78px;
height: 78px;
background-image: url('../images/chrome.png');
}
#chromium_logo
{
width: 77px;
height: 78px;
background-image: url('../images/chromium.png');
}
#firefox_logo
{
width: 86px;
height: 80px;
background-image: url('../images/firefox.png');
}
#opera_logo
{
width: 73px;
height: 78px;
background-image: url('../images/opera.png');
}
#safari_logo
{
width: 78px;
height: 79px;
background-image: url('../images/safari.png');
}
#ie_logo
{
width: 80px;
height: 78px;
background-image: url('../images/ie.png');
}

View File

@@ -1 +1 @@
prosody-plugins/ /usr/share/jitsi-meet/
resources/prosody-plugins/ /usr/share/jitsi-meet/

View File

@@ -65,7 +65,7 @@ case "$1" in
# SSL for nginx
db_get jitsi-meet/cert-choice
CERT_CHOICE="$RET"
UPLOADED_CERT_CHOICE="A certificate is available and the files are uploaded on the server"
UPLOADED_CERT_CHOICE="I want to use my own certificate"
if [ "$CERT_CHOICE" = "$UPLOADED_CERT_CHOICE" ] ; then
db_set jitsi-meet/cert-path-key "/etc/ssl/$JVB_HOSTNAME.key"
@@ -127,6 +127,7 @@ case "$1" in
echo "org.jitsi.videobridge.rest.jetty.ResourceHandler.resourceBase=/usr/share/jitsi-meet" >> $JVB_CONFIG
echo "org.jitsi.videobridge.rest.jetty.ResourceHandler.alias./config.js=/etc/jitsi/meet/$JVB_HOSTNAME-config.js" >> $JVB_CONFIG
echo "org.jitsi.videobridge.rest.jetty.ResourceHandler.alias./interface_config.js=/usr/share/jitsi-meet/interface_config.js" >> $JVB_CONFIG
echo "org.jitsi.videobridge.rest.jetty.ResourceHandler.alias./logging_config.js=/usr/share/jitsi-meet/logging_config.js" >> $JVB_CONFIG
echo "org.jitsi.videobridge.rest.jetty.RewriteHandler.regex=^/([a-zA-Z0-9]+)$" >> $JVB_CONFIG
echo "org.jitsi.videobridge.rest.jetty.RewriteHandler.replacement=/" >> $JVB_CONFIG
echo "org.jitsi.videobridge.rest.jetty.SSIResourceHandler.paths=/" >> $JVB_CONFIG
@@ -222,6 +223,13 @@ case "$1" in
invoke-rc.d apache2 reload
fi
echo "----------------"
echo ""
echo "You can now switch to a Lets Encrypt certificate. To do so, execute:"
echo "/usr/share/jitsi-meet/scripts/install-letsencrypt-cert.sh"
echo ""
echo "----------------"
# and we're done with debconf
db_stop
;;

View File

@@ -1,9 +1,10 @@
Template: jitsi-meet/cert-choice
Type: select
__Choices: Self-signed certificate will be generated, A certificate is available and the files are uploaded on the server
__Choices: Generate a new self-signed certificate (You will later get a chance to obtain a Let's encrypt certificate), I want to use my own certificate
_Description: SSL certificate for the Jitsi Meet instance
Jitsi Meet is best to be set up with an SSL certificate.
Having no certificate, a self-signed one will be generated.
By choosing self-signed you will later have a chance to install Lets Encrypt certificates.
Having a certificate signed by a recognised CA, it can be uploaded on the server
and point its location. The default filenames will be /etc/ssl/--domain.name--.key
for the key and /etc/ssl/--domain.name--.crt for the certificate.

View File

@@ -1,12 +1,14 @@
*.js /usr/share/jitsi-meet/
interface_config.js /usr/share/jitsi-meet/
logging_config.js /usr/share/jitsi-meet/
*.json /usr/share/jitsi-meet/
*.html /usr/share/jitsi-meet/
*.ico /usr/share/jitsi-meet/
libs /usr/share/jitsi-meet/
static /usr/share/jitsi-meet/
css/all.css /usr/share/jitsi-meet/css/
css/unsupported_browser.css /usr/share/jitsi-meet/css/
sounds /usr/share/jitsi-meet/
fonts /usr/share/jitsi-meet/
images /usr/share/jitsi-meet/
lang /usr/share/jitsi-meet/
connection_optimization /usr/share/jitsi-meet/
resources/*.sh /usr/share/jitsi-meet/scripts/

View File

@@ -20,13 +20,13 @@ msgstr ""
#. Type: select
#. Choices
#: ../jitsi-meet-web-config.templates:1001
msgid "Self-signed certificate will be generated"
msgid "Generate a new self-signed certificate (You will later get a chance to obtain a Let's encrypt certificate)"
msgstr ""
#. Type: select
#. Choices
#: ../jitsi-meet-web-config.templates:1001
msgid "A certificate is available and the files are uploaded on the server"
msgid "I want to use my own certificate"
msgstr ""
#. Type: select

View File

@@ -1,181 +1,213 @@
Jitsi Meet API
============
# Jitsi Meet API
You can use Jitsi Meet API to embed Jitsi Meet in to your application.
You can use the Jitsi Meet API to embed Jitsi Meet in to your application.
Installation
==========
## Installation
To embed Jitsi Meet in your application you need to add the Jitsi Meet API library:
To embed Jitsi Meet in your application you need to add Jitsi Meet API library
```javascript
<script src="https://meet.jit.si/external_api.js"></script>
```
The next step for embedding Jitsi Meet is to create the Jitsi Meet API object
## API
### `api = new JitsiMeetExternalAPI(domain, room, [width], [height], [htmlElement], [configOverwite], [interfaceConfigOverwrite], [noSsl], [jwt])`
The next step for embedding Jitsi Meet is to create the Jitsi Meet API object.
Its constructor gets a number of options:
* **domain**: domain used to build the conference URL, "meet.jit.si" for
example.
* **room**: name of the room to join.
* **width**: (optional) width for the iframe which will be created.
* **height**: (optional) height for the iframe which will be created.
* **htmlElement**: (optional) HTL DOM Element where the iframe will be added as
a child.
* **configOverwite**: (optional) JS object with overrides for options defined in
[config.js].
* **interfaceConfigOverwrite**: (optional) JS object with overrides for options
defined in [interface_config.js].
* **noSsl**: (optional, defaults to true) Boolean indicating if the server
should be contacted using HTTP or HTTPS.
* **jwt**: (optional) [JWT](https://jwt.io/) token.
Example:
```javascript
<script>
var domain = "meet.jit.si";
var room = "JitsiMeetAPIExample";
var width = 700;
var height = 700;
var api = new JitsiMeetExternalAPI(domain, room, width, height);
</script>
var domain = "meet.jit.si";
var room = "JitsiMeetAPIExample";
var width = 700;
var height = 700;
var htmlElement = document.querySelector('#meet');
var api = new JitsiMeetExternalAPI(domain, room, width, height, htmlElement);
```
You can paste that lines in your html code where you want to be placed the Jitsi Meet conference
or you can specify the parent HTML element for the Jitsi Meet conference in the JitsiMeetExternalAPI
constructor.
You can overwrite options set in [config.js] and [interface_config.js].
For example, to enable the film-strip-only interface mode, you can use:
```javascript
var api = new JitsiMeetExternalAPI(domain, room, width, height, htmlElement);
var interfaceConfigOverwrite = {filmStripOnly: true};
var api = new JitsiMeetExternalAPI(domain, room, width, height, undefined, undefined, interfaceConfigOverwrite);
```
If you don't specify room the user will enter in new conference with random room name.
You can overwrite options set in config.js and interface_config.js. For example, to enable the film-strip-only interface mode and disable simulcast, you can use:
You can also pass a jwt token to Jitsi Meet:
```javascript
var jwt = "<jwt_token>";
var noSsl = false;
var api = new JitsiMeetExternalAPI(domain, room, width, height, htmlElement, configOverwrite, interfaceConfigOverwrite, noSsl, jwt);
```
### Controlling the embedded Jitsi Meet Conference
You can control the embedded Jitsi Meet conference using the `JitsiMeetExternalAPI` object by using `executeCommand`:
```javascript
var configOverwrite = {enableSimulcast: false};
var interfaceConfigOverwrite = {filmStripOnly: true};
var api = new JitsiMeetExternalAPI(domain, room, width, height, htmlElement, configOverwrite, interfaceConfigOverwrite);
api.executeCommand(command, ...arguments)
```
Controlling embedded Jitsi Meet Conference
=========
The `command` parameter is String object with the name of the command. The following commands are currently supported:
You can control the embedded Jitsi Meet conference using the JitsiMeetExternalAPI object.
You can send command to Jitsi Meet conference using ```executeCommand```.
```
api.executeCommand(command, arguments)
```
The ```command``` parameter is String object with the name of the command.
The ```arguments``` parameter is array with the arguments required by the command.
If no arguments are required by the command this parameter can be omitted or you can pass empty array.
Currently we support the following commands:
* **displayName** - sets the display name of the local participant. This command requires one argument -
the new display name to be set
```
* **displayName** - Sets the display name of the local participant. This command requires one argument - the new display name to be set.
```javascript
api.executeCommand('displayName', 'New Nickname');
```
* **toggleAudio** - mutes / unmutes the audio for the local participant. No arguments are required.
```
api.executeCommand('toggleAudio', [])
```
* **toggleVideo** - mutes / unmutes the video for the local participant. No arguments are required.
```
api.executeCommand('toggleVideo', [])
```
* **toggleFilmStrip** - hides / shows the film strip. No arguments are required.
```
api.executeCommand('filmStrip', [])
```
* **toggleChat** - hides / shows the chat. No arguments are required.
```
api.executeCommand('toggleChat', [])
```
* **toggleContactList** - hides / shows the contact list. No arguments are required.
```
api.executeCommand('toggleContactList', [])
* **toggleAudio** - Mutes / unmutes the audio for the local participant. No arguments are required.
```javascript
api.executeCommand('toggleAudio')
```
* **toggleShareScreen** - starts / stops the screen sharing. No arguments are required.
* **toggleVideo** - Mutes / unmutes the video for the local participant. No arguments are required.
```javascript
api.executeCommand('toggleVideo')
```
api.executeCommand('toggleShareScreen', [])
* **toggleFilmStrip** - Hides / shows the film strip. No arguments are required.
```javascript
api.executeCommand('toggleFilmStrip')
```
* **toggleChat** - Hides / shows the chat. No arguments are required.
```javascript
api.executeCommand('toggleChat')
```
* **toggleContactList** - Hides / shows the contact list. No arguments are required.
```javascript
api.executeCommand('toggleContactList')
```
* **toggleShareScreen** - Starts / stops screen sharing. No arguments are required.
```javascript
api.executeCommand('toggleShareScreen')
```
* **hangup** - Hangups the call. No arguments are required.
```
api.executeCommand('hangup', [])
```javascript
api.executeCommand('hangup')
```
You can also execute multiple commands using the method ```executeCommands```.
* **email** - Changes the local email address. This command requires one argument - the new email address to be set.
```javascript
api.executeCommand('email', 'example@example.com')
```
* **avatarUrl** - Changes the local avatar URL. This command requires one argument - the new avatar URL to be set.
```javascript
api.executeCommand('avatarUrl', 'https://avatars0.githubusercontent.com/u/3671647')
```
You can also execute multiple commands using the `executeCommands` method:
```javascript
api.executeCommands(commands)
```
The ```commands``` parameter is object with keys the names of the commands and values the arguments for the
commands.
```
The `commands` parameter is an object with the names of the commands as keys and the arguments for the commands asvalues:
```javascript
api.executeCommands({displayName: ['nickname'], toggleAudio: []});
```
You can add event listeners to the embedded Jitsi Meet using ```addEventListener``` method.
```
You can add event listeners to the embedded Jitsi Meet using the `addEventListener` method.
```javascript
api.addEventListener(event, listener)
```
The ```event``` parameter is String object with the name of the event.
The ```listener``` paramenter is Function object with one argument that will be notified when the event occurs
with data related to the event.
Currently we support the following events:
The `event` parameter is a String object with the name of the event.
The `listener` parameter is a Function object with one argument that will be notified when the event occurs with data related to the event.
* **incomingMessage** - event notifications about incoming
messages. The listener will receive object with the following structure:
```
The following events are currently supported:
* **incomingMessage** - Event notifications about incoming
messages. The listener will receive an object with the following structure:
```javascript
{
"from": from,//JID of the user that sent the message
"nick": nick,//the nickname of the user that sent the message
"message": txt//the text of the message
"from": from, // JID of the user that sent the message
"nick": nick, // the nickname of the user that sent the message
"message": txt // the text of the message
}
```
* **outgoingMessage** - event notifications about outgoing
messages. The listener will receive object with the following structure:
```
* **outgoingMessage** - Event notifications about outgoing
messages. The listener will receive an object with the following structure:
```javascript
{
"message": txt//the text of the message
"message": txt // the text of the message
}
```
* **displayNameChanged** - event notifications about display name
change. The listener will receive object with the following structure:
```
changes. The listener will receive an object with the following structure:
```javascript
{
jid: jid,//the JID of the participant that changed his display name
displayname: displayName //the new display name
"jid": jid, // the JID of the participant that changed his display name
"displayname": displayName // the new display name
}
```
* **participantJoined** - event notifications about new participant.
The listener will receive object with the following structure:
```
* **participantJoined** - event notifications about new participants who join the room. The listener will receive an object with the following structure:
```javascript
{
jid: jid //the jid of the participant
"jid": jid // the JID of the participant
}
```
* **participantLeft** - event notifications about participant that left room.
The listener will receive object with the following structure:
```
* **participantLeft** - event notifications about participants that leave the room. The listener will receive an object with the following structure:
```javascript
{
jid: jid //the jid of the participant
"jid": jid // the JID of the participant
}
```
* **videoConferenceJoined** - event notifications fired when the local user has joined the video conference.
The listener will receive object with the following structure:
```
* **videoConferenceJoined** - event notifications fired when the local user has joined the video conference. The listener will receive an object with the following structure:
```javascript
{
roomName: room //the room name of the conference
"roomName": room // the room name of the conference
}
```
* **videoConferenceLeft** - event notifications fired when the local user has left the video conference.
The listener will receive object with the following structure:
```
* **videoConferenceLeft** - event notifications fired when the local user has left the video conference. The listener will receive an object with the following structure:
```javascript
{
roomName: room //the room name of the conference
"roomName": room // the room name of the conference
}
```
* **readyToClose** - event notification fired when Jitsi Meet is ready to be closed (hangup operations are completed).
You can also add multiple event listeners by using ```addEventListeners```.
You can also add multiple event listeners by using `addEventListeners`.
This method requires one argument of type Object. The object argument must
have keys with the names of the events and values the listeners of the events.
have the names of the events as keys and the listeners of the events as values.
```
```javascript
function incomingMessageListener(object)
{
...
// ...
}
function outgoingMessageListener(object)
{
...
// ...
}
api.addEventListeners({
@@ -183,20 +215,28 @@ api.addEventListeners({
outgoingMessage: outgoingMessageListener})
```
If you want to remove a listener you can use ```removeEventListener``` method with argument the name of the event.
```
If you want to remove a listener you can use `removeEventListener` method with argument the name of the event.
```javascript
api.removeEventListener("incomingMessage");
```
If you want to remove more than one event you can use ```removeEventListeners``` method with argument
array with the names of the events.
```
If you want to remove more than one event you can use `removeEventListeners` method with an Array with the names of the events as an argument.
```javascript
api.removeEventListeners(["incomingMessage", "outgoingMessageListener"]);
```
You can remove the embedded Jitsi Meet Conference with the following code:
You can get the number of participants in the conference with the following API function:
```javascript
var numberOfParticipants = api.getNumberOfParticipants();
```
You can remove the embedded Jitsi Meet Conference with the following API function:
```javascript
api.dispose()
```
It is a good practice to remove the conference before the page is unloaded.
NOTE: It's a good practice to remove the conference before the page is unloaded.
[config.js]: https://github.com/jitsi/jitsi-meet/blob/master/config.js
[interface_config.js]: https://github.com/jitsi/jitsi-meet/blob/master/interface_config.js

View File

@@ -20,7 +20,7 @@ server {
root /usr/share/jitsi-meet;
index index.html index.htm;
error_page 404 /404.html;
error_page 404 /static/404.html;
location /config.js {
alias /etc/jitsi/meet/jitsi-meet.example.com-config.js;

View File

@@ -29,6 +29,8 @@
Allow from all
</Directory>
ErrorDocument 404 /static/404.html
Alias "/config.js" "/etc/jitsi/meet/jitsi-meet.example.com-config.js"
<Location /config.js>
Require all granted

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

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

View File

@@ -1,29 +0,0 @@
# Overview
Jitsi Meet supports logging to an [InfluxDB](http://influxdb.com/) database.
# Configuration
The following needs to be done to enable this functionality.
## Install InfluxDB
The details are outside the scope of the document, see http://influxdb.com/download/ .
## Create an InfluxDB database
Use the InfluxDB admin interface (running on port 8083) and create a database. In this example we name it <code>jitsi_database</code>
## Enable logging for Jitsi Videobridge
Add the following properties to <code>/usr/share/jitsi-videobridge/.sip-communicator/sip-communicator.properties</code>.
- org.jitsi.videobridge.log.INFLUX_DB_ENABLED=true
- org.jitsi.videobridge.log.INFLUX_URL_BASE=http://influxdb.example.com:8086
- org.jitsi.videobridge.log.INFLUX_DATABASE=jitsi_database
- org.jitsi.videobridge.log.INFLUX_USER=user
- org.jitsi.videobridge.log.INFLUX_PASS=pass
## Enable logging for Jicofo
Add the same properties as above to <code>/usr/share/jicofo/.sip-communicator/sip-communicator.properties</code>.
## Enable logging for Jitsi Meet itself
Change "logStats" to "true" in <code>/etc/jitsi/meet/you-domain.config.js</code> or the <code>config.js</code> file used in your installation.
# User interface
You can explore the database using the [Jiloin](https://github.com/jitsi/jiloin) web interface.

View File

@@ -6,6 +6,34 @@ change references to that to match your host, and generate some passwords for
There are also some complete [example config files](https://github.com/jitsi/jitsi-meet/tree/master/doc/example-config-files/) available, mentioned in each section.
## Network description
This how the network look like:
```
+ +
| |
| |
v |
443 |
+-------+ |
| | |
| NginX | |
| | |
+--+-+--+ |
| | |
+------------+ | | +--------------+ |
| | | | | | |
| jitsi-meet +<---+ +--->+ prosody/xmpp | |
| |files 5280 | | |
+------------+ +--------------+ v
5222,5347^ ^5347 4443
+--------+ | | +-------------+
| | | | | |
| jicofo +----^ ^----+ videobridge |
| | | |
+--------+ +-------------+
```
## Install prosody
```sh
apt-get install prosody
@@ -76,7 +104,9 @@ Add a new file `jitsi.example.com` in `/etc/nginx/sites-available` (see also the
server_names_hash_bucket_size 64;
server {
listen 80;
listen 443;
# tls configuration that is not covered in this guide
# we recommend the use of https://certbot.eff.org/
server_name jitsi.example.com;
# set the root
root /srv/jitsi.example.com;
@@ -131,9 +161,9 @@ Or autostart it by adding the line in `/etc/rc.local`:
## Install Jitsi Conference Focus (jicofo)
Install JDK and Ant if missing:
Install JDK and Maven if missing:
```
apt-get install default-jdk ant
apt-get install default-jdk maven
```
_NOTE: When installing on older Debian releases keep in mind that you need JDK >= 1.7._
@@ -145,12 +175,14 @@ git clone https://github.com/jitsi/jicofo.git
Build distribution package. Replace {os-name} with one of: 'lin', 'lin64', 'macosx', 'win', 'win64'.
```sh
cd jicofo
ant dist.{os-name}
mvn package -DskipTests -Dassembly.skipAssembly=false
```
Run jicofo:
```sh
cd dist/{os-name}'
./jicofo.sh --host=127.0.0.1 --domain=jitsi.example.com --secret=YOURSECRET2 --user_domain=auth.jitsi.example.com --user_name=focus --user_password=YOURSECRET3
=======
unzip target/jicofo-{os-name}-1.0-SNAPSHOT.zip
cd jicofo-{os-name}-1.0-SNAPSHOT'
./jicofo.sh --host=localhost --domain=jitsi.example.com --secret=YOURSECRET2 --user_domain=auth.jitsi.example.com --user_name=focus --user_password=YOURSECRET3
```
## Deploy Jitsi Meet
@@ -159,6 +191,8 @@ Checkout and configure Jitsi Meet:
cd /srv
git clone https://github.com/jitsi/jitsi-meet.git
mv jitsi-meet/ jitsi.example.com
npm install
make
```
Edit host names in `/srv/jitsi.example.com/config.js` (see also the example config file):
@@ -167,11 +201,11 @@ var config = {
hosts: {
domain: 'jitsi.example.com',
muc: 'conference.jitsi.example.com',
bridge: 'jitsi-videobridge.jitsi.example.com'
bridge: 'jitsi-videobridge.jitsi.example.com',
focus: 'focus.jitsi.example.com'
},
useNicks: false,
bosh: '//jitsi.example.com/http-bind', // FIXME: use xep-0156 for that
desktopSharing: 'false' // Desktop sharing method. Can be set to 'ext', 'webrtc' or false to disable.
//chromeExtensionId: 'diibjkoicjeejcmhdnailmkgecihlobk', // Id of desktop streamer Chrome extension
//minChromeExtVersion: '0.1' // Required version of Chrome extension
};

96
doc/mobile.md Normal file
View File

@@ -0,0 +1,96 @@
# Jitsi Meet mobile apps
Jitsi Meet can also be built as a standalone mobile application for
iOS and Android. It uses the [React Native] framework.
First make sure the [React Native dependencies] are installed.
**NOTE**: This document assumes the app is being built on a macOS system.
**NOTE**: The app must be built for an actual device since the simulators don't
work properly with the native plugins we require.
## iOS
1. Install some extra dependencies
- Install ios-deploy globally (in case you want to use the React Native CLI
to deploy the app to the device)
```bash
npm install -g ios-deploy
```
You may need to add ```--unsafe-perm=true``` if you are running on [Mac OS 10.11 or greater](https://github.com/phonegap/ios-deploy#os-x-1011-el-capitan-or-greater).
2. Build the app
There are 2 ways to build the app: using the CLI or using Xcode.
Using the CLI:
```bash
react-native run-ios --device
```
When the app is launched from the CLI the output can be checked with the
following command:
```bash
react-native log-ios
```
Using Xcode
- Open **ios/jitsi-meet-react.xcworkspace** in Xcode. Make sure it's the
workspace file!
- Select your device from the top bar and hit the "play" button.
When the app is launched from Xcode the Debug console will show the output
logs the application creates.
3. Other remarks
It's likely you'll need to change the bundle ID for deploying to a device
because the default bundle ID points to the application signed by Atlassian.
This can be changed in the "General" tab. Under "Identity" set
"Bundle Identifier" to a different value, and adjust the "Team" in the
"Signing" section to match your own.
## Android
The [React Native dependencies] page has very detailed information on how to
setup [Android Studio] and the required components for getting the necessary
build environment. Make sure you follow it closely.
1. Building the app
The app can be built using the CLI utility as follows:
```bash
react-native run-android
```
It will be launched on the connected Android device.
## Debugging
The official documentation on [debugging] is quite extensive, it is the
preferred method for debugging.
**NOTE**: When using Chrome Developer Tools for debugging the JavaScript code
is being interpreted by Chrome's V8 engine, instead of JSCore which
React Native uses. It's important to keep this in mind due to potential
differences in supported JavaScript features.
[Android Studio]: https://developer.android.com/studio/index.html
[debugging]: https://facebook.github.io/react-native/docs/debugging.html
[React Native]: https://facebook.github.io/react-native/
[React Native dependencies]: https://facebook.github.io/react-native/docs/getting-started.html#installing-dependencies

6
flow-typed/npm/flow-bin_v0.x.x.js vendored Normal file
View File

@@ -0,0 +1,6 @@
// flow-typed signature: 6a5610678d4b01e13bbfbbc62bdaf583
// flow-typed version: 3817bc6980/flow-bin_v0.x.x/flow_>=v0.25.x
declare module "flow-bin" {
declare module.exports: string;
}

36
flow-typed/npm/react-i18next_v2.x.x.js vendored Normal file
View File

@@ -0,0 +1,36 @@
// flow-typed signature: 57cf34196930be78935a42e5c8ac3cb6
// flow-typed version: ae6284e7b7/react-i18next_v2.x.x/flow_>=v0.36.x_<=v0.39.x
declare module 'react-i18next' {
declare type TFunction = (key?: ?string, data?: ?Object) => string;
declare type Locales = string | Array<string>;
declare type StatelessComponent<P> = (props: P) => ?React$Element<any>;
declare type Comp<P> = StatelessComponent<P> | Class<React$Component<*, P, *>>;
declare type Translator<OP, P> = {
(component: StatelessComponent<P>): Class<React$Component<void, OP, void>>;
<Def, St>(component: Class<React$Component<Def, P, St>>): Class<React$Component<Def, OP, St>>;
}
declare function translate<OP, P>(locales: Locales): Translator<OP, P>;
declare type NamespacesProps = {
components: Array<Comp<*>>,
i18n: { loadNamespaces: Function },
};
declare function loadNamespaces(props: NamespacesProps): Promise<void>;
declare type ProviderProps = { i18n: Object, children: React$Element<any> };
declare var I18nextProvider: Class<React$Component<void, ProviderProps, void>>;
declare type InterpolateProps = {
children?: React$Element<any>,
className?: string,
};
declare var Interpolate: Class<React$Component<void, InterpolateProps, void>>;
}

89
flow-typed/npm/react-redux_v5.x.x.js vendored Normal file
View File

@@ -0,0 +1,89 @@
// flow-typed signature: 0ed284c5a2e97a9e3c0e87af3dedc09d
// flow-typed version: bdf1e66252/react-redux_v5.x.x/flow_>=v0.30.x
import type { Dispatch, Store } from 'redux'
declare module 'react-redux' {
/*
S = State
A = Action
OP = OwnProps
SP = StateProps
DP = DispatchProps
*/
declare type MapStateToProps<S, OP: Object, SP: Object> = (state: S, ownProps: OP) => SP | MapStateToProps<S, OP, SP>;
declare type MapDispatchToProps<A, OP: Object, DP: Object> = ((dispatch: Dispatch<A>, ownProps: OP) => DP) | DP;
declare type MergeProps<SP, DP: Object, OP: Object, P: Object> = (stateProps: SP, dispatchProps: DP, ownProps: OP) => P;
declare type StatelessComponent<P> = (props: P) => ?React$Element<any>;
declare class ConnectedComponent<OP, P, Def, St> extends React$Component<void, OP, void> {
static WrappedComponent: Class<React$Component<Def, P, St>>;
getWrappedInstance(): React$Component<Def, P, St>;
static defaultProps: void;
props: OP;
state: void;
}
declare type ConnectedComponentClass<OP, P, Def, St> = Class<ConnectedComponent<OP, P, Def, St>>;
declare type Connector<OP, P> = {
(component: StatelessComponent<P>): ConnectedComponentClass<OP, P, void, void>;
<Def, St>(component: Class<React$Component<Def, P, St>>): ConnectedComponentClass<OP, P, Def, St>;
};
declare class Provider<S, A> extends React$Component<void, { store: Store<S, A>, children?: any }, void> { }
declare type ConnectOptions = {
pure?: boolean,
withRef?: boolean
};
declare type Null = null | void;
declare function connect<A, OP>(
...rest: Array<void> // <= workaround for https://github.com/facebook/flow/issues/2360
): Connector<OP, $Supertype<{ dispatch: Dispatch<A> } & OP>>;
declare function connect<A, OP>(
mapStateToProps: Null,
mapDispatchToProps: Null,
mergeProps: Null,
options: ConnectOptions
): Connector<OP, $Supertype<{ dispatch: Dispatch<A> } & OP>>;
declare function connect<S, A, OP, SP>(
mapStateToProps: MapStateToProps<S, OP, SP>,
mapDispatchToProps: Null,
mergeProps: Null,
options?: ConnectOptions
): Connector<OP, $Supertype<SP & { dispatch: Dispatch<A> } & OP>>;
declare function connect<A, OP, DP>(
mapStateToProps: Null,
mapDispatchToProps: MapDispatchToProps<A, OP, DP>,
mergeProps: Null,
options?: ConnectOptions
): Connector<OP, $Supertype<DP & OP>>;
declare function connect<S, A, OP, SP, DP>(
mapStateToProps: MapStateToProps<S, OP, SP>,
mapDispatchToProps: MapDispatchToProps<A, OP, DP>,
mergeProps: Null,
options?: ConnectOptions
): Connector<OP, $Supertype<SP & DP & OP>>;
declare function connect<S, A, OP, SP, DP, P>(
mapStateToProps: MapStateToProps<S, OP, SP>,
mapDispatchToProps: MapDispatchToProps<A, OP, DP>,
mergeProps: MergeProps<SP, DP, OP, P>,
options?: ConnectOptions
): Connector<OP, P>;
}

56
flow-typed/npm/redux_v3.x.x.js vendored Normal file
View File

@@ -0,0 +1,56 @@
// flow-typed signature: ba132c96664f1a05288f3eb2272a3c35
// flow-typed version: c4bbd91cfc/redux_v3.x.x/flow_>=v0.33.x
declare module 'redux' {
/*
S = State
A = Action
*/
declare type Dispatch<A: { type: $Subtype<string> }> = (action: A) => A;
declare type MiddlewareAPI<S, A> = {
dispatch: Dispatch<A>;
getState(): S;
};
declare type Store<S, A> = {
// rewrite MiddlewareAPI members in order to get nicer error messages (intersections produce long messages)
dispatch: Dispatch<A>;
getState(): S;
subscribe(listener: () => void): () => void;
replaceReducer(nextReducer: Reducer<S, A>): void
};
declare type Reducer<S, A> = (state: S, action: A) => S;
declare type Middleware<S, A> =
(api: MiddlewareAPI<S, A>) =>
(next: Dispatch<A>) => Dispatch<A>;
declare type StoreCreator<S, A> = {
(reducer: Reducer<S, A>, enhancer?: StoreEnhancer<S, A>): Store<S, A>;
(reducer: Reducer<S, A>, preloadedState: S, enhancer?: StoreEnhancer<S, A>): Store<S, A>;
};
declare type StoreEnhancer<S, A> = (next: StoreCreator<S, A>) => StoreCreator<S, A>;
declare function createStore<S, A>(reducer: Reducer<S, A>, enhancer?: StoreEnhancer<S, A>): Store<S, A>;
declare function createStore<S, A>(reducer: Reducer<S, A>, preloadedState: S, enhancer?: StoreEnhancer<S, A>): Store<S, A>;
declare function applyMiddleware<S, A>(...middlewares: Array<Middleware<S, A>>): StoreEnhancer<S, A>;
declare type ActionCreator<A, B> = (...args: Array<B>) => A;
declare type ActionCreators<K, A> = { [key: K]: ActionCreator<A, any> };
declare function bindActionCreators<A, C: ActionCreator<A, any>>(actionCreator: C, dispatch: Dispatch<A>): C;
declare function bindActionCreators<A, K, C: ActionCreators<K, A>>(actionCreators: C, dispatch: Dispatch<A>): C;
declare function combineReducers<O: Object, A>(reducers: O): Reducer<$ObjMap<O, <S>(r: Reducer<S, any>) => S>, A>;
declare function compose<S, A>(...fns: Array<StoreEnhancer<S, A>>): Function;
}

Binary file not shown.

View File

@@ -14,6 +14,7 @@
<glyph unicode="&#xe900;" glyph-name="connection-lost" horiz-adv-x="1414" d="M0 299.153h196.337v-187.951h-196.337v187.951zM271.842 480.372h196.337v-369.169h-196.337v369.169zM543.656 661.562h196.337v-550.36h-196.337v550.36zM815.47 842.766v-731.564h119.56c-14.589 33.025-23.125 71.503-23.232 111.943 0.132 86.42 38.697 163.851 99.656 216.468l0.348 403.153h-196.332zM1087.292 1024v-533.672c28.874 10.572 62.222 16.73 97.009 16.825 35.717-0.129 69.823-6.614 101.322-18.371l-1.999 535.218h-196.332zM1192.868 439.852c-0.009 0-0.020 0-0.031 0-122.247 0-221.351-98.447-221.372-219.896 0-0.007 0-0.014 0-0.021 0-121.467 99.111-219.935 221.372-219.935 0.011 0 0.021 0 0.032 0 122.248 0.014 221.345 98.477 221.345 219.935 0 0.007 0 0.013 0 0.020-0.021 121.441-99.11 219.883-221.345 219.897zM1194.706 372.607c87.601-0.006 158.614-69.787 158.614-155.866 0-0.006 0-0.012 0-0.019-0.022-86.062-71.026-155.822-158.614-155.828-87.588 0.006-158.593 69.766-158.615 155.826 0 0.007 0 0.014 0 0.020 0 86.079 71.013 155.86 158.613 155.866zM1286.795 355.682l48.348-52.528-236.375-217.567-48.348 52.528 236.375 217.567z" />
<glyph unicode="&#xe901;" glyph-name="avatar" d="M512 204c106 0 200 56 256 138-2 84-172 132-256 132-86 0-254-48-256-132 56-82 150-138 256-138zM512 810c-70 0-128-58-128-128s58-128 128-128 128 58 128 128-58 128-128 128zM512 938c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426z" />
<glyph unicode="&#xe902;" glyph-name="download" d="M726 470h-128v170h-172v-170h-128l214-214zM826 596c110-8 198-100 198-212 0-118-96-214-214-214h-554c-142 0-256 114-256 256 0 132 100 240 228 254 54 102 160 174 284 174 156 0 284-110 314-258z" />
<glyph unicode="&#xe903;" glyph-name="mic-camera-combined" d="M756.704 628.138l267.296 202.213v-635.075l-267.296 202.213v-191.923c0-12.085-11.296-21.863-25.216-21.863h-706.272c-13.92 0-25.216 9.777-25.216 21.863v612.25c0 12.085 11.296 21.863 25.216 21.863h706.272c13.92 0 25.216-9.777 25.216-21.863v-189.679zM371.338 376.228c47.817 0 86.529 40.232 86.529 89.811v184.835c0 49.651-38.713 89.883-86.529 89.883-47.788 0-86.515-40.232-86.515-89.883v-184.835c0-49.579 38.756-89.811 86.515-89.811v0zM356.754 314.070v-32.78h33.718v33.412c73.858 9.606 131.235 73.73 131.235 151.351v88.232h-30.636v-88.232c0-67.57-53.696-122.534-119.734-122.534-66.024 0-119.691 54.964-119.691 122.534v88.232h-30.636v-88.232c0-79.215 59.674-144.502 135.744-151.969v-0.014z" />
<glyph unicode="&#xe904;" glyph-name="kick" d="M512 810l284-426h-568zM214 298h596v-84h-596v84z" />
<glyph unicode="&#xe905;" glyph-name="hangup" d="M512 640c-68 0-134-10-196-30v-132c0-16-10-34-24-40-42-20-80-46-114-78-8-8-18-12-30-12s-22 4-30 12l-106 106c-8 8-12 18-12 30s4 22 12 30c130 124 306 200 500 200s370-76 500-200c8-8 12-18 12-30s-4-22-12-30l-106-106c-8-8-18-12-30-12s-22 4-30 12c-34 32-72 58-114 78-14 6-24 20-24 38v132c-62 20-128 32-196 32z" />
<glyph unicode="&#xe906;" glyph-name="chat" d="M854 342v512h-684v-598l86 86h598zM854 938c46 0 84-38 84-84v-512c0-46-38-86-84-86h-598l-170-170v768c0 46 38 84 84 84h684z" />

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Binary file not shown.

View File

@@ -1,6 +1,35 @@
{
"IcoMoonType": "selection",
"icons": [
{
"icon": {
"paths": [
"M756.704 395.862l267.296-202.213v635.075l-267.296-202.213v191.923c0 12.085-11.296 21.863-25.216 21.863h-706.272c-13.92 0-25.216-9.777-25.216-21.863v-612.25c0-12.085 11.296-21.863 25.216-21.863h706.272c13.92 0 25.216 9.777 25.216 21.863v189.679zM371.338 647.772c47.817 0 86.529-40.232 86.529-89.811v-184.835c0-49.651-38.713-89.883-86.529-89.883-47.788 0-86.515 40.232-86.515 89.883v184.835c0 49.579 38.756 89.811 86.515 89.811v0zM356.754 709.93v32.78h33.718v-33.412c73.858-9.606 131.235-73.73 131.235-151.351v-88.232h-30.636v88.232c0 67.57-53.696 122.534-119.734 122.534-66.024 0-119.691-54.964-119.691-122.534v-88.232h-30.636v88.232c0 79.215 59.674 144.502 135.744 151.969v0.014z"
],
"attrs": [
{}
],
"isMulticolor": false,
"isMulticolor2": false,
"grid": 0,
"tags": [
"Combined Shape"
]
},
"attrs": [
{}
],
"properties": {
"order": 109,
"id": 0,
"name": "mic-camera-combined",
"prevSize": 32,
"code": 59651
},
"setIdx": 0,
"setId": 2,
"iconIdx": 0
},
{
"icon": {
"paths": [
@@ -26,8 +55,8 @@
"prevSize": 32,
"code": 59677
},
"setIdx": 0,
"setId": 2,
"setIdx": 1,
"setId": 1,
"iconIdx": 0
},
{
@@ -55,8 +84,8 @@
"prevSize": 32,
"code": 59676
},
"setIdx": 0,
"setId": 2,
"setIdx": 1,
"setId": 1,
"iconIdx": 1
},
{
@@ -81,9 +110,9 @@
"code": 59649,
"name": "avatar"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 12
"setIdx": 1,
"setId": 1,
"iconIdx": 2
},
{
"icon": {
@@ -107,9 +136,9 @@
"code": 59653,
"name": "hangup"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 123
"setIdx": 1,
"setId": 1,
"iconIdx": 3
},
{
"icon": {
@@ -133,9 +162,9 @@
"code": 59654,
"name": "chat"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 149
"setIdx": 1,
"setId": 1,
"iconIdx": 4
},
{
"icon": {
@@ -159,9 +188,9 @@
"code": 59650,
"name": "download"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 165
"setIdx": 1,
"setId": 1,
"iconIdx": 5
},
{
"icon": {
@@ -185,9 +214,9 @@
"code": 59655,
"name": "edit"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 186
"setIdx": 1,
"setId": 1,
"iconIdx": 6
},
{
"icon": {
@@ -211,9 +240,9 @@
"code": 59656,
"name": "share-doc"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 207
"setIdx": 1,
"setId": 1,
"iconIdx": 7
},
{
"icon": {
@@ -237,9 +266,9 @@
"code": 59657,
"name": "telephone"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 216
"setIdx": 1,
"setId": 1,
"iconIdx": 8
},
{
"icon": {
@@ -263,9 +292,9 @@
"code": 59652,
"name": "kick"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 243
"setIdx": 1,
"setId": 1,
"iconIdx": 9
},
{
"icon": {
@@ -289,9 +318,9 @@
"code": 59679,
"name": "menu-up"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 257
"setIdx": 1,
"setId": 1,
"iconIdx": 10
},
{
"icon": {
@@ -315,9 +344,9 @@
"code": 59680,
"name": "menu-down"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 258
"setIdx": 1,
"setId": 1,
"iconIdx": 11
},
{
"icon": {
@@ -341,9 +370,9 @@
"code": 59659,
"name": "full-screen"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 351
"setIdx": 1,
"setId": 1,
"iconIdx": 12
},
{
"icon": {
@@ -367,9 +396,9 @@
"code": 59660,
"name": "exit-full-screen"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 352
"setIdx": 1,
"setId": 1,
"iconIdx": 13
},
{
"icon": {
@@ -393,9 +422,9 @@
"code": 59658,
"name": "star-full"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 364
"setIdx": 1,
"setId": 1,
"iconIdx": 14
},
{
"icon": {
@@ -419,9 +448,9 @@
"code": 59661,
"name": "security"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 474
"setIdx": 1,
"setId": 1,
"iconIdx": 15
},
{
"icon": {
@@ -445,9 +474,9 @@
"code": 59662,
"name": "security-locked"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 475
"setIdx": 1,
"setId": 1,
"iconIdx": 16
},
{
"icon": {
@@ -471,9 +500,9 @@
"code": 59663,
"name": "reload"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 483
"setIdx": 1,
"setId": 1,
"iconIdx": 17
},
{
"icon": {
@@ -497,9 +526,9 @@
"code": 59664,
"name": "microphone"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 493
"setIdx": 1,
"setId": 1,
"iconIdx": 18
},
{
"icon": {
@@ -523,9 +552,9 @@
"code": 59665,
"name": "mic-empty"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 494
"setIdx": 1,
"setId": 1,
"iconIdx": 19
},
{
"icon": {
@@ -549,9 +578,9 @@
"code": 59666,
"name": "mic-disabled"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 495
"setIdx": 1,
"setId": 1,
"iconIdx": 20
},
{
"icon": {
@@ -575,9 +604,9 @@
"code": 59678,
"name": "raised-hand"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 540
"setIdx": 1,
"setId": 1,
"iconIdx": 21
},
{
"icon": {
@@ -601,9 +630,9 @@
"code": 59675,
"name": "contactList"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 550
"setIdx": 1,
"setId": 1,
"iconIdx": 22
},
{
"icon": {
@@ -627,9 +656,9 @@
"code": 59667,
"name": "link"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 560
"setIdx": 1,
"setId": 1,
"iconIdx": 23
},
{
"icon": {
@@ -653,9 +682,9 @@
"code": 59668,
"name": "shared-video"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 591
"setIdx": 1,
"setId": 1,
"iconIdx": 24
},
{
"icon": {
@@ -679,9 +708,9 @@
"code": 59669,
"name": "settings"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 666
"setIdx": 1,
"setId": 1,
"iconIdx": 25
},
{
"icon": {
@@ -705,9 +734,9 @@
"code": 59670,
"name": "star"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 718
"setIdx": 1,
"setId": 1,
"iconIdx": 26
},
{
"icon": {
@@ -731,9 +760,9 @@
"code": 59681,
"name": "switch-camera"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 742
"setIdx": 1,
"setId": 1,
"iconIdx": 27
},
{
"icon": {
@@ -757,9 +786,9 @@
"code": 59671,
"name": "share-desktop"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 784
"setIdx": 1,
"setId": 1,
"iconIdx": 28
},
{
"icon": {
@@ -783,9 +812,9 @@
"code": 59672,
"name": "camera"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 799
"setIdx": 1,
"setId": 1,
"iconIdx": 29
},
{
"icon": {
@@ -809,9 +838,9 @@
"code": 59673,
"name": "camera-disabled"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 800
"setIdx": 1,
"setId": 1,
"iconIdx": 30
},
{
"icon": {
@@ -835,9 +864,9 @@
"code": 59674,
"name": "volume"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 822
"setIdx": 1,
"setId": 1,
"iconIdx": 31
},
{
"icon": {
@@ -885,7 +914,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 0
"iconIdx": 32
},
{
"icon": {
@@ -956,7 +985,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 4
"iconIdx": 33
},
{
"icon": {
@@ -983,7 +1012,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 12
"iconIdx": 34
},
{
"icon": {
@@ -1011,7 +1040,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 13
"iconIdx": 35
},
{
"icon": {
@@ -1039,7 +1068,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 22
"iconIdx": 36
}
],
"height": 1024,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 611 B

182
images/logo-blue.svg Normal file
View File

@@ -0,0 +1,182 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="210mm"
height="297mm"
viewBox="0 0 744.09448819 1052.3622047"
id="svg3526"
version="1.1"
inkscape:version="0.91 r13725"
inkscape:export-filename="/Users/ystamcheva/Dropbox/Designs/appLogo.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
sodipodi:docname="logo-blue.svg">
<defs
id="defs3528" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.49497475"
inkscape:cx="817.30793"
inkscape:cy="496.00851"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1440"
inkscape:window-height="851"
inkscape:window-x="0"
inkscape:window-y="1"
inkscape:window-maximized="1" />
<metadata
id="metadata3531">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
id="g4181">
<g
style="fill:#17a0db;fill-opacity:1"
transform="translate(43.272677,-6.8248629)"
id="g33">
<path
d="m 257.311,591.057 c 27.544,0 85.707,-16.445 124.179,-27.332 5.595,-1.575 10.81,-3.049 15.549,-4.371 0.767,-0.211 1.51,-0.403 2.213,-0.579 -2.161,-2.139 -5.755,-5.387 -11.612,-10.295 -25.628,-17.369 -49.827,-25.456 -76.146,-25.456 -5.741,0 -11.707,0.352 -18.208,1.088 -22.283,2.535 -40.848,7.845 -49.767,10.39 -4.521,1.296 -5.883,1.683 -7.292,1.683 -2.688,0 -4.997,-1.599 -5.9,-4.069 -0.904,-2.483 -0.13,-5.223 1.969,-6.981 l 0.127,-0.102 c 15.379,-12.883 44.032,-36.866 98.39,-47.582 9.428,-1.853 19.514,-2.796 29.968,-2.796 24.334,0 49.53,5.026 74.869,14.925 34.511,13.474 58.094,30.771 77.062,44.67 10.211,7.489 19.03,13.959 26.705,17.516 1.961,0.912 2.979,1.169 3.453,1.236 0.349,-0.452 1.106,-1.7 2.219,-4.974 0.298,-0.867 2.453,-10.019 -13.007,-62.071 -8.985,-30.217 -19.822,-61.077 -25.465,-74.778 -10.916,-26.509 -8.237,-45.296 -4.877,-56.284 -9.248,3.399 -18.701,8.688 -28.646,15.993 l -0.62,0.458 c -4.969,3.684 -10.031,7.853 -15.482,12.725 -32.074,28.718 -56.104,43.69 -71.455,44.504 l -0.423,0.021 -0.421,-0.036 c -13.524,-1.148 -34.019,-20.834 -42.403,-30.801 -1.743,-1.169 -3.729,-1.699 -6.35,-1.699 -2.632,0 -5.583,0.553 -8.438,1.095 -2.077,0.394 -4.218,0.795 -6.341,1.01 -6.767,0.679 -16.252,2.867 -25.406,4.974 -4.413,1.014 -8.967,2.063 -13.13,2.922 -0.079,0.013 -1.866,0.382 -5.06,1.224 -22.624,6.693 -39.673,14.372 -48.012,21.628 -0.091,0.079 -0.36,0.288 -0.789,0.603 -5.64,4.009 -19.199,15.447 -23.29,34.907 l -0.043,0.162 c -8.541,35.837 4.408,80.28 21.615,105.666 8.093,11.932 16.814,19.376 23.944,20.42 1.775,0.252 3.905,0.386 6.321,0.386 z"
id="path35"
inkscape:connector-curvature="0"
style="fill:#17a0db;fill-opacity:1" />
</g>
<g
style="fill:#17a0db;fill-opacity:1"
transform="translate(43.272677,-6.8248629)"
id="g37">
<path
d="m 383.729,400.995 c 0.549,0.108 1.191,0.162 1.9,0.162 14.785,0 47.804,-21.408 53.912,-31.205 l 0.486,-0.78 0.694,-0.611 c 2.083,-2.056 8.099,-12.885 11.019,-19.367 -31.312,-9.394 -34.767,-26.347 -37.821,-41.41 -0.355,-1.749 -0.667,-3.324 -0.946,-4.732 -0.357,-1.842 -0.731,-3.713 -1.052,-5.159 -46.646,15.471 -60.905,24.154 -68.687,30.611 -4.027,3.345 -6.398,12.858 5.215,39.189 5.932,13.422 26.386,31.591 35.28,33.302 z"
id="path39"
inkscape:connector-curvature="0"
style="fill:#17a0db;fill-opacity:1" />
</g>
<path
style="fill:#17a0db;fill-opacity:1"
inkscape:connector-curvature="0"
id="path43"
d="m 183.03568,710.19014 c -5.799,-6.834 -8.258,-15.447 -7.293,-25.624 4.105,-49.397 -1.525,-61.33 -4.132,-64.162 -0.629,-0.685 -0.969,-0.685 -1.238,-0.685 -0.101,0 -0.195,0.006 -0.296,0.016 -4.84,1.157 -37.441,23.198 -44.638,89.005 -3.471,31.758 2.611,72.542 7.794,97.348 4.165,-14.646 10.742,-30.779 23.483,-47.384 11.862,-15.444 24.801,-27.623 40.852,-38.298 -4.99,-2.075 -10.346,-5.274 -14.532,-10.216 z" />
<g
style="fill:#17a0db;fill-opacity:1"
transform="translate(43.272677,-6.8248629)"
id="g45">
<path
d="m 485.028,154.141 c -3.896,25.701 -10.239,50.115 -22.077,75.883 12.904,-14.609 20.445,-30.481 22.971,-48.296 1.051,-7.38 2.045,-14.439 -0.894,-27.587 z"
id="path47"
inkscape:connector-curvature="0"
style="fill:#17a0db;fill-opacity:1" />
</g>
<g
style="fill:#17a0db;fill-opacity:1"
transform="translate(43.272677,-6.8248629)"
id="g49">
<path
d="m 413.102,273.797 c 23.135,-20.915 37.22,-55.455 43.078,-75.971 -20.149,19.407 -44.636,29.82 -60.351,36.512 -5.412,2.308 -10.08,4.295 -12.878,5.926 -1.178,0.685 -2.367,1.374 -3.571,2.069 -9.533,5.515 -23.924,13.85 -26.022,18.987 l -0.06,0.167 -0.078,0.165 c -6.529,13.72 -10.208,34.352 -11.387,46.184 15.135,-9.242 30.738,-15.41 43.699,-20.529 12.03,-4.753 22.432,-8.863 27.57,-13.51 z"
id="path51"
inkscape:connector-curvature="0"
style="fill:#17a0db;fill-opacity:1" />
</g>
<g
style="fill:#17a0db;fill-opacity:1"
transform="translate(43.272677,-6.8248629)"
id="g53">
<path
d="m 436.439,291.877 c -0.141,0.357 -0.292,0.695 -0.455,1.017 -3.833,11.143 1.446,26.3 11.227,32.017 2.602,1.522 5.132,2.452 7.559,2.772 0.334,0.014 0.666,0.027 1.001,0.027 7.601,0 13.801,-5.56 18.4,-16.519 2.896,-8.34 3.308,-18.23 1.125,-27.158 -1.696,-6.936 -6.084,-15.215 -8.88,-19.343 -5.219,3.582 -15.533,11.462 -22.615,17.716 -4.946,4.777 -6.733,7.785 -7.362,9.471 z"
id="path55"
inkscape:connector-curvature="0"
style="fill:#17a0db;fill-opacity:1" />
</g>
<g
style="fill:#17a0db;fill-opacity:1"
transform="translate(43.272677,-6.8248629)"
id="g57">
<path
d="m 501.845,575.103 c 8.403,-2.29 15.076,-4.165 19.998,-5.623 -10.137,-7.061 -21.871,-15.846 -37.823,-28.253 -39.096,-30.404 -81.019,-45.826 -124.587,-45.826 -23.861,0 -44.647,4.592 -61.098,10.151 4.101,-0.255 8.271,-0.377 12.554,-0.377 5.088,0 10.42,0.179 15.842,0.541 16.949,1.136 60.616,8.845 100.106,55.931 7.956,9.469 16.507,17.307 40.828,17.307 8.679,0 18.796,-0.967 30.913,-2.959 0.749,-0.209 1.882,-0.518 3.267,-0.892 z"
id="path59"
inkscape:connector-curvature="0"
style="fill:#17a0db;fill-opacity:1" />
</g>
<g
style="fill:#17a0db;fill-opacity:1"
transform="translate(43.272677,-6.8248629)"
id="g61">
<path
d="m 557.268,369.949 c -7.755,-12.043 -17.498,-19.524 -25.41,-19.524 -1.464,0 -2.862,0.258 -4.154,0.765 -4.239,1.672 -10.952,21.042 -7.979,35.126 2.023,9.582 13.67,41.96 19.262,57.52 2.142,5.958 3.18,8.869 3.527,9.951 0.275,0.853 0.67,2.077 1.17,3.621 4.517,13.765 16.111,49.145 19.562,77.793 7.175,-30.554 11.239,-67.36 9.647,-111.409 -0.723,-20.199 -6.274,-39.323 -15.625,-53.843 z"
id="path63"
inkscape:connector-curvature="0"
style="fill:#17a0db;fill-opacity:1" />
</g>
<g
style="fill:#17a0db;fill-opacity:1"
transform="translate(43.272677,-6.8248629)"
id="g65">
<path
d="m 412.08,575.289 c -0.153,-0.2 -0.3,-0.397 -0.445,-0.585 -0.614,0.1 -1.616,0.319 -3.185,0.776 l -0.657,0.197 c -8.011,2.95 -22.707,7.908 -39.694,13.64 -20.387,6.87 -43.477,14.659 -62.808,21.595 -24.596,9.165 -32.572,12.781 -35.073,14.048 -0.454,1.218 -0.963,2.772 -1.53,4.486 -5.817,17.705 -19.139,58.23 -84.831,86.562 13.568,13.744 43.101,38.415 101.24,38.415 5.035,0 10.258,-0.188 15.494,-0.566 43.896,-3.121 85.158,-22.544 116.206,-54.673 28.233,-29.21 44.259,-65.641 44.507,-100.76 -6.871,-0.571 -18.519,-2.281 -29.301,-7.4 -0.125,-0.061 -12.447,-6.002 -19.923,-15.735 z"
id="path67"
inkscape:connector-curvature="0"
style="fill:#17a0db;fill-opacity:1" />
</g>
<g
style="fill:#17a0db;fill-opacity:1"
transform="translate(43.272677,-6.8248629)"
id="g69">
<path
d="m 162.104,639.109 c -0.122,10.334 -1.489,20.245 -2.82,29.907 -0.716,5.216 -1.464,10.615 -2.014,16.041 -0.746,10.914 1.612,14.717 2.659,15.829 0.571,0.629 1.513,1.346 3.536,1.346 1.558,0 3.418,-0.432 5.383,-1.251 19.507,-8.176 38.032,-22.367 46.937,-30.243 -13.668,-6.095 -34.689,-19.26 -53.681,-31.629 z"
id="path71"
inkscape:connector-curvature="0"
style="fill:#17a0db;fill-opacity:1" />
</g>
<g
style="fill:#17a0db;fill-opacity:1"
transform="translate(43.272677,-6.8248629)"
id="g73">
<path
d="m 484.26,598.224 c -0.552,7.258 -1.737,20.949 -3.631,31.378 -2.295,12.629 -6.095,23.31 -8.305,28.889 3.945,3.648 7.878,7.228 10.429,9.488 10.265,-6.718 43.961,-32.297 67.208,-90.368 -7.447,5.03 -17.906,9.456 -31.465,13.332 -13.797,3.929 -27.204,6.229 -34.236,7.281 z"
id="path75"
inkscape:connector-curvature="0"
style="fill:#17a0db;fill-opacity:1" />
</g>
<g
transform="translate(43.272677,-6.8248629)"
id="g85"
style="fill:#17a0db;fill-opacity:1">
<path
style="fill:#17a0db;fill-opacity:1"
inkscape:connector-curvature="0"
id="path87"
d="M 627.562,350.519 C 613.5,321.124 593.893,306.283 580.351,297.677 568.965,290.444 555.872,285.188 541.339,282 c -1.622,-10.158 -4.397,-20.542 -8.198,-30.646 24.507,-36.531 30.407,-77.605 17.008,-119.213 C 539.858,100.151 531.868,79.524 524.996,67.213 510.15,40.585 489.58,34.997 474.936,34.997 c -15.09,0 -29.538,6.412 -39.667,17.61 -10.37,11.462 -15.213,26.462 -13.634,42.228 1.349,13.446 -2.178,37.872 -4.519,46.594 -0.04,0.117 -4.202,11.776 -35.168,26.784 -0.746,0.268 -2.332,0.811 -4.773,1.629 -17.812,5.965 -50.913,17.062 -72.963,46.219 -16.847,20.407 -20.985,40.629 -25.766,64.036 -2.858,13.955 -5.846,32.187 -5.105,53.745 -55.35,12.291 -95.226,37.338 -118.609,74.54 -24.203,38.52 -28.402,86.272 -12.468,141.993 l 0.14,0.414 c 0.292,1.014 0.6,2.024 0.921,3.03 -2.718,-0.466 -5.465,-0.858 -8.285,-1.169 -2.469,-0.284 -5.015,-0.42 -7.54,-0.42 -27.636,0 -57.043,17.371 -78.666,46.474 -16.427,22.098 -36.156,61.131 -36.852,121.593 -0.523,44.905 4.279,86.306 14.283,123.054 7.461,27.381 15.784,44.202 18.979,50.09 l 67.793,127.079 31.06,-140.731 c 10.6,-47.935 21.066,-68.283 34.571,-81.732 31.425,18.938 68.541,28.901 107.941,28.901 43.919,0 89.715,-12.667 128.934,-35.662 25.477,-14.954 47.193,-33.324 64.629,-54.658 0.236,0 0.469,0 0.704,0 l 1.857,-0.038 c 10.782,-0.365 25.522,-5.697 40.434,-14.63 12.421,-7.433 31.147,-21.108 49.946,-44.064 18.945,-23.155 34.402,-51.324 45.926,-83.731 13.5,-37.939 21.717,-82.115 24.404,-131.272 3.253,-45.723 -2.078,-83.533 -15.881,-112.384 z m -31.124,109.427 c -2.415,44.805 -9.745,84.66 -21.764,118.441 -9.713,27.302 -22.502,50.739 -38.005,69.69 -26.696,32.611 -52.783,41.355 -55.551,41.465 l -0.22,0 c -2.528,0 -4.012,-1.032 -11.095,-5.988 -1.979,-1.379 -4.969,-3.467 -7.436,-5.075 -14.813,28.811 -39.145,53.701 -70.659,72.185 -32.098,18.824 -69.432,29.202 -105.1,29.202 -42.352,0 -79.532,-13.979 -107.842,-40.493 -38.621,24.556 -61.833,45.044 -80.652,130.273 l -3.562,16.157 -7.787,-14.59 C 84.8,867.621 78.058,854.32 71.708,830.982 62.852,798.444 58.598,761.384 59.071,720.842 c 0.944,-80.909 44.373,-121.518 68.427,-121.518 0.792,0 1.578,0.039 2.328,0.128 22.8,2.551 37.699,12.402 64.745,30.291 2.796,1.853 5.74,3.8 8.843,5.838 9.69,6.36 23.387,14.125 26.835,14.791 6.562,-0.381 12.986,-15.079 14.853,-28.713 0.114,-0.829 0.226,-1.598 0.334,-2.315 0.147,-1.612 0.227,-3.03 0.27,-4.194 -1.144,-0.399 -2.333,-0.869 -3.547,-1.403 l -0.27,-0.091 c -17.012,-5.857 -41.868,-34.625 -54.378,-76.385 -12.081,-42.21 -9.691,-77.122 7.099,-103.83 27.221,-43.328 86.307,-53.515 105.849,-56.861 6.109,-1.214 12.498,-2.351 18.999,-3.378 3.035,-0.762 5.11,-1.399 6.449,-1.978 0.58,-0.403 0.835,-0.833 0.439,-2.403 l 0.53,-0.148 -0.513,0.115 c -0.237,-1.065 -0.565,-2.311 -0.941,-3.753 -0.521,-1.997 -1.103,-4.256 -1.705,-6.936 -6.05,-27.141 -2.962,-49.884 0.863,-68.559 4.297,-21.019 6.678,-32.656 16.605,-44.279 13.152,-18.103 36.803,-26.025 50.953,-30.77 3.948,-1.322 7.359,-2.462 9.331,-3.412 43.344,-20.789 57.145,-42.646 61.091,-57.318 3.127,-11.642 8.084,-42.253 5.931,-63.63 -0.239,-2.425 0.326,-4.421 1.695,-5.935 1.215,-1.341 2.942,-2.104 4.748,-2.104 4.061,0 9.623,0 30.377,64.478 10.949,33.996 2.785,65.868 -24.244,94.74 -0.347,0.375 -0.7,0.742 -1.04,1.095 -0.738,0.76 -1.848,1.909 -1.999,2.326 0.006,0 -0.048,1.042 1.755,4.031 11.425,18.864 17.633,42.323 15.832,59.763 -0.429,4.062 -1.206,7.971 -1.879,11.411 -0.4,1.968 -0.879,4.377 -1.126,6.241 0.111,0 0.226,0 0.347,0 3.088,-0.327 7.867,-0.7 13.628,-0.7 13.556,0 32.969,2.077 48.503,11.951 9.382,5.952 21.255,15.137 29.981,33.404 10.281,21.472 14.096,51.453 11.369,89.114 z" />
</g>
</g>
<path
style="fill:#ffffff"
d=""
id="path3618"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -2,6 +2,7 @@
<head>
<meta charset="utf-8">
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--#include virtual="base.html" -->
<script>
window.indexLoadedTime = window.performance.now();
@@ -112,6 +113,11 @@
window.setTimeout(
function () { window.location.replace(href); }, delay);
// Call extra handler if defined.
if (typeof postLoadErrorHandler === "function") {
postLoadErrorHandler();
}
};
window.removeEventListener(
'error', loadErrHandler, true /* capture phase */);
@@ -121,7 +127,7 @@
'error', loadErrHandler, true /* capture phase type of listener */);
</script>
<script><!--#include virtual="/config.js" --></script><!-- adapt to your needs, i.e. set hosts and bosh path -->
<script src="utils.js?v=1"></script>
<script src="static/utils.js?v=1"></script>
<!--#include virtual="connection_optimization/connection_optimization.html" -->
<script src="connection_optimization/do_external_connect.js?v=1"></script>
<script><!--#include virtual="/interface_config.js" --></script>

View File

@@ -11,6 +11,8 @@ var interfaceConfig = { // eslint-disable-line no-unused-vars
DEFAULT_LOCAL_DISPLAY_NAME: "me",
SHOW_JITSI_WATERMARK: true,
JITSI_WATERMARK_LINK: "https://jitsi.org",
// if watermark is disabled by default, it can be shown only for guests
SHOW_WATERMARK_FOR_GUESTS: true,
SHOW_BRAND_WATERMARK: false,
BRAND_WATERMARK_LINK: "",
SHOW_POWERED_BY: false,
@@ -53,6 +55,8 @@ var interfaceConfig = { // eslint-disable-line no-unused-vars
* Whether to only show the filmstrip (and hide the toolbar).
*/
filmStripOnly: false,
//A html text to be shown to guests on the close page, false disables it
CLOSE_PAGE_GUEST_HINT: false,
RANDOM_AVATAR_URL_PREFIX: false,
RANDOM_AVATAR_URL_SUFFIX: false,
FILM_STRIP_MAX_HEIGHT: 120,
@@ -66,5 +70,16 @@ var interfaceConfig = { // eslint-disable-line no-unused-vars
AUDIO_LEVEL_SECONDARY_COLOR: "rgba(255,255,255,0.2)",
POLICY_LOGO: null,
LOCAL_THUMBNAIL_RATIO: 16/9, //16:9
REMOTE_THUMBNAIL_RATIO: 1 //1:1
REMOTE_THUMBNAIL_RATIO: 1, //1:1
// Documentation reference for the live streaming feature.
LIVE_STREAMING_HELP_LINK: "https://jitsi.org/live",
/**
* Whether the mobile app Jitsi Meet is to be promoted to participants
* attempting to join a conference in a mobile Web browser. If undefined,
* default to true.
*
* @type {boolean}
*/
MOBILE_APP_PROMO: true
};

View File

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

View File

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

View File

@@ -8,11 +8,35 @@
*/
#import "AppDelegate.h"
#import <Crashlytics/Crashlytics.h>
#import <Fabric/Fabric.h>
#import "RCTBundleURLProvider.h"
#import "RCTLinkingManager.h"
#import "RCTRootView.h"
#import <React/RCTAssert.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTLinkingManager.h>
#import <React/RCTRootView.h>
/**
* A <tt>RCTFatalHandler</tt> implementation which swallows JavaScript errors.
* In the Release configuration, React Native will (intentionally) raise an
* unhandled NSException for an unhandled JavaScript error. This will
* effectively kill the application. <tt>_RCTFatal</tt> is suitable to be in
* accord with the Web i.e. not kill the application.
*/
RCTFatalHandler _RCTFatal = ^(NSError *error) {
id jsStackTrace = error.userInfo[RCTJSStackTraceKey];
@try {
NSString *name
= [NSString stringWithFormat:@"%@: %@",
RCTFatalExceptionName,
error.localizedDescription];
NSString *message
= RCTFormatError(error.localizedDescription, jsStackTrace, 75);
[NSException raise:name format:@"%@", message];
} @catch (NSException *e) {
if (!jsStackTrace) {
@throw;
}
}
};
@implementation AppDelegate
@@ -29,7 +53,15 @@ continueUserActivity:(NSUserActivity *)userActivity
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[Fabric with:@[[Crashlytics class]]];
#if !DEBUG
// In the Release configuration, React Native will (intentionally) raise an
// unhandled NSException for an unhandled JavaScript error. This will
// effectively kill the application. In accord with the Web, do not kill the
// application.
if (!RCTGetFatalHandler()) {
RCTSetFatalHandler(_RCTFatal);
}
#endif
NSURL *jsCodeLocation
= [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios"

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

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@@ -2,53 +2,103 @@
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
"scale" : "3x",
"size" : "20x20"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "AppIcon-29@2x.png",
"scale" : "2x"
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "AppIcon-29@3x.png",
"scale" : "3x"
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "AppIcon-40@2x.png",
"scale" : "2x"
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "AppIcon-60@2x.png",
"scale" : "3x"
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "AppIcon-60@2x.png",
"scale" : "2x"
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "AppIcon-60@3x.png",
"scale" : "3x"
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"filename" : "AppIcon-29@2x.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"filename" : "AppIcon-40@2x.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"filename" : "AppIcon-76@1x.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"filename" : "AppIcon-76@2x.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"filename" : "AppIcon-83.5@2x.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}

View File

@@ -1,22 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchScreen-480@1x.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchScreen-480@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "LaunchScreen-480@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 KiB

View File

@@ -17,25 +17,24 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>1.3</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLName</key>
<string>org.jitsi.meet</string>
<key>CFBundleURLSchemes</key>
<array>
<string>org.jitsi.meet</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>Fabric</key>
<dict>
<key>APIKey</key>
<string>a8ae24a58302ba79da1d312138e941f6b86e3242</string>
<key>Kits</key>
<array>
<dict>
<key>KitInfo</key>
<dict/>
<key>KitName</key>
<string>Crashlytics</string>
</dict>
</array>
</dict>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>
@@ -57,11 +56,11 @@
</dict>
</dict>
<key>NSCameraUsageDescription</key>
<string></string>
<string>Participate in conferences with video.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>NSMicrophoneUsageDescription</key>
<string></string>
<string>Participate in conferences with audio.</string>
<key>UIAppFonts</key>
<array>
<string>jitsi.ttf</string>
@@ -81,9 +80,10 @@
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>

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