Compare commits

...

299 Commits

Author SHA1 Message Date
Saúl Ibarra Corretgé
505ed15323 WIP 2020-06-10 17:10:02 +02:00
Vlad Piersec
8758c222c6 feat(branding): Add ability to customize logo & background 2020-06-10 14:58:27 +02:00
Bettenbuk Zoltan
29dc63fbcb ref: merge prejoin with lobby 2020-06-09 18:10:43 +02:00
Bettenbuk Zoltan
475a2ae596 feat: lobby feature
The lobby feature adds the possibility to lock a meeting and only allow people in after virtually knocking and going through formal approval
2020-06-09 18:10:43 +02:00
dependabot[bot]
338c960215 build(deps): bump websocket-extensions from 0.1.3 to 0.1.4
Bumps [websocket-extensions](https://github.com/faye/websocket-extensions-node) from 0.1.3 to 0.1.4.
- [Release notes](https://github.com/faye/websocket-extensions-node/releases)
- [Changelog](https://github.com/faye/websocket-extensions-node/blob/master/CHANGELOG.md)
- [Commits](https://github.com/faye/websocket-extensions-node/compare/0.1.3...0.1.4)

Signed-off-by: dependabot[bot] <support@github.com>
2020-06-09 10:09:02 +02:00
Jaya Allamsetty
e6093e0706 fix(UI): Highlight the audio device when we hover over it 2020-06-08 15:34:05 -04:00
Jaya Allamsetty
d1d968997e Disable audiosettings button on Firefox as it is not supported 2020-06-08 15:34:05 -04:00
Jaya Allamsetty
45570bc0e7 fix(device-selection): Update redux when a new speaker is selected
Update userSelectedAudioOutputDeviceId and userSelectedAudioOutputDeviceLabel when a new speaker is selected from the audio settings popup menu
2020-06-08 15:34:05 -04:00
Jaya Allamsetty
f4bcad02d8 fix(device-selection): Add a workaround for a chrome bug with default mic
Pass the real deviceId to gUM instead of 'default' for Chrome to return the correct media stream
2020-06-08 15:34:05 -04:00
khajaamin
26f7951894 Marathi language (#6615)
* Lang folder removed from proxy server and now using from local dev dir

* Added Marathi 100% langulage transalation
2020-06-08 12:33:40 -05:00
Richard Février
35dabb1a27 main-fr.json : remove duplicated key introduced by #6461 2020-06-08 12:13:36 -05:00
Murat Emir Cabaroğlu
c3b79802b2 add missing and fix wrong turkish translation 2020-06-08 11:17:28 -05:00
Дамян Минков
e6dbe65193 Moderated rooms or subdomains (#6959)
* fix: Fixes using token with no user context.

* feat(moderated): Adds option to add moderated rooms and subdomains.

When a user joins such room or subdomain in order to be a moderator needs to provide a valid jwt token for that room.

* squash: Renames function.

* ref: Removes filtering jicofo setting owners.

This will be disabled on jicofo side and will greatly simplify logic.
Also check the checks to avoid jwt for main domain to access subdomains and the other way around.

* fix: Skips allowners logic for admins.
2020-06-05 07:57:49 -05:00
Deepak Verma
ff23f81dfe flags: fix comment 2020-06-05 13:53:35 +02:00
Jaya Allamsetty
bc66c9063a chore(deps): update lib-jitsi-meet 2020-06-04 10:54:06 -04:00
Emil Ivov
974ef4a382 Merge pull request #6941 from jitsi/saghul-patch-5
shared-video: use a more recent video by default
2020-06-03 06:42:41 -05:00
Saúl Ibarra Corretgé
3bf82b573c shared-video: use a more recent video by default 2020-06-03 11:27:08 +02:00
hmuresan
b4b4339a1a external_api: add start/stop recording commands 2020-06-03 09:30:19 +02:00
Hristo Terezov
6773aed67f feat(recording): Limit notification 2020-06-02 16:00:54 -05:00
Saúl Ibarra Corretgé
d740752522 rn,responsive-ui: refactor dimensions detection
Use a dimensions detecting root component. The Dimensions module does not
measure the app's view size, but the Window, which may not be the same, for
example on iOS when PiP is used.

Also refactor the aspect ratio wrap component since it can be taken directly
from the store.

Last, remove the use of DimensionsDetector on LargeVideo and TileView since they
occupy the full-screen anyway.

Fixes PiP mode on iOS.
2020-06-02 16:54:28 +02:00
Marius Bardan
d93b219c7f lang: update RO translations 2020-06-02 10:19:06 +02:00
Marius Bardan
10cd150a07 lang: update RO translations 2020-06-02 10:19:06 +02:00
Jaya Allamsetty
a31f3c0c76 fix(config): Add missing capScreenshareBitrate to config.js 2020-05-29 14:04:30 -04:00
Simon Honegger
af39186a5f fix: typeof returns a string, so this condition was always true 2020-05-29 19:53:05 +02:00
Saúl Ibarra Corretgé
d4d1d0aa70 dev: add plugin for circular dependency detection
Example run: https://gist.github.com/saghul/e5e12edc108bdedbcbe65a3d7528235f
2020-05-29 10:37:09 +02:00
Saúl Ibarra Corretgé
3a88f4939c misc: break import cycle 2020-05-29 10:37:09 +02:00
Saúl Ibarra Corretgé
fe221fe4be deps: run npm audit fix 2020-05-29 10:37:09 +02:00
Jaya Allamsetty
1caaa47f5e chore(deps): update lib-jitsi-meet
fix(safari): Disable VAD processing on Safari - cfbb511bce
2020-05-28 17:19:07 -04:00
Hristo Terezov
a2c4d17e4d fix(record):web/mobile match disable functionality 2020-05-28 15:39:49 -05:00
Hristo Terezov
ce1de9e1e7 feat(recording): Disable buttons on active session 2020-05-28 15:39:49 -05:00
Hristo Terezov
3e7abf3da0 feat(subtitles): Disable for guests. 2020-05-28 13:43:18 -05:00
damencho
8b4f1789a6 chore(deps): Update lib-jitsi-meet, callstats using full URL. 2020-05-28 11:15:33 -05:00
Gabriel Imre
444e2b90df callstats: add siteID passing; sanitize confID path 2020-05-28 10:00:45 -05:00
Saúl Ibarra Corretgé
7de88995a5 labels: don't disable all labels when VIDEO_QUALITY_LABEL_DISABLED is set
Fixes: https://github.com/jitsi/jitsi-meet/issues/6880
2020-05-28 10:15:52 +02:00
Hristo Terezov
f0c6e934ce feat(config):InsecureRoomNameWarning config option 2020-05-27 18:03:15 -05:00
Дамян Минков
78b01d2c97 Adding whitelist and move away from using custom field for password. (#6621)
* Adding whitelist and move away from using custom field for password.

We re-use room lock for lobby password.

* Make sure we do not run muc-occupant-pre-join for non members only rooms.

* Destroying lobby room, when main room is destroyed or membersonly is disabled.

* Adds destroy reason.

* Clears lobby room instance on destroy.

Fixes problem with on/off/on of lobby feature.

* Add lobby room jid only when members only is on.

* Sends main room jid on lobby destroy.

We can use that in client loggic to auto-join lobby participants to main room as lobby is disabled while waiting.

* fix: Fixes using is_healthcheck_room.

* squash: Enables lobby rooms feature by default.

* chore(deps): Update lib-jitsi-meet, to enable lobby rooms.
2020-05-27 18:01:41 -05:00
Saúl Ibarra Corretgé
bf60be1654 style: fixup needlessly wrapped line 2020-05-27 16:45:11 +02:00
Saúl Ibarra Corretgé
5202a7e5b8 room-lock: use the proper text for the room lock prompt 2020-05-27 16:45:11 +02:00
Saúl Ibarra Corretgé
2af0c0ba17 rn: bump SDK version to 2.9.0 2020-05-27 15:35:58 +02:00
Saúl Ibarra Corretgé
fbb6486b5f deps: update react-native-watch-connectivity
It's back in active development and fixes a warning in iOS.
2020-05-27 15:35:58 +02:00
Saúl Ibarra Corretgé
a113151563 deps: update react-native-calendar-events
Rebase our patches (in PR) on top of latest master.

Sshould fix a crash when requesting permisssions.
2020-05-27 15:35:58 +02:00
Raider700
470fda3467 lang: add missing fields to German translation 2020-05-27 11:48:51 +02:00
Saúl Ibarra Corretgé
edea6316ab Update config.js 2020-05-27 08:43:48 +02:00
Saúl Ibarra Corretgé
adac9ee5f8 config: don't enable H.264 by default on P2P
We are not actively testing it and it currently crashes Chrome 83+ when insertable streams are used.
2020-05-27 08:43:48 +02:00
Saúl Ibarra Corretgé
af8bd876e6 deps: run npm audit fix
Skipped webpack, requires further investigation.
2020-05-27 00:16:20 +02:00
Jaya Allamsetty
403c4a7ee7 chore(deps): update lib-jitsi-meet
c94f6a570f
2020-05-26 17:14:21 -04:00
marius-bardan
21fe3c87a6 lang: enable support for romanian lang (#6869)
Co-authored-by: Marius Bardan <marius.bardan@8x8.com>
2020-05-26 15:05:41 +02:00
lorddavidiii
6ddac3bddf debian,turn: fix getting an external ip in IPv6 enabled networks 2020-05-26 13:20:34 +02:00
Mihai Uscat
663a65ad81 fix(SecurityDialog): fix button overflow 2020-05-26 10:22:22 +02:00
marius-bardan
5977f09202 lang: complete Romanian translation
Co-authored-by: Marius Bardan <marius.bardan@8x8.com>
2020-05-26 09:18:38 +02:00
Riccardo Magliocchetti
6be2a8575f lang: update document to match current reality 2020-05-25 17:26:15 +02:00
Suguru Hirahara
0d14e2fa5c gh: update 1-bug-report template
* Update 1-bug-report.md

- Comment out the general notice
- Add the information that questions and posts asking for help will be
closed
- Sort sections based on action stream -- steps, expected behaviour, (yet) actual behaviour
- Replace environment information with server-side and client-side ones

* Update .github/ISSUE_TEMPLATE/1-bug-report.md

Co-authored-by: Saúl Ibarra Corretgé <s@saghul.net>

Co-authored-by: Saúl Ibarra Corretgé <s@saghul.net>
2020-05-25 16:45:21 +02:00
qwertiko GmbH
1e0669d33b lang: fixes for German 2020-05-25 14:40:10 +02:00
Ricardo Brisighelli
d69c2c84d7 lang: update Spanish translation 2020-05-25 14:38:44 +02:00
Suguru Hirahara
0ea7a31b08 lang: add Arabic translation 2020-05-25 14:05:46 +02:00
Oleksa
6284e5fab3 lang: update Ukranian translation 2020-05-25 13:58:17 +02:00
Philip Eriksson
647852bd82 lang: fixes for Swedish 2020-05-25 13:52:15 +02:00
nordlolek
4e0d6e56bc rn,lang: bundle Slovenian translations 2020-05-25 13:46:37 +02:00
Quentí
c02763a29e lang: update for Occitan 2020-05-25 13:45:17 +02:00
Vangelis Zacharioudakis
0b8ec5a342 lang: add Greek language translation 2020-05-25 13:40:36 +02:00
huzaifahj
1a4be30ea1 lang: make "OK" capitalization consistent 2020-05-25 13:24:06 +02:00
tolgakaratas
d53d6e5fa8 lang,rn: bundle Turkish language 2020-05-25 13:20:54 +02:00
zzoond
93b05d13c3 lang: fix for russian 2020-05-25 11:27:50 +02:00
Michael Telatynski
79f4531bd2 lang: allow translation of accessibility label string "Edit your profile" 2020-05-25 11:26:25 +02:00
Jaya Allamsetty
5348fa19c8 feat: show option to join via browser on supported mobile browsers
Currently Chromium based browsers and Firefox are supported on Android
Only Safari is supported on iOS
2020-05-22 10:52:59 -04:00
Felix C. Stegerman
b25319fd2e add missing build dependency on nodejs 2020-05-21 10:29:36 -05:00
Felix C. Stegerman
63ca419e76 improve "open in app" page 2020-05-21 08:39:17 -04:00
Jonathan Lennox
393fb692ca Make TLS configs in Debian sample files follow Mozilla security guidelines. 2020-05-20 12:03:41 -05:00
JB BUGEAUD
735b686b98 Update of main fr translation (#6141)
* Update of main fr translation

Correct some non french sounding sentenses.  One example welcomepage.title, before "fully featured" was translated as "entièrement en vedette"  (which is gibberish) and now "riche en fonctionnalités".

* Fixing typo

Fixing missing comma

* Another typo fix

Yet another missing comma fixed.
2020-05-20 11:29:06 -05:00
Bettenbuk Zoltan
0598e7369b ref: eslint-config-jitsi@1.0.3 2020-05-20 17:14:29 +02:00
Suguru Hirahara
8c30e43b5f Retry "external_api: fixed using deeplinks"
Set target='_top' inside anchor.

Courtesy of #6700
Follow-up to: #6784
2020-05-20 10:18:29 -04:00
Mihai Uscat
75c836c70c feat(AddPeopleDialog): Update design; feat(SecurityDialog): Implement 2020-05-20 16:14:47 +02:00
Saúl Ibarra Corretgé
70d8fe91c3 deps: replace jsrsasign
We were only using a couple of utility functionss to parse tokens, not to
validate them in any way.
2020-05-20 15:06:19 +02:00
Julian1203
c6d5e103f5 lang: fixes for German 2020-05-20 12:20:56 +02:00
christian-sh
7f1f92cdf0 lang: fix passwordLabel translation in German
The former translation contained a typo and incorrect grammar.
2020-05-20 12:15:32 +02:00
Suguru Hirahara
8c02ba5ee9 doc: update README.md
- Fix a broken link (fixes #6780)
- Set direct links
- Add a link to the Docker installation guide
2020-05-20 08:07:32 +02:00
Jaya Allamsetty
5591144693 Revert "external_api: fixed using deeplinks"
This breaks the mobile deeplinking page
This reverts commit 532dadb245.
2020-05-19 16:43:10 -04:00
damencho
fa43539718 chore(deps): lib-jitsi-meet, skips sending an extra presence on join. 2020-05-19 15:39:20 -05:00
Jaya Allamsetty
7e0a36e88e chore(deps): Update lib-jitsi-meet
fix(Firefox): Enable RTX support on Firefox
E2EE fixes/improvements
fix(screenshare): Add google conference flag only when simulcast is on
fix(video-quality): Apply pending video constraints on p2p originator
2020-05-19 12:28:05 -04:00
msalmasi
532dadb245 external_api: fixed using deeplinks
This update opens links in the full body of the window so deeplinks will work on iOS Safari when using the external API in an iFrame.
2020-05-19 14:09:42 +02:00
Felix C. Stegerman
55051cc203 dev: don't proxy /lang/ 2020-05-19 11:58:21 +02:00
Vlad Piersec
4975f15345 fix(prejoin_page): Always show 'join without audio' & add disabled button.
* The prejoin page always displays the 'join without audio' option.
* The join button will be disabled if there is no input.
* Fix some CSS for the case when the user is not anonymous.
2020-05-19 11:47:55 +02:00
Alejandro Blanco
2e2d40c1d0 external-api: add muteEveryone command 2020-05-19 08:50:21 +02:00
Bettenbuk Zoltan
c08638da51 feat: insecure room name warning 2020-05-18 17:59:07 +02:00
Bettenbuk Zoltan
9525cab60f feat: icon type circular label 2020-05-18 17:59:07 +02:00
Bettenbuk Zoltan
21d5c895fc fix: package.lock version mismatch 2020-05-18 16:30:24 +02:00
Saúl Ibarra Corretgé
305a63e8f9 deep-linking: fix generating links for external API
The ocnfig is not overridden early enough.

Fixes: https://github.com/jitsi/jitsi-meet/issues/6489
2020-05-18 16:06:13 +02:00
Emil Ivov
2fef06772b Merge pull request #6755 from saghul/e2ee-label
e2ee: update padlock label tooltip
2020-05-18 07:51:37 -05:00
Vlad Piersec
b2895b7095 feat(prejoin_page): Add ability for guest to join audio by phone 2020-05-18 14:47:44 +02:00
Saúl Ibarra Corretgé
41dc14d30c e2ee: update padlock label tooltip 2020-05-18 14:12:00 +02:00
Suguru Hirahara
2ddfead4f5 doc: fix links on README 2020-05-18 11:53:58 +02:00
Saúl Ibarra Corretgé
d55b49b2c3 doc: move mobile docs to the handbook 2020-05-18 11:44:53 +02:00
Saúl Ibarra Corretgé
64d74852e0 ios: fix PiP window sshowing conference controls
The dynamic size of it was causing trouble. Fix it by setting a fixed PiP window
size (150px) which makes it consisstent with what we have on Android.

Fixes: https://github.com/jitsi/jitsi-meet/issues/6562
2020-05-18 09:34:52 +02:00
Saúl Ibarra Corretgé
7c4c8384fd doc: replace documentation with the handbook
- Leave a link on doc/README,api,quick-install
- Moved the cloud API swagger file to resources/
- Merged the coding conventions with CONTRIBUTING.md
2020-05-17 08:02:29 +02:00
Hristo Terezov
262e855260 fix: recommended browser page link. 2020-05-15 15:06:41 -05:00
Jaya Allamsetty
3f679407a9 fix(video-quality): Get rid of the video qaulity warning for p2p
It is now possible to change the sender video quality for p2p calls as well
2020-05-15 09:49:55 -04:00
Saúl Ibarra Corretgé
4faeb84d2e build: fix using parallell make
We don't support it, so make sure targets run serially.

Fixe: https://github.com/jitsi/jitsi-meet/issues/6647
2020-05-14 11:14:43 +02:00
Philipp Hancke
eed5e31ec9 Merge pull request #6061 from jitsi/npmrc
dev: add npmrc with package-lock set to true
2020-05-14 10:17:27 +02:00
Felix C. Stegerman
4b1d8ba877 update react-emoji-render to v1.2.4 (#6674) 2020-05-13 21:14:27 +02:00
NicolasD
3043f50ce3 rn,flags: add "toolbox.alwaysVisible" flag 2020-05-13 16:25:06 +02:00
Saúl Ibarra Corretgé
b7f1f3c659 ios: try to leave the meeting when the app is terminating
Fixes: https://github.com/jitsi/jitsi-meet/issues/6665
2020-05-13 16:21:38 +02:00
tmoldovan8x8
07f64d94c0 android: set view listener in onCreate 2020-05-13 10:56:37 +02:00
Boris Grozev
76e1217439 ref: Make is_healthcheck_room more generic. 2020-05-12 18:22:14 -05:00
crouchingtigerhiddenadam
591ea0a44a doc: quick install guide updates
* optional fix for https port 5284 error

https://community.jitsi.org/t/no-certificate-present-in-ssl-tls-configuration-for-https-port-5284/47836/7

* usage of sudo and systemctl made more consistent

* jigasi download url changed to stable

Jigasi download url changed. Is this required in addition to apt install jigasi as part of the quick install guide?

* wget/dpkg removed from jagasi instructions
2020-05-12 16:32:37 +02:00
Edgard Messias
24052e9f9a fix: Fixed browser language detect (close #5987) 2020-05-12 09:26:53 -05:00
bgrozev
38b8772af0 docs: Fix video tutorial links. (#6655) 2020-05-11 11:23:35 -05:00
Mihai Uscat
5fdb7c176c feat(MobileDeepLinking): Enable custom deeplinking domain 2020-05-11 15:33:10 +02:00
Saúl Ibarra Corretgé
a8da6d4095 lang: improve Basque translation
Thanks @irontec, @librezale and @arraintxo for working on it!
2020-05-11 15:32:31 +02:00
Saúl Ibarra Corretgé
01fc098d4b prejoin: fixup mobile
Avoid importing components, which are not yet implemented on mobile.
2020-05-11 14:15:55 +02:00
Saúl Ibarra Corretgé
b50b30e3eb doc: recommend Node 12 2020-05-11 13:51:00 +02:00
Wuriyanto
1b8e5d0244 change cjson to cjson.safe and cath error from decode function 2020-05-11 05:46:07 -05:00
Vlad Piersec
908712b96f feat(prejoin_page): Rework prejoin page
* Add a checkbox for skipping the prejoin page on next use. (This is hidden for
now, until we also have a settings entry for it).
* Rework 'Join by Phone' buttons and add new overlay.
* Update the device status accordingly if there were errors while adding
devices.
* The input is filled with the display name if there was one previously used.
* Join the meeting on 'Enter' press.
2020-05-11 10:59:52 +02:00
Goacid
a41bda73ff doc: add more details about systemd limits 2020-05-11 09:33:50 +02:00
Fabian Rodriguez
75ea0070e2 lang: improve frCA 2020-05-11 09:23:53 +02:00
Saúl Ibarra Corretgé
65a8091e53 android: simplify code
- No need to handle the activity result in the fragment, since we already do in
  the Activity
- Automagically ddispose the view when destroyed
2020-05-10 08:03:29 +02:00
Saúl Ibarra Corretgé
7fea8e2e6c android: suppress lint warning 2020-05-10 08:03:29 +02:00
Hristo Terezov
d388a7bd3c feat(reload): Preserve local track mute state. 2020-05-07 18:18:21 -05:00
Jaya Allamsetty
a48aa2b999 feat(external_api): Add command for setting send/recv video quality 2020-05-07 18:10:41 -04:00
tmoldovan8x8
b3f16926d4 rn: add ability to disable crash reporting 2020-05-07 23:05:48 +02:00
Paweł Domas
f646bc7a7a ref: disable ICE restart by default (#6594)
* ref: disable ICE restart by default

The reason for that it's currently causing issues with signaling when
Octo is enabled. Also when we do an "ICE restart"(which is not a real
ICE restart), the client maintains the TCC sequence number counter, but
the bridge resets it. The bridge sends media packets with TCC sequence
numbers starting from 0.

The 'enableIceRestart' config option can be used to force it, but it's
not recommended.
2020-05-07 06:59:37 -05:00
Andrey Nedobylsky
e90b60d661 lang: fix Russian translation
Fixed Russian translation for audioVideoSwitch
2020-05-07 11:39:59 +02:00
ludovicm67
bdd129b9a2 feat(analytics): include MatomoHandler by default 2020-05-06 15:32:49 +02:00
ludovicm67
4c635a2a63 feat(analytics): add Matomo support 2020-05-06 15:32:49 +02:00
Saúl Ibarra Corretgé
2b526557e4 participants: fix accessing the local participant ID
getLocalParticipant returns a participant object stored in Redux, not a
JitsiParticipant object.
2020-05-06 15:27:08 +02:00
Saúl Ibarra Corretgé
eee1f50ed2 deps: update lib-jitsi-meet
Fix losing media when using insertable streams on track changes.
2020-05-06 09:20:16 -04:00
Saúl Ibarra Corretgé
e9562adddf lang: add Basque to the list of available languages 2020-05-06 14:53:11 +02:00
patidars
8accd9e433 rn,flags: feature flag to show/hide 'Tile View' button 2020-05-06 14:22:59 +02:00
Saúl Ibarra Corretgé
caabdadf19 rn,polyfills: refactor all mobile polyfills
Move all polyfills to a standalone feature, which gets imported before anything
else in the mobile entrypoint. This guarantees that any further import sees the
polyfilled environment.
2020-05-06 12:35:12 +02:00
Saúl Ibarra Corretgé
062bc13d4f rn,storage: fix not using a persistent localStorage
In
1ffd75c0a6
we switched to using the localStorage wrapper provided by js-utils, which
checks for window.localStorage's availability very early. Our polyfill must be
applied earlier that any such import.

Here we are importing it in the entrypoint, which means no code ran before this,
literally.
2020-05-06 12:35:12 +02:00
ktagbnaw
a56e451536 misc: fix typo 2020-05-06 09:50:11 +02:00
Jim Bullington
acbf641fb4 Add participantRoleChanged event to external API (#6573)
* Add participantRoleChanged event to external API

* Update API documentation

* Remove unneeded whitespace

* Remove more unneeded whitespace

* Fix jsdoc formatting

* Fix jsdoc formatting
2020-05-05 09:03:54 -05:00
patidars
a18fd1cdb3 rn,flags: add feature flag to show/hide the 'Raise Hand' button 2020-05-04 18:22:45 +02:00
Saúl Ibarra Corretgé
9be78c60eb rn,lang: fix language detection to take region into account
If we have a regional variant, prefer that.
2020-05-04 16:59:37 +02:00
Vlad Piersec
a45cbf41ef feat(prejoin_page): Add prejoin page 2020-05-04 12:49:35 +02:00
Emil Ivov
5b53232964 Merge pull request #6547 from jitsi/fix-mobile-imports
chore(package): update dependencies.
2020-05-02 22:26:21 -05:00
Hristo Terezov
d4d4490aa9 chore(package): update dependencies. 2020-05-02 22:10:54 -05:00
Emil Ivov
0fd0897531 Merge pull request #6529 from jitsi/local-storage
fix(localStorage): exception when disabled.
2020-05-02 19:39:07 -05:00
Hristo Terezov
360383440e chore(package): Update dependencies. 2020-05-02 19:36:28 -05:00
Rich Brown
1a40672427 Fix the command to update jitsi-stable.list (#5731)
* Fix the command to update jitsi-stable.list

This command uses the technique recommended below that will always work. (See "Safest Solution (#3)") 

https://askubuntu.com/questions/185268/permission-denied-etc-apt-sources-list

* Update quick-install.md

remove "-a" argument from `tee`  to remove merge conflict
2020-05-02 07:50:34 +02:00
Hristo Terezov
1ffd75c0a6 fix(localStorage): exception when disabled. 2020-05-01 14:48:08 -05:00
Julian1203
77d38731e9 Update main-de.json
Fixed typo
2020-05-01 10:25:21 -05:00
Hristo Terezov
13f76c2cce fix(follow-me): disable the auto pin on SS 2020-04-30 16:58:22 -05:00
Jaya Allamsetty
9ad87f3706 fix: Add safari to optimal browser lists 2020-04-30 17:39:07 -04:00
damencho
eea8fef044 Initial Lobby backend implementation. 2020-04-30 16:34:46 -05:00
Jaya Allamsetty
c2cb4ea6b6 deps: update ljm 2020-04-30 15:29:04 -04:00
Jaya Allamsetty
d6cf0c0afd deps: bump lib-jitsi-meet 2020-04-30 12:56:31 -04:00
Fabian Rodriguez
f5faf5bbaa Update main-es.json
Added missing strings for Mute Everyone feature, other small fixes.
2020-04-30 10:16:05 -05:00
Valso
363982fad4 Update languages-eo.json
Add correct translation for  "el": "Greka",
2020-04-30 10:15:37 -05:00
Julian1203
62f47d5b87 Update main-de.json
Small improvement
2020-04-30 10:15:14 -05:00
Julian1203
223e8560ca lang: fixes for German 2020-04-30 14:44:06 +02:00
tmoldovan8x8
2085851179 android: persist Amplitude device id when not set externally
Co-authored-by: Titus-Andrei Moldovan <moldovan.titus@gmail.com>
2020-04-30 13:12:09 +02:00
Ferdi Bayrak
47bc6f0470 Added Turkish language on BuiltinLanguages.native.js (#5965)
* Added Turkish lang

Added Turkish lang

* Update BuiltinLanguages.native.js

* Update BuiltinLanguages.native.js
2020-04-29 16:27:37 -05:00
Tao Sasaki
c5686386fa Fix strange Japanese text (#6303) 2020-04-29 15:41:34 -05:00
adrmzz
e1cededb76 Adding Sardinian (#5984)
* Create main-sc.json

* Create languages-sc.json

* Update languages.json

* Update main-sc.json

(just a couple of minor edits to the translation)

* Update BuiltinLanguages.native.js

adding Sardinian

* trailing spaces corrected

* Update BuiltinLanguages.native.js

* Update BuiltinLanguages.native.js

fixed spaces

* Update main-sc.json
2020-04-29 14:07:51 -05:00
t7yang
268dc33324 polish zh-TW translation (#5678)
* polish zh-TW translation

Fix typos, use the correct and localize terms, replace some translations to make it fluent for native speaker.

* fix syntax error
2020-04-29 11:19:59 -05:00
Oleksa
baaf55a2ab Update languages.json 2020-04-29 10:30:27 -05:00
James Baird
a8252103ea Fix grammar on unsupported browser message
It should read "Chrome or Firefox" not "Chrome and Firefox", as you only need to use a single browser, not both.
2020-04-29 10:30:06 -05:00
zibens
b0ab51af90 Add files via upload
Introducing Latvian language, to make it more widespread in Latvia
2020-04-29 10:29:08 -05:00
tzagim
69b20cd945 Add Hebrew Translation & Fix TYPO (#5907)
* Create languages-he.json

Hebrew list languages

* Update languages-he.json

TYPO

* Update main-he.json

1/5

* Update main-he.json

2/5

* Update main-he.json

4/5

* Update main-he.json

Pause

* Update main-he.json

* Update main-he.json

Finish

* Update main.json

TYPO

* Update main.json

TYPO

* Update main.json

TYPO

* Update main-he.json

Add missing strings

* Update languages-he.json
2020-04-29 10:26:31 -05:00
ariadi
8bb0141c1a Translation in Indonesian (#5913)
* Add Indonesian

* Indonesian translation

* Update languages-id.json

* Create main-id.json

* Update languages-id.json

* Update main-id.json

* Update main-id.json
2020-04-29 10:25:56 -05:00
James.zhu
ed766c6fe2 Update main-zhCN.json
I will update the files for some mistakes in chinese. I would late update whole file in chinese.
2020-04-29 10:25:05 -05:00
chipechop
d883bae925 Update main-it.json
Simplified Mobile mani menu, with more fluent wording.
2020-04-29 10:23:21 -05:00
Joan Montané
62d3d1f294 Update BuiltinLanguages.native.js 2020-04-29 10:22:59 -05:00
Joan Montané
dbfed573ac Add Catalan entry on BuiltinLanguages.native.js 2020-04-29 10:22:59 -05:00
Daniel Neumann
640b9bfd52 added missing translations 2020-04-29 10:20:26 -05:00
Saúl Ibarra Corretgé
dac6d9d63c aandroid: raise SDK version 2020-04-29 17:20:11 +02:00
Daniel Ortega
0662da58b4 Fixing wrong translation in muteParticipantButton button 2020-04-29 10:20:04 -05:00
Daniel Ortega
d7d4ea819f Adding missing question mark 2020-04-29 10:20:04 -05:00
Daniel Ortega
2c6cac6526 Adding mute action related missing translations in spanish 2020-04-29 10:20:04 -05:00
Milan Kral
f53251f104 Enable Slovak translation.
Add Slovak translation to BuiltinLanguages

Follow up to #5523
2020-04-29 10:19:40 -05:00
Jelrik van Hal
8e01f769d9 Adds Dutch translation for "toolbar.muteEveryone" 2020-04-29 10:19:21 -05:00
Özcan Oğuz
8c4656a3c8 Wrong translation fixed 2020-04-29 10:18:36 -05:00
cayenne17
a5a36aa1e1 lang: translation improvements for French 2020-04-29 10:18:16 -05:00
Saúl Ibarra Corretgé
6939939a0f deps: update lib-jitsi-meet
Fixes mobile when importing E2EE.
2020-04-29 17:17:22 +02:00
Marc Laporte
c60671e008 Fix a typo 2020-04-29 10:16:59 -05:00
Valso
8e4e1f139a Update languages-eo.json 2020-04-29 10:16:38 -05:00
Anugoon Chotigarn
b608051177 Add Thailand (th) translation 2020-04-29 10:16:18 -05:00
Дамян Минков
2dad7e920b Merge weblate translations (#6461)
* Translated using Weblate (French)

Currently translated at 96.1% (646 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fr/

* Translated using Weblate (French)

Currently translated at 96.7% (650 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fr/

* Translated using Weblate (French)

Currently translated at 96.7% (650 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fr/

* Translated using Weblate (French)

Currently translated at 96.7% (650 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fr/

* Translated using Weblate (French)

Currently translated at 98.6% (663 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fr/

* Translated using Weblate (French)

Currently translated at 98.6% (663 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fr/

* Translated using Weblate (French)

Currently translated at 98.5% (662 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fr/

* Translated using Weblate (French)

Currently translated at 98.5% (662 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fr/

* Translated using Weblate (French)

Currently translated at 98.6% (663 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fr/

* Translated using Weblate (French)

Currently translated at 98.6% (663 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fr/

* Translated using Weblate (French)

Currently translated at 99.2% (667 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fr/

* Translated using Weblate (French)

Currently translated at 99.2% (667 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fr/

* Translated using Weblate (French)

Currently translated at 98.9% (665 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fr/

* Translated using Weblate (French)

Currently translated at 99.1% (666 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fr/

* Translated using Weblate (French)

Currently translated at 99.1% (666 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fr/

* Translated using Weblate (French)

Currently translated at 98.9% (665 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fr/

* Translated using Weblate (Italian)

Currently translated at 75.0% (24 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/it/

* Translated using Weblate (German)

Currently translated at 98.9% (665 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/de/

* Translated using Weblate (German)

Currently translated at 98.9% (665 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/de/

* Translated using Weblate (German)

Currently translated at 98.9% (665 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/de/

* Translated using Weblate (German)

Currently translated at 98.9% (665 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/de/

* Translated using Weblate (Russian)

Currently translated at 97.7% (657 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/ru/

* Translated using Weblate (Russian)

Currently translated at 97.7% (657 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/ru/

* Translated using Weblate (German)

Currently translated at 99.8% (671 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/de/

* Translated using Weblate (German)

Currently translated at 99.8% (671 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/de/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (672 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/hu/

* Translated using Weblate (Swedish)

Currently translated at 84.8% (570 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 84.8% (570 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 81.5% (548 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 81.8% (550 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 81.9% (551 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 81.9% (551 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 81.9% (551 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 82.1% (552 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 82.1% (552 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 82.2% (553 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 82.2% (553 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 83.4% (561 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 83.4% (561 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 84.3% (567 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 84.3% (567 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 84.5% (568 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 84.9% (571 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 84.9% (571 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 84.9% (571 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 84.9% (571 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 85.1% (572 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 85.1% (572 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 85.2% (573 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 85.2% (573 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 86.0% (578 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 86.0% (578 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 85.7% (576 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 86.3% (580 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 86.3% (580 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 86.7% (583 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 86.7% (583 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 87.7% (590 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 87.7% (590 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 86.9% (584 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 87.6% (589 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 91.5% (615 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 91.5% (615 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 88.8% (597 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 88.8% (597 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 90.9% (611 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 90.9% (611 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 90.9% (611 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 90.9% (611 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 91.3% (614 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Swedish)

Currently translated at 91.3% (614 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Basque)

Currently translated at 38.0% (256 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 38.6% (260 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 38.8% (261 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 39.2% (264 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 39.2% (264 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 39.5% (266 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 39.8% (268 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 40.1% (270 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 41.0% (276 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 41.3% (278 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 41.2% (277 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 41.8% (281 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 42.1% (283 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 43.3% (291 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 43.3% (291 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 43.7% (294 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 44.0% (296 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 44.1% (297 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 44.1% (297 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 44.3% (298 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 44.4% (299 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 44.9% (302 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 45.3% (305 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 45.5% (306 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 45.6% (307 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 45.6% (307 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 45.8% (308 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 46.1% (310 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 46.4% (312 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 46.7% (314 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 46.8% (315 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 47.1% (317 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 47.1% (317 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 47.4% (319 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 48.2% (324 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 47.9% (322 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 48.2% (324 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 48.2% (324 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 49.5% (333 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 48.9% (329 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 50.1% (337 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 50.2% (338 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 50.0% (336 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 50.4% (339 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 51.6% (347 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 51.1% (344 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 50.8% (342 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 51.1% (344 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 52.5% (353 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 51.7% (348 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 52.8% (355 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 51.9% (349 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 52.3% (352 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 54.4% (366 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 53.7% (361 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 53.8% (362 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 54.9% (369 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 54.4% (366 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 54.7% (368 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 93.8% (631 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/zh_Hant/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 93.8% (631 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/zh_Hant/

* Translated using Weblate (Basque)

Currently translated at 55.8% (375 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 56.8% (382 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 55.9% (376 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 57.7% (388 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 57.7% (388 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 58.9% (396 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 57.8% (389 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 58.1% (391 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 60.4% (406 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 61.0% (410 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 59.5% (400 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 59.9% (403 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 60.7% (408 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 61.0% (410 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 60.8% (409 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 61.7% (415 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 61.1% (411 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 61.0% (410 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 61.9% (416 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 62.6% (421 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 61.3% (412 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 61.7% (415 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 62.0% (417 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 62.2% (418 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 61.9% (416 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 62.2% (418 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 62.3% (419 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 62.3% (419 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 63.2% (425 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 63.3% (426 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 63.3% (426 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 63.5% (427 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 64.4% (433 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 63.9% (430 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 64.8% (436 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 64.8% (436 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 64.5% (434 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 65.7% (442 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 65.0% (437 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 66.2% (445 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 65.9% (443 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 66.2% (445 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 66.3% (446 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 67.1% (451 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 67.8% (456 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 67.5% (454 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 67.5% (454 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 69.7% (469 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 69.6% (468 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 70.0% (471 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 70.2% (472 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 70.5% (474 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Galician)

Currently translated at 93.8% (631 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/gl/

* Translated using Weblate (English (United Kingdom))

Currently translated at 91.3% (614 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/en_GB/

* Translated using Weblate (English (United Kingdom))

Currently translated at 91.3% (614 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/en_GB/

* Translated using Weblate (English (United Kingdom))

Currently translated at 86.4% (581 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/en_GB/

* Translated using Weblate (English)

Currently translated at 99.8% (671 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/en/

* Translated using Weblate (Afrikaans)

Currently translated at 63.6% (428 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/af/

* Translated using Weblate (Bulgarian)

Currently translated at 98.5% (662 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/bg/

* Translated using Weblate (Catalan)

Currently translated at 99.8% (671 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/ca/

* Translated using Weblate (Czech)

Currently translated at 72.1% (485 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Danish)

Currently translated at 94.7% (637 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/da/

* Translated using Weblate (German)

Currently translated at 98.9% (665 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/de/

* Translated using Weblate (Esperanto)

Currently translated at 42.1% (283 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eo/

* Translated using Weblate (English (United Kingdom))

Currently translated at 88.8% (597 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/en_GB/

* Translated using Weblate (Spanish)

Currently translated at 95.6% (643 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/es/

* Translated using Weblate (Spanish (American))

Currently translated at 97.3% (654 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/es_US/

* Translated using Weblate (Spanish)

Currently translated at 95.6% (643 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/es/

* Translated using Weblate (Estonian)

Currently translated at 98.2% (660 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/et/

* Translated using Weblate (Finnish)

Currently translated at 80.6% (542 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fi/

* Translated using Weblate (French)

Currently translated at 100.0% (672 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fr/

* Translated using Weblate (French (Canada))

Currently translated at 93.6% (629 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/fr_CA/

* Translated using Weblate (Galician)

Currently translated at 94.4% (635 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/gl/

* Translated using Weblate (Croatian)

Currently translated at 53.7% (361 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/hr/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (672 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/hu/

* Translated using Weblate (Armenian)

Currently translated at 36.4% (245 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/hy/

* Translated using Weblate (Italian)

Currently translated at 84.8% (570 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/it/

* Translated using Weblate (Japanese)

Currently translated at 70.8% (476 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/ja/

* Translated using Weblate (Kabyle)

Currently translated at 20.5% (138 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/kab/

* Translated using Weblate (Korean)

Currently translated at 52.8% (355 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/ko/

* Translated using Weblate (Norwegian Bokmål)

Currently translated at 73.0% (491 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/nb_NO/

* Translated using Weblate (Dutch)

Currently translated at 86.7% (583 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/nl/

* Translated using Weblate (Occitan)

Currently translated at 99.8% (671 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/oc/

* Translated using Weblate (Polish)

Currently translated at 90.3% (607 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/pl/

* Translated using Weblate (Occitan)

Currently translated at 99.8% (671 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/oc/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.1% (666 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/pt_BR/

* Translated using Weblate (Russian)

Currently translated at 97.9% (658 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/ru/

* Translated using Weblate (Slovak)

Currently translated at 19.6% (132 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sk/

* Translated using Weblate (Slovenian)

Currently translated at 14.8% (100 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sl/

* Translated using Weblate (Swedish)

Currently translated at 93.4% (628 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sv/

* Translated using Weblate (Turkish)

Currently translated at 48.3% (325 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/tr/

* Translated using Weblate (Turkish)

Currently translated at 48.3% (325 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/tr/

* Translated using Weblate (Vietnamese)

Currently translated at 82.2% (553 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/vi/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 85.2% (573 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/zh_Hans/

* Translated using Weblate (Catalan)

Currently translated at 100.0% (32 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/ca/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (672 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/zh_Hant/

* Translated using Weblate (German)

Currently translated at 100.0% (32 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/de/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (32 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/es/

* Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (32 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/en_GB/

* Translated using Weblate (French)

Currently translated at 100.0% (32 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/fr/

* Translated using Weblate (Finnish)

Currently translated at 100.0% (32 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/fi/

* Translated using Weblate (French (Canada))

Currently translated at 100.0% (32 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/fr_CA/

* Translated using Weblate (Italian)

Currently translated at 100.0% (32 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/it/

* Translated using Weblate (Italian)

Currently translated at 100.0% (32 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/it/

* Translated using Weblate (Galician)

Currently translated at 100.0% (32 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/gl/

* Translated using Weblate (Turkish)

Currently translated at 100.0% (32 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/tr/

* Translated using Weblate (Norwegian Bokmål)

Currently translated at 56.2% (18 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/nb_NO/

* Translated using Weblate (Occitan)

Currently translated at 100.0% (32 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/oc/

* Translated using Weblate (Swedish)

Currently translated at 100.0% (32 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/sv/

* Translated using Weblate (Icelandic)

Currently translated at 100.0% (672 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/is/

* Translated using Weblate (Sardinian)

Currently translated at 99.1% (666 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sc/

* Translated using Weblate (Ukrainian)

Currently translated at 97.9% (658 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/uk/

* Translated using Weblate (Belarusian)

Currently translated at 95.0% (639 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/be/

* Translated using Weblate (Basque)

Currently translated at 74.1% (498 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (English (United Kingdom))

Currently translated at 89.2% (600 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/en_GB/

* Translated using Weblate (Basque)

Currently translated at 86.1% (579 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

* Translated using Weblate (Basque)

Currently translated at 87.5% (588 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/eu/

Co-authored-by: anonymous <noreply@weblate.org>
Co-authored-by: Jeannette L <j.lavoie@net-c.ca>
Co-authored-by: Artem <KovalevArtem.ru@gmail.com>
Co-authored-by: Gyuris Gellért <bubu@ujevangelizacio.hu>
Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Co-authored-by: Leif-Jöran Olsson <info@friprogramvarusyndikatet.se>
Co-authored-by: khalasa47 <khalash@protonmail.com>
Co-authored-by: BiziA <adrianpena.hf@gmail.com>
Co-authored-by: Osoitz <oelkoro@gmail.com>
Co-authored-by: 麋悟BigELK176 <bigelk176@gmail.com>
Co-authored-by: Iñigo Zendegi Urzelai <izendegi@gmail.com>
Co-authored-by: Ciarán Ainsworth <ciaranainsworth@posteo.net>
Co-authored-by: BMN <weblate@yopmail.com>
Co-authored-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com>
Co-authored-by: Xosé M <xosem@disroot.org>
Co-authored-by: Quentin PAGÈS <quentinantonin@free.fr>
Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
Co-authored-by: Joan Montané <joan@montane.cat>
2020-04-29 10:15:22 -05:00
Daniil Gentili
be2d20e20e doc: fix echo when running with sudo 2020-04-29 14:57:21 +02:00
Potecaru Tudor
fd11c36bc3 fix: guard for cases where user hits leave before being connected to the room
Co-authored-by: Tudor-Ovidiu Avram <tudor.potecaru@8x8.com>
2020-04-29 14:52:44 +02:00
Saúl Ibarra Corretgé
60148b6439 interface_config: add trailing commas and end marker 2020-04-29 13:07:55 +02:00
Saúl Ibarra Corretgé
62b4c97423 rn: raise SDK version to 2.8.1 2020-04-29 11:44:17 +02:00
Saúl Ibarra Corretgé
f08fa1e374 deps: update lib-jitsi-meet 2020-04-29 11:33:42 +02:00
Saúl Ibarra Corretgé
e5b563ba46 rn,flags: add more feature flags to toggle specific behavior
- Invite funcionality (altogether)
- Recording
- Live streaming
- Meeting name
- Meeting password
2020-04-29 10:19:17 +02:00
Pablo Espinosa
c41047344f lang: fixes for Spanish translation 2020-04-29 10:04:49 +02:00
Saúl Ibarra Corretgé
6ae148403d misc: drop the pre-commit hook
GH Actions now runs the linter.
2020-04-28 17:43:11 +02:00
Jaya Allamsetty
b5676c3729 feat(video-quality):control sender resolution based on user pref 2020-04-28 10:17:06 -04:00
drimovecz
3ab6b97b8b Added module for filtering transcription requests from presence stanz… (#6404)
* Added module for filtering transcription requests from presence stanzas when the users making the requests do not have access to the transcription feature

* Add comments explaining the functionality and configuration for the transcription filtering module.

Co-authored-by: drimovecz <daniel.rimovecz@8x8.com>
2020-04-28 09:11:58 -05:00
Saúl Ibarra Corretgé
5ea8e198c7 e2ee: add label if all participants have E2EE enabled 2020-04-28 16:11:39 +02:00
Saúl Ibarra Corretgé
2ad6bfbc20 e2ee: broadcast e2ee enabled status using presnce 2020-04-28 16:11:39 +02:00
Saúl Ibarra Corretgé
6ce27ef10d misc: set worker names 2020-04-28 12:02:58 +02:00
Ricardo Santana
93ef8495ca fix locale detect error on mobile apps (#5956) 2020-04-27 17:38:57 +02:00
Hristo Terezov
94a15914d0 fix(document.title): use URL decoded room name. 2020-04-25 10:27:47 -05:00
Hristo Terezov
851976ebdf fix(RemoteVideo): .oncanplay -> addEventListener
Replaces the .oncanplay listener with addEventListener('canplay', ...).
This is needed because third party libraries (for example callstats)
are brutally overriding the .oncanplay property and replacing our
listener.
2020-04-24 16:04:32 -05:00
Ruben Kerkhof
57bb2ead36 Conference timer should start counting at 0
It's starting at 1 hour because os.time(os.date("!*t") returns the wrong
time depending on system timezone. os.time() already returns the number
of seconds since epoch in UTC so just use that.

Fixes #5595
2020-04-23 10:22:02 -05:00
Saúl Ibarra Corretgé
027c6ddad0 fastlane,ios: make contact information configurable 2020-04-23 12:43:59 +02:00
Emil Ivov
8648a5a998 Redirect security section to jitsi.org/security 2020-04-22 12:58:18 -05:00
Julian1203
c83b30558d lang: fixes for German 2020-04-22 15:44:09 +02:00
Julian1203
057dfc8194 lang: fixes for German 2020-04-22 15:42:18 +02:00
Fabian Rodriguez
5eae0b58e9 lang: fixes for Spanish (US) 2020-04-22 15:40:57 +02:00
Fabian Rodriguez
1538107e93 lang: fixes for Spanish translation 2020-04-22 15:28:46 +02:00
Bettenbuk Zoltan
cd1862a2d3 fix: private message open 2020-04-22 12:09:07 +02:00
Eduard Itrich
147a076f5d doc: fixed typo in port number of jicofo 2020-04-22 10:57:34 +02:00
Hristo Terezov
9bdaea4069 fix(avatar): use text instead of foreign object.
Reason: On Safari the foreign object is not scaled correctly.
2020-04-21 10:12:51 -05:00
Jonathan Scholz
547d1547bb fix(dialog): use height behavior in KeyboardAvoidingView 2020-04-21 15:13:08 +02:00
Jonathan Scholz
39853e048b fix(dialog): fix on-screen keyboard overlapping dialog boxes 2020-04-21 15:13:08 +02:00
Saúl Ibarra Corretgé
8b454b5196 deps: update lib-jitsi-meet
f97c37d0 e2ee: also enable on p2p connections
a832b39b fix(safari): construct track constraints from getSettings (#1104)
2020-04-21 15:05:40 +02:00
Saúl Ibarra Corretgé
e2788e0fb2 e2ee: show warning if not all participants support E2EE
Refs: https://github.com/jitsi/lib-jitsi-meet/pull/1108
2020-04-21 13:41:05 +02:00
Titus-Andrei Moldovan
b1d1599a1c android: add a consistent deviceId for Amplitude from SharedPreferences 2020-04-21 11:45:42 +02:00
Saúl Ibarra Corretgé
cef98f457f ios: bump CocoaPods dependency 2020-04-21 09:58:24 +02:00
Andrei Gavrilescu
6b0e8aab11 bugfix(remote-control): Remote control not working on linux 2020-04-21 10:33:25 +03:00
Jaya Allamsetty
086889ed70 deps: update lib-jitsi-meet 2020-04-20 18:05:49 -04:00
Saúl Ibarra Corretgé
516e5af118 doc: update supported platforms for building mobile apps 2020-04-20 20:25:24 +02:00
Saúl Ibarra Corretgé
afe1b4b0f9 rn: now working on 20.3 2020-04-20 16:01:25 +02:00
Saúl Ibarra Corretgé
8790ad6013 misc: update GH issue templates
- Use config.yml to prevent creating issues with a blank template
- Don't use a template to direct people to the forum
- Create a security policy template
2020-04-20 15:06:57 +02:00
antonbks
8bbc04d4db doc: fix dev server backend default 2020-04-20 14:02:23 +02:00
Hristo Terezov
4fda428be1 fix(largeVideo): update don't depend on thumbnails 2020-04-17 15:33:13 -05:00
Hristo Terezov
f972ebfe9e fix(thumbnail): videos on safari. 2020-04-17 13:15:25 -05:00
Jaya Allamsetty
3dfcc8d80e deps(ljm): Bump lib-jitsi-meet for Firefox ESR simulcast fix 2020-04-16 21:07:22 -04:00
Saúl Ibarra Corretgé
33ebd241a9 external_api: add command to set E2EE key 2020-04-16 20:25:56 +02:00
Saúl Ibarra Corretgé
cb6fbb0f03 e2ee: add UI elements
* Add dialog to set the E2EE key
* Use the Redux action / middleware to update the key even when set through the
  hash parameter
* Cleanup URL after processing the key so it's not recorded in browser history
2020-04-16 20:25:56 +02:00
Philipp Hancke
0077ee29c5 deps: bump lib-jitsi-meet
Changelog:
101fecbb Thu Apr 16 11:23:58 2020 +0200 Philipp Hancke: e2ee: decode static black frame for decryption errors (#1098)
c3fd3431 Thu Apr 16 13:09:18 2020 +0200 Philipp Hancke: e2ee: remove encodedFrameType workaround (#1099)

git log --no-merges --reverse --pretty="%h %ad %an: %s" 70a3298914f3905297e4e9dcc200b95e9b7a73e9..c3fd3431a66556de7b2ec7632f9f6d75b64aad0a
2020-04-16 17:20:08 +02:00
Bettenbuk Zoltan
551db30cc7 fix: modal keyboard avoiding view fix 2020-04-16 15:30:01 +02:00
Philipp Hancke
1bd930a3cb deps: update lib-jitsi-meet
Changelog:
6502bc67 Wed Apr 15 10:51:35 2020 +0200 Philipp Hancke: e2ee: generate silence in case of audio decryption errors
adc87bcf Mon Apr 6 15:07:48 2020 -0500 paweldomas: fix(strophe.jingle.js): exception on ICE config modification
2020-04-15 21:24:33 +02:00
Philipp Hancke
169906f4cb dev: add npmrc with package-lock set to true
adds a .npmrc file to create/update the package-lock.json file regardless
of a developers local settings.
2020-04-15 20:57:05 +02:00
Jaya Allamsetty
e0563a743f Revert "feat(browser-support): Add safari to list of optimal browsers"
This reverts commit 4824c8714a.
2020-04-15 11:24:04 -05:00
Saúl Ibarra Corretgé
a4ab7ea95f deps: upddate lib-jitsi-meet 2020-04-15 11:04:23 -05:00
Vlad Piersec
b50d6e43d0 fix(settings_buttons): Persist audio/video settings across sessions. 2020-04-15 08:33:19 -05:00
Saúl Ibarra Corretgé
f9fcb46036 pip: disable PiP on Android < 26
Fixes: https://github.com/jitsi/jitsi-meet/issues/6008
2020-04-15 12:12:58 +02:00
Jaya Allamsetty
4824c8714a feat(browser-support): Add safari to list of optimal browsers 2020-04-14 13:42:27 -04:00
damencho
be56521267 debian: Skips deploy-hook when there is no hook available. 2020-04-14 11:54:58 -05:00
Jaya Allamsetty
b7eda8df7a fix(safari): set playsInline attribute to true on the video element
The playsInline attribute needs to be set to true for video to be rendered on Safari on iOS
2020-04-14 12:28:09 -04:00
Jaya Allamsetty
d632b6e13e deps: Update ljm for FF simulcast, js-utils for detecting Edge on Android 2020-04-14 11:07:09 -04:00
Bettenbuk Zoltan
dff7d661ca doc: add documentation to some url params 2020-04-14 16:05:04 +02:00
Julian1203
edb8ecd542 Update main-de.json (#5905)
The word "Weitere" implied that there are already people in the meeting so I replaced it with "andere". 
I also made line 775 gender-neutral as "der Einzige" would technically only refer to males which isn't an unusual thing to do but some people might consider it discriminatory against women.
2020-04-11 12:31:36 -05:00
Mantas Kriaučiūnas
b64112432d Add Lithuanian (lt) translation (#5903)
* Add Lithuanian (lt) language

Add Lithuanian (lt) language

* Added Lithuanian translation

Add Lithuanian translation by Mantas Kriaučiūnas (Baltix) and Raminta Stasaitytė

* Dropping by  damencho request
2020-04-11 12:30:19 -05:00
Daniel Ortega
d8963bc903 Fixing wrong text at key "done" in main-es.json (#5900) 2020-04-11 11:33:14 -05:00
Julian1203
5c39a2f6a6 Update main-de.json (#5895)
Fixed same mistake again as it was in there twice, also made the phrase a bit shorter as otherwise it wouldn't fit in the screen.
Changed "Wollen" to "Möchten" as it's more polite.
2020-04-11 09:32:04 -05:00
Daniel Ortega
a72928a9e7 Adding Spanish translation of "Hebrew" literal (#5893)
* Adding Spanish translation of "Hebrew" literal

* Adding Spanish translation (esUS) of "Hebrew" literal
2020-04-11 09:00:45 -05:00
devSJR
e2ea26eb1f Update main-de.json (#5892)
sie -> Sie
ihre -> Ihre
100% -> 100 %
2020-04-11 08:59:31 -05:00
Saúl Ibarra Corretgé
9962a2ea61 config: whitelist disableSimulcast 2020-04-11 11:37:02 +02:00
Hristo Terezov
07e203ce8d fix(youtube-policy-links): Alignment. 2020-04-10 17:55:50 -05:00
yanas
638fdf0370 Revert "Improve accessibility of Buttons in Webapp (#5432)"
This reverts commit 953f838a2a.
2020-04-10 16:12:21 -05:00
Hristo Terezov
6ce1eaba24 feat(old-electron-app-notification): Implement
Detects if Jitsi Meet is running in old jitsi-meet-electron app and
warns the user for scurity issues.
2020-04-10 14:39:31 -05:00
ferdibayrak
4780e48be8 Update main-tr.json (#5876)
Hello. I am an iOS developer. Jitsi's Turkish translation is now 100% completed. Please update the translation file.
2020-04-10 14:37:05 -05:00
Jaya Allamsetty
7776f0a98c deps(ljm): Update ljm, add safari support and disable simulcast on Firefox 2020-04-10 14:31:06 -04:00
Julian1203
2eede7e76b Update main-de.json (#5873)
Fixed very small mistake in the programming. I don't need to sign the CLA for this, do I?
2020-04-10 13:03:58 -05:00
adrmzz
72a7bd0a68 Adding Sardinian translation (#5386)
* Create main-sc.json

* Create languages-sc.json

* Update languages.json

* Update main-sc.json

(just a couple of minor edits to the translation)
2020-04-10 13:03:26 -05:00
Selyan Slimane Amiri
9085cbf363 Update languages-kab.json (#5871) 2020-04-10 12:22:18 -05:00
Nicolas
be80f26086 Update main-ru.json (#5861)
+lonelyMeetingExperience for russian
2020-04-10 12:19:59 -05:00
Neil Brown
a876f78fd7 Update quick-install.md (#5819)
Add information about firewall ports.
2020-04-10 12:19:39 -05:00
Pierre Pronchery
73d948d150 Also ship robots.txt in the source package (#5811) 2020-04-10 12:19:11 -05:00
Philippe Jtreize
c5aa555816 lang: translation improvements and corrections for French (#5807) 2020-04-10 12:18:43 -05:00
Peter Martin
7902223f09 lang: add Dutch (NL) translation (#5804)
* lang: add Dutch (NL) translation

* lang: add Dutch (NL) translation - fix
2020-04-10 12:18:07 -05:00
Hanno Böck
ac117cd50d Update browser links to HTTPS (#5788)
* Update recommended browser links to https

* Update browser URLs to https
2020-04-10 12:17:10 -05:00
Jens-Christian Fischer
f2df5906f6 Document a scalable installation with multiple videobridges (#5783) 2020-04-10 12:16:18 -05:00
Vyacheslav
0fcecaf18f fix Russian translation (#5746)
Co-authored-by: vbukharin <buhv@skbkontur.ru>
2020-04-10 12:13:34 -05:00
yamakz5555
8cc4b73722 Issue #5741 (#5742)
Japanese mistranslation in speaker stats screen.
2020-04-10 12:13:14 -05:00
Joris Bodin
c08f5c7e18 Fix french (#5721) 2020-04-10 12:13:00 -05:00
Daniel Ortega
2e0f3ae84f Using "Japonés" instead of "Jopones" (#5715) 2020-04-10 12:12:46 -05:00
Marco Manenti
41bfb4c7ec Update main-it.json (#5688)
* Update main-it.json

Some revision

* Update main-it.json

other language revision
2020-04-10 12:12:31 -05:00
Stav Levi
4a12cdfac7 Add Lang Hebrew (#5662)
* Update languages.json

* Create main-he.json
2020-04-10 12:07:12 -05:00
Neil Brown
7b34fb89d1 Update quick-install.md (#5658)
Clarify that a Let’s Encrypt cert is sufficient for iOS and Android clients.
2020-04-10 12:06:40 -05:00
Felix Wolfsteller
4ec438d3f3 i18n: german, fix translation key. (#5657) 2020-04-10 12:06:16 -05:00
Khatanbaatar
e79633b0ca translated Mongolian language (#5646)
* translated Mongolia language

* app translated Mongolian language

* sorry, lint not checked

* lint checked
2020-04-10 12:04:48 -05:00
Ricardo Simões
49a9934c41 Added Portuguese European (Portugal) pt language (#5642)
* Create main-pt.json

Started Portuguese European pt-PT translation

* Created Portuguese European Language pt

Created Portuguese European Language (pt-PT) Portugal
2020-04-10 12:04:09 -05:00
Christian Gräfe
193d19ce21 Update main-de.json (#5634)
simple Typo
2020-04-10 12:03:18 -05:00
Claudius Ellsel
fe83d87d2d Tiny correction in README (#5582) 2020-04-10 12:03:02 -05:00
Julian1203
b4a2327264 Update main-de.json (#5564)
Just checked and Firefox calls the button "Erlauben" in their official German translation while Chrome, Chrome on Android and Opera call it "Zulassen".
"Host" should now be translated consistently
Added two hyphens because "meeting password" is one word in German
2020-04-10 12:00:59 -05:00
MilanKral
d9edf661dd lang: Slovak translation (#5523) 2020-04-10 12:00:26 -05:00
Marco Zehe
e32f367b0c React Native accessibility fixes (#5825)
* Accessibility: Make the native toolbox item communicate that it is a button.

* Accessibility: If an item is toggled, mark it as selected for accessibility

* Accessibility: Make the toolbox a toolbar for accessibility

* Accessibility: Mark the bottom sheet as a menu for accessibility

* Fix typo, AccessibilityRole, not AccessibleRole

* Statement fix

* Appease the linter

* Fix linting errors for real this time
2020-04-10 08:07:48 -05:00
Volker Braun
2b181673b5 android: arcel the serverURL in the Android SDK
In the Android SDK, the setServerURL option is erroneously
ignored. The meeting's serverURL always defaults to
https://meet.jit.si because the serverURL is not parceled.
2020-04-10 14:53:47 +02:00
Emil Ivov
87a058eaa4 Merge pull request #5838 from jitsi/project-hps
Project HiPS, first pass
2020-04-10 07:44:38 -05:00
Saúl Ibarra Corretgé
eef0f5ed97 Project HPS, first pass 2020-04-10 14:40:58 +02:00
Saúl Ibarra Corretgé
1751fc7635 deps: lib-jitsi-meet@latest 2020-04-10 14:40:58 +02:00
pan93412
4aa58f041f i18n: zh_TW: new translation (#5827)
* i18n: zh_TW: new translation

* Delete strings.xml

* Delete strings.xml
2020-04-09 22:27:56 -05:00
Bettenbuk Zoltan
39d789a088 feat: add url params: config.disableInviteFunctions, config.doNotStoreRoom and userInfo.displayName 2020-04-09 17:14:16 +02:00
Peter Martin
2654c77f2c lang: Duch language fixes 2020-04-09 11:29:07 +02:00
Jaya Allamsetty
7af88e5c4f fix(safari): Update the check for Safari
In preparation for the lib-jitsi-meet PR for Safari support, isSafariWithWebrtc() will no longer be available
2020-04-08 15:06:29 -04:00
Дамян Минков
ffdd4f2eed debian: updates around coturn package and order of install (#5729)
* debian: Update coturn udp port to non-privileged one.

* debian: Turnserver config requires jitsi-meet-web-config files.

* doc: Updates doc, removing `--no-install-recommends`.

* debian: Moves checks and configs to default to prosody 0.11.

* debian: Disable room locking on internal muc.

* add scripts for deploying coturn with certbot

* turnserver: Removes unused variable showing error.

* debian: updates let's encrypt and coturn scripts.

* debian: Detect failure to retrieve external ip address.

* debian: Always configure turn when the turnserver package is installed.

Co-authored-by: Julien Fastré <julien.fastre@champs-libres.coop>
2020-04-08 13:06:49 -05:00
Paul Menzel
0b0a19ea5c doc/debian/jitsi-meet-turn: Correct file name to README 2020-04-08 10:59:30 -05:00
Russell Graves
b10aa422ca Add gzip to nginx server config. (#5700)
* Add gzip and expiration to nginx server config.

* Add application/json to gzip_types line to cover translations.

* Add gzip_vary for content caches, remove expires section.

Per discussion, expiration seems likely to cause more confusion than it solves.  Add gzip_vary to prevent content caches from caching un-compressed versions of the content and confusing browsers.
2020-04-07 09:42:27 -05:00
Bettenbuk Zoltan
b706972acb fix: re-add android only chat input padding 2020-04-07 11:18:50 +02:00
Bettenbuk Zoltan
5574221044 ref: SharedDocument to JitsiModal 2020-04-07 11:18:50 +02:00
Bettenbuk Zoltan
0f4369a9a9 ref: AddPeopleDialog to JitsiModal 2020-04-07 11:18:50 +02:00
Bettenbuk Zoltan
0c2e13a453 ref: DialInSummary to JitsiModal 2020-04-07 11:18:50 +02:00
Bettenbuk Zoltan
2f817b6633 ref: Settings to JitsiModal 2020-04-07 11:18:50 +02:00
Bettenbuk Zoltan
678ed605d7 ref: change JitsiModal to better fit to needs 2020-04-07 11:18:50 +02:00
vp8x8
84714ba3bd settings: enable settings buttons on permission grant
Some CSS fixes are also included.
2020-04-07 09:14:23 +02:00
Tim Ruffing
b8963629bf Pass upper case country codes to i18n-iso-countries
Related to #5697.
2020-04-06 22:17:27 -05:00
Damian Goeldi
47cffeb00a add missing IPv6 listener to nginx jitsi module 2020-04-06 21:27:40 -05:00
Paul Mestrum
b70633ef24 tile-view: fix number of columns calculation 2020-04-06 19:42:53 +02:00
Hristo Terezov
145596ac6a fix(tile-view): hidden thumbnails on scroll 2020-04-06 12:22:43 -05:00
moses gunesch
76607bbad8 doc: mention privacy error in Chrome for development 2020-04-06 10:25:13 +02:00
bgrozev
36113fd54f debian: clean up password generation, use 16 characters 2020-04-06 10:22:56 +02:00
Дамян Минков
f86ace17d8 Fix weblate2 (#5695)
* Added translation using Weblate (Icelandic)

* Added translation using Weblate (Icelandic)

* Added translation using Weblate (Sardinian)

* Deleted translation using Weblate (Sardinian)

* Added translation using Weblate (Sardinian)

* Translated using Weblate (Sardinian)

Currently translated at 0.0% (0 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sc/

* Added translation using Weblate (Sardinian)

* Translated using Weblate (Sardinian)

Currently translated at 0.0% (0 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/sc/

* Translated using Weblate (Icelandic)

Currently translated at 100.0% (32 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/is/

* Translated using Weblate (Icelandic)

Currently translated at 100.0% (672 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/is/

* Translated using Weblate (Bulgarian)

Currently translated at 99.8% (671 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/bg/

* Translated using Weblate (Catalan)

Currently translated at 100.0% (672 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/ca/

* Translated using Weblate (Bulgarian)

Currently translated at 99.8% (671 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/bg/

* Translated using Weblate (Czech)

Currently translated at 36.7% (247 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Turkish)

Currently translated at 23.3% (157 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/tr/

* Translated using Weblate (ptbr (generated))

Currently translated at 100.0% (672 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/ptbr/

* Translated using Weblate (Sardinian)

Currently translated at 99.8% (671 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sc/

* Translated using Weblate (Czech)

Currently translated at 39.8% (268 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 46.8% (315 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 46.8% (315 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 46.8% (315 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 47.0% (316 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 47.0% (316 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 50.5% (340 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 50.7% (341 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 50.8% (342 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 52.8% (355 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 72.6% (488 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Turkish)

Currently translated at 100.0% (32 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/tr/

* Translated using Weblate (Danish)

Currently translated at 95.6% (643 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/da/

* Translated using Weblate (Norwegian Bokmål)

Currently translated at 40.6% (13 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/nb_NO/

* Translated using Weblate (Norwegian Bokmål)

Currently translated at 20.8% (140 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/nb_NO/

* Added translation using Weblate (Arabic)

* Added translation using Weblate (Arabic)

* Added translation using Weblate (Serbian)

* Added translation using Weblate (Serbian)

* Added translation using Weblate (Ukrainian)

* Translated using Weblate (Ukrainian)

Currently translated at 96.8% (651 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/uk/

* Translated using Weblate (Ukrainian)

Currently translated at 96.8% (651 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/uk/

* Translated using Weblate (Ukrainian)

Currently translated at 97.0% (652 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/uk/

* Translated using Weblate (Ukrainian)

Currently translated at 97.1% (653 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/uk/

* Translated using Weblate (Ukrainian)

Currently translated at 97.4% (655 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/uk/

* Added translation using Weblate (Belarusian)

* Added translation using Weblate (Romanian)

* Added translation using Weblate (Ukrainian)

Co-authored-by: Sveinn í Felli <sv1@fellsnet.is>
Co-authored-by: Václav Zbránek <vaclav@weblate.org>
Co-authored-by: Joan Montané <joan@montane.cat>
Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
Co-authored-by: Rafael Fontenelle <rafaelff@gnome.org>
Co-authored-by: Adrià Martín <adriamartinmor@gmail.com>
Co-authored-by: Tomas Apeltauer <tomas.apeltauer@gmail.com>
Co-authored-by: anonymous <noreply@weblate.org>
Co-authored-by: Lukáš Jelínek <devel@aiken.cz>
Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Co-authored-by: Ahmed Abdelhamid <dralawady@gmail.com>
Co-authored-by: Nenad Nikolic <nikbit2015@gmail.com>
Co-authored-by: Oleksa Stasevych <oleksiy.stasevych@gmail.com>
Co-authored-by: Антон Костюченко <1292729@gmail.com>
Co-authored-by: marius-bardan <marius.bardan@gmail.com>
2020-04-05 17:24:20 -05:00
Dara Poon
0e16008085 Use regexes to match ALPN protocols (#5651)
nginx presents the client's list of ALPN protocols as
$ssl_preread_alpn_protocols, a comma-separated string.  Use regular
expressions to match each item in the list, rather than the exact value
of the entire list at once.
2020-04-05 09:23:43 -05:00
Дамян Минков
f66a919e08 Fix weblate (#5672)
* Added translation using Weblate (Icelandic)

* Added translation using Weblate (Icelandic)

* Added translation using Weblate (Sardinian)

* Deleted translation using Weblate (Sardinian)

* Added translation using Weblate (Sardinian)

* Translated using Weblate (Sardinian)

Currently translated at 0.0% (0 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sc/

* Added translation using Weblate (Sardinian)

* Translated using Weblate (Sardinian)

Currently translated at 0.0% (0 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/sc/

* Translated using Weblate (Icelandic)

Currently translated at 100.0% (32 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/is/

* Translated using Weblate (Icelandic)

Currently translated at 100.0% (672 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/is/

* Translated using Weblate (Bulgarian)

Currently translated at 99.8% (671 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/bg/

* Translated using Weblate (Catalan)

Currently translated at 100.0% (672 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/ca/

* Translated using Weblate (Bulgarian)

Currently translated at 99.8% (671 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/bg/

* Translated using Weblate (Czech)

Currently translated at 36.7% (247 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Turkish)

Currently translated at 23.3% (157 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/tr/

* Translated using Weblate (ptbr (generated))

Currently translated at 100.0% (672 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/ptbr/

* Translated using Weblate (Sardinian)

Currently translated at 99.8% (671 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/sc/

* Translated using Weblate (Czech)

Currently translated at 39.8% (268 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 46.8% (315 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 46.8% (315 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 46.8% (315 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 47.0% (316 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 47.0% (316 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 50.5% (340 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 50.7% (341 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 50.8% (342 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 52.8% (355 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Czech)

Currently translated at 72.6% (488 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/cs/

* Translated using Weblate (Turkish)

Currently translated at 100.0% (32 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/tr/

* Translated using Weblate (Danish)

Currently translated at 95.6% (643 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/da/

* Translated using Weblate (Norwegian Bokmål)

Currently translated at 40.6% (13 of 32 strings)

Translation: Jitsi/languages
Translate-URL: https://hosted.weblate.org/projects/jitsi/languages/nb_NO/

* Translated using Weblate (Norwegian Bokmål)

Currently translated at 20.8% (140 of 672 strings)

Translation: Jitsi/main
Translate-URL: https://hosted.weblate.org/projects/jitsi/main/nb_NO/

Co-authored-by: Sveinn í Felli <sv1@fellsnet.is>
Co-authored-by: Václav Zbránek <vaclav@weblate.org>
Co-authored-by: Joan Montané <joan@montane.cat>
Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
Co-authored-by: Rafael Fontenelle <rafaelff@gnome.org>
Co-authored-by: Adrià Martín <adriamartinmor@gmail.com>
Co-authored-by: Tomas Apeltauer <tomas.apeltauer@gmail.com>
Co-authored-by: anonymous <noreply@weblate.org>
Co-authored-by: Lukáš Jelínek <devel@aiken.cz>
Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
2020-04-05 08:58:21 -05:00
Saúl Ibarra Corretgé
8115fb5e78 config: remove aspect ratio constraint from config example
Some cameras may not be able to satisfy it and gUM will fail.

Refs: https://github.com/jitsi/lib-jitsi-meet/pull/1066
2020-04-05 08:46:51 +02:00
803 changed files with 33841 additions and 13519 deletions

View File

@@ -4,25 +4,45 @@ about: Create a report to help us improve
---
*This Issue tracker is only for reporting bugs and tracking code related issues.*
<!--
Before posting, please make sure you check community.jitsi.org to see if the same or similar bugs have already been discussed.
General questions, installation help, and feature requests can also be posted to community.jitsi.org.
This issue tracker is only for reporting bugs and tracking issues related to the source code.
## Description
---
Before posting, please make sure to check if the same or similar bugs have already been discussed: https://github.com/jitsi/jitsi-meet/issues
## Current behavior
---
General questions regarding usage, installation, etc. should be posted at https://community.jitsi.org. They will be closed if posted here.
## Expected Behavior
---
-->
## Possible Solution
---
### Description:
## Steps to reproduce
---
<!-- Please describe the bug clearly and concisely. -->
# Environment details
---
### Steps to reproduce:
1. <!-- Open '...' -->
2. <!-- Click on '...' -->
3. <!-- and so on... -->
### Expected behavior:
<!-- Please describe what should happen. -->
### Actual behavior:
<!-- Please describe what actually happens. -->
<!-- Please attach screenshot if possible. -->
### Server information:
- Jitsi Meet version:
- Operating System:
### Client information:
- Browser / app version:
- Operating System:
### Additional information:
<!-- Please provide additional information about the bug, if any. -->

View File

@@ -9,7 +9,7 @@ Thank you for suggesting an idea to make Jitsi Meet better.
Please fill in as much of the template below as you're able.
Note that the ultimate decission for implementing features lies on the Jitsi team, not all feature requests shall be accepted.
Note that the ultimate decision for implementing features lies on the Jitsi team, not all feature requests shall be accepted.
-->
**Is your feature request related to a problem you are facing?**

View File

@@ -1,10 +0,0 @@
---
name: Need help with Jitsi Meet?
about: Please ask it in our community at https://community.jitsi.org
---
If you have a question about Jitsi Meet that is not a bug report or feature
request, please post it in https://community.jitsi.org
Questions posted to this repository will be closed.

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Need help with Jitsi Meet?
url: https://community.jitsi.org
about: Please ask it in our community.

1
.npmrc Normal file
View File

@@ -0,0 +1 @@
package-lock=true

View File

@@ -27,3 +27,99 @@ in the agreement, unfortunately, we cannot accept your contribution.
- Maintain a clean list of commits, squash them if necessary.
- Rebase your topic branch on top of the master branch before creating the pull
request.
## Coding style
### Comments
* Comments documenting the source code are required.
* Comments from which documentation is automatically generated are **not**
subject to case-by-case decisions. Such comments are used, for example, on
types and their members. Examples of tools which automatically generate
documentation from such comments include JSDoc, Javadoc, Doxygen.
* Comments which are not automatically processed are strongly encouraged. They
are subject to case-by-case decisions. Such comments are often observed in
function bodies.
* Comments should be formatted as proper English sentences. Such formatting pays
attention to, for example, capitalization and punctuation.
### Duplication
* Don't copy-paste source code. Reuse it.
### Formatting
* Line length is limited to 120 characters.
* Sort by alphabetical order in order to make the addition of new entities as
easy as looking a word up in a dictionary. Otherwise, one risks duplicate
entries (with conflicting values in the cases of key-value pairs). For
example:
* Within an `import` of multiple names from a module, sort the names in
alphabetical order. (Of course, the default name stays first as required by
the `import` syntax.)
````javascript
import {
DOMINANT_SPEAKER_CHANGED,
JITSI_CLIENT_CONNECTED,
JITSI_CLIENT_CREATED,
JITSI_CLIENT_DISCONNECTED,
JITSI_CLIENT_ERROR,
JITSI_CONFERENCE_JOINED,
MODERATOR_CHANGED,
PEER_JOINED,
PEER_LEFT,
RTC_ERROR
} from './actionTypes';
````
* Within a group of imports (e.g. groups of imports delimited by an empty line
may be: third-party modules, then project modules, and eventually the
private files of a module), sort the module names in alphabetical order.
````javascript
import React, { Component } from 'react';
import { connect } from 'react-redux';
````
### Indentation
* Align `switch` and `case`/`default`. Don't indent the `case`/`default` more
than its `switch`.
````javascript
switch (i) {
case 0:
...
break;
default:
...
}
````
### Naming
* An abstraction should have one name within the project and across multiple
projects. For example:
* The instance of lib-jitsi-meet's `JitsiConnection` type should be named
`connection` or `jitsiConnection` in jitsi-meet, not `client`.
* The class `ReducerRegistry` should be defined in ReducerRegistry.js and its
imports in other files should use the same name. Don't define the class
`Registry` in ReducerRegistry.js and then import it as `Reducers` in other
files.
* The names of global constants (including ES6 module-global constants) should
be written in uppercase with underscores to separate words. For example,
`BACKGROUND_COLOR`.
* The underscore character at the beginning of a name signals that the
respective variable, function, property is non-public i.e. private, protected,
or internal. In contrast, the lack of an underscore at the beginning of a name
signals public API.

View File

@@ -21,6 +21,7 @@ compile:
clean:
rm -fr $(BUILD_DIR)
.NOTPARALLEL:
deploy: deploy-init deploy-appbundle deploy-rnnoise-binary deploy-lib-jitsi-meet deploy-libflac deploy-css deploy-local
deploy-init:
@@ -79,12 +80,13 @@ deploy-css:
deploy-local:
([ ! -x deploy-local.sh ] || ./deploy-local.sh)
.NOTPARALLEL:
dev: deploy-init deploy-css deploy-rnnoise-binary deploy-lib-jitsi-meet deploy-libflac
$(WEBPACK_DEV_SERVER)
source-package:
mkdir -p source_package/jitsi-meet/css && \
cp -r *.js *.html connection_optimization favicon.ico fonts images libs static sounds LICENSE lang source_package/jitsi-meet && \
cp -r *.js *.html resources/*.txt connection_optimization favicon.ico fonts images libs static sounds LICENSE lang source_package/jitsi-meet && \
cp css/all.css source_package/jitsi-meet/css && \
(cd source_package ; tar cjf ../jitsi-meet.tar.bz2 jitsi-meet) && \
rm -rf source_package

View File

@@ -1,8 +1,8 @@
# 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, [secure](#security) and scalable video conferences. Jitsi Meet in action can be seen at [here at the session #482 of the VoIP Users Conference](http://youtu.be/7vFUVClsNh0).
Jitsi Meet is an open-source (Apache) WebRTC JavaScript application that uses [Jitsi Videobridge](https://jitsi.org/videobridge) to provide high quality, [secure](https://jitsi.org/security) and scalable video conferences. Jitsi Meet in action can be seen at [here at the session #482 of the VoIP Users Conference](http://youtu.be/7vFUVClsNh0).
The Jitsi Meet client runs in your browser, without installing anything else on your computer. You can try it out at https://meet.jit.si .
The Jitsi Meet client runs in your browser, without installing anything else on your computer. You can try it out at https://meet.jit.si.
Jitsi Meet allows very efficient collaboration. Users can stream their desktop or only some windows. It also supports shared document editing with Etherpad.
@@ -10,9 +10,11 @@ Jitsi Meet allows very efficient collaboration. Users can stream their desktop o
On the client side, no installation is necessary. You just point your browser to the URL of your deployment. This section is about installing a Jitsi Meet suite on your server and hosting your own conferencing service.
Installing Jitsi Meet is a simple experience. For Debian-based system, following the [quick-install](https://github.com/jitsi/jitsi-meet/blob/master/doc/quick-install.md) document, which uses the package system. You can also see a demonstration of the process in [this tutorial video](https://jitsi.org/tutorial).
Installing Jitsi Meet is a simple experience. For Debian-based system, following the [quick install](https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-quickstart) document, which uses the package system. You can also see a demonstration of the process in [this tutorial video](https://jitsi.org/tutorial).
For other systems, or if you wish to install all components manually, see the [detailed manual installation instructions](https://github.com/jitsi/jitsi-meet/blob/master/doc/manual-install.md).
For other systems, or if you wish to install all components manually, see the [detailed manual installation instructions](https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-manual).
Installation with Docker is also available. Please see the [instruction](https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-docker).
## Download
@@ -46,9 +48,13 @@ You can also sign up for our open beta testing here:
* [Android](https://play.google.com/apps/testing/org.jitsi.meet)
* [iOS](https://testflight.apple.com/join/isy6ja7S)
## Release notes
Release notes for Jitsi Meet are maintained on [this repository](https://github.com/jitsi/jitsi-meet-release-notes).
## Development
For web development see [here](doc/development.md), and for mobile see [here](doc/mobile.md).
For web development see [here](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-web), and for mobile see [here](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-mobile).
## Contributing
@@ -61,25 +67,13 @@ Jitsi Meet provides a very flexible way of embedding in external applications by
## Security
WebRTC does not (yet) provide a way of conducting multi-party conversations with end-to-end encryption.
Unless you consistently compare DTLS fingerprints with your peers vocally, the same goes for one-to-one calls.
As a result, your stream is encrypted on the network but decrypted on the machine that hosts the bridge when using Jitsi Meet.
The security section here was starting to feel a bit too succinct for the complexity of the topic, so we created a post that covers the topic much more broadly here: https://jitsi.org/security
The Jitsi Meet architecture allows you to deploy your own version, including
all server components. In that case, your security guarantees will be roughly
equivalent to a direct one-to-one WebRTC call. This is the uniqueness of
Jitsi Meet in terms of security.
The [meet.jit.si](https://meet.jit.si) service is maintained by the Jitsi team
at [8x8](https://8x8.com).
The section on end-to-end encryption in that document is likely going to be one of the key points of interest: https://jitsi.org/security/#e2ee
## Security issues
We take security very seriously and develop all Jitsi projects to be secure and safe.
If you find (or simply suspect) a security issue in any of the Jitsi projects, please send us an email to security@jitsi.org.
**We encourage responsible disclosure for the sake of our users, so please reach out before posting in a public space.**
For information on reporting security vulnerabilities in Jitsi Meet, see [SECURITY.md](./SECURITY.md).
## Acknowledgements

View File

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

View File

@@ -1,380 +1,3 @@
# Jitsi Meet SDK for Android
## Sample applications using the SDK
If you want to see how easy integrating the Jitsi Meet SDK into a native application is, take a look at the
[sample applications repository](https://github.com/jitsi/jitsi-meet-sdk-samples).
## Build your own, or use a pre-build SDK artifacts/binaries
Jitsi conveniently provides a pre-build SDK artifacts/binaries in its Maven repository. When you do not require any
modification to the SDK itself or any of its dependencies, it's suggested to use the pre-build SDK. This avoids the
complexity of building and installing your own SDK artifacts/binaries.
### Use pre-build SDK artifacts/binaries
In your project, add the Maven repository
`https://github.com/jitsi/jitsi-maven-repository/raw/master/releases` and the
dependency `org.jitsi.react:jitsi-meet-sdk` into your `build.gradle` files.
The repository typically goes into the `build.gradle` file in the root of your project:
```gradle
allprojects {
repositories {
google()
jcenter()
maven {
url "https://github.com/jitsi/jitsi-maven-repository/raw/master/releases"
}
}
}
```
Dependency definitions belong in the individual module `build.gradle` files:
```gradle
dependencies {
// (other dependencies)
implementation ('org.jitsi.react:jitsi-meet-sdk:2.+') { transitive = true }
}
```
### Build and use your own SDK artifacts/binaries
<details>
<summary>Show building instructions</summary>
Start by making sure that your development environment [is set up correctly](https://github.com/jitsi/jitsi-meet/blob/master/doc/mobile.md).
A note on dependencies: Apart from the SDK, Jitsi also publishes a binary Maven artifact for some of the SDK dependencies (that are not otherwise publicly available) to the Jitsi Maven repository. When you're planning to use a SDK that is built from source, you'll likely use a version of the source code that is newer (or at least _different_) than the version of the source that was used to create the binary SDK artifact. As a consequence, the dependencies that your project will need, might also be different from those that are published in the Jitsi Maven repository. This might lead to build problems, caused by dependencies that are unavailable.
If you want to use a SDK that is built from source, you will likely benefit from composing a local Maven repository that contains these dependencies. The text below describes how you create a repository that includes both the SDK as well as these dependencies. For illustration purposes, we'll define the location of this local Maven repository as `/tmp/repo`
In source code form, the Android SDK dependencies are locked/pinned by package.json and package-lock.json of the Jitsi Meet project. To obtain the data, execute NPM in the jitsi-meet project directory:
npm install
This will pull in the dependencies in either binary format, or in source code format, somewhere under /node_modules/
Third-party React Native _modules_, which Jitsi Meet SDK for Android depends on, are download by NPM in source code
or binary form. These need to be assembled into Maven artifacts, and then published to your local Maven repository.
A script is provided to facilitate this. From the root of the jitsi-meet project repository, run:
./android/scripts/release-sdk.sh /tmp/repo
This will build and publish the SDK, and all of its dependencies to the specified Maven repository (`/tmp/repo`) in
this example.
You're now ready to use the artifacts. In _your_ project, add the Maven repository that you used above (`/tmp/repo`) into your top-level `build.gradle` file:
allprojects {
repositories {
maven { url "file:/tmp/repo" }
google()
jcenter()
}
}
You can use your local repository to replace the Jitsi repository (`maven { url "https://github.com/jitsi/jitsi-maven-repository/raw/master/releases" }`) when you published _all_ subprojects. If you didn't do that, you'll have to add both repositories. Make sure your local repository is listed first!
Then, define the dependency `org.jitsi.react:jitsi-meet-sdk` into the `build.gradle` file of your module:
implementation ('org.jitsi.react:jitsi-meet-sdk:+') { transitive = true }
Note that there should not be a need to explicitly add the other dependencies, as they will be pulled in as transitive
dependencies of `jitsi-meet-sdk`.
</details>
## Using the API
Jitsi Meet SDK is an Android library which embodies the whole Jitsi Meet
experience and makes it reusable by third-party apps.
First, add Java 1.8 compatibility support to your project by adding the
following lines into your `build.gradle` file:
```
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
```
To get started, extends your `android.app.Activity` from
`org.jitsi.meet.sdk.JitsiMeetActivity`:
```java
package org.jitsi.example;
import org.jitsi.meet.sdk.JitsiMeetActivity;
public class MainActivity extends JitsiMeetActivity {
}
```
Alternatively, you can use the `org.jitsi.meet.sdk.JitsiMeetView` class which
extends `android.view.View`.
Note that this should only be needed when `JitsiMeetActivity` cannot be used for
some reason. Extending `JitsiMeetView` requires manual wiring of the view to
the activity, using a lot of boilerplate code. Using the Activity instead of the
View is strongly recommended.
<details>
<summary>Show example</summary>
```java
package org.jitsi.example;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import org.jitsi.meet.sdk.JitsiMeetView;
import org.jitsi.meet.sdk.ReactActivityLifecycleCallbacks;
// Example
//
public class MainActivity extends FragmentActivity implements JitsiMeetActivityInterface {
private JitsiMeetView view;
@Override
protected void onActivityResult(
int requestCode,
int resultCode,
Intent data) {
JitsiMeetActivityDelegate.onActivityResult(
this, requestCode, resultCode, data);
}
@Override
public void onBackPressed() {
JitsiMeetActivityDelegate.onBackPressed();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
view = new JitsiMeetView(this);
JitsiMeetConferenceOptions options = new JitsiMeetConferenceOptions.Builder()
.setRoom("https://meet.jit.si/test123")
.build();
view.join(options);
setContentView(view);
}
@Override
protected void onDestroy() {
super.onDestroy();
view.dispose();
view = null;
JitsiMeetActivityDelegate.onHostDestroy(this);
}
@Override
public void onNewIntent(Intent intent) {
JitsiMeetActivityDelegate.onNewIntent(intent);
}
@Override
public void onRequestPermissionsResult(
final int requestCode,
final String[] permissions,
final int[] grantResults) {
JitsiMeetActivityDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
protected void onResume() {
super.onResume();
JitsiMeetActivityDelegate.onHostResume(this);
}
@Override
protected void onStop() {
super.onStop();
JitsiMeetActivityDelegate.onHostPause(this);
}
}
```
</details>
### JitsiMeetActivity
This class encapsulates a high level API in the form of an Android `FragmentActivity`
which displays a single `JitsiMeetView`. You can pass a URL as a `ACTION_VIEW`
on the Intent when starting it and it will join the conference, and will be
automatically terminated (finish() will be called on the activity) when the
conference ends or fails.
### JitsiMeetView
The `JitsiMeetView` class is the core of Jitsi Meet SDK. It's designed to
display a Jitsi Meet conference (or a welcome page).
#### join(options)
Joins the conference specified by the given `JitsiMeetConferenceOptions`.
#### leave()
Leaves the currently active conference. If the welcome page is enabled it will
go back to it, otherwise a black window will be shown.
#### dispose()
Releases all resources associated with this view. This method MUST be called
when the Activity holding this view is going to be destroyed, usually in the
`onDestroy()` method.
#### getListener()
Returns the `JitsiMeetViewListener` instance attached to the view.
#### setListener(listener)
Sets the given listener (class implementing the `JitsiMeetViewListener`
interface) on the view.
### JitsiMeetConferenceOptions
This object encapsulates all the options that can be tweaked when joining
a conference.
Example:
```java
JitsiMeetConferenceOptions options = new JitsiMeetConferenceOptions.Builder()
.setServerURL(new URL("https://meet.jit.si"))
.setRoom("test123")
.setAudioMuted(false)
.setVideoMuted(false)
.setAudioOnly(false)
.setWelcomePageEnabled(false)
.build();
```
See the `JitsiMeetConferenceOptions` implementation for all available options.
### JitsiMeetActivityDelegate
This class handles the interaction between `JitsiMeetView` and its enclosing
`Activity`. Generally this shouldn't be consumed by users, because they'd be
using `JitsiMeetActivity` instead, which is already completely integrated.
All its methods are static.
#### onActivityResult(...)
Helper method to handle results of auxiliary activities launched by the SDK.
Should be called from the activity method of the same name.
#### onBackPressed()
Helper method which should be called from the activity's `onBackPressed` method.
If this function returns `true`, it means the action was handled and thus no
extra processing is required; otherwise the app should call the parent's
`onBackPressed` method.
#### onHostDestroy(...)
Helper method which should be called from the activity's `onDestroy` method.
#### onHostResume(...)
Helper method which should be called from the activity's `onResume` or `onStop`
method.
#### onHostStop(...)
Helper method which should be called from the activity's `onSstop` method.
#### onNewIntent(...)
Helper method for integrating the *deep linking* functionality. If your app's
activity is launched in "singleTask" mode this method should be called from the
activity's `onNewIntent` method.
#### onRequestPermissionsResult(...)
Helper method to handle permission requests inside the SDK. It should be called
from the activity method of the same name.
#### onUserLeaveHint()
Helper method for integrating automatic Picture-in-Picture. It should be called
from the activity's `onUserLeaveHint` method.
This is a static method.
#### JitsiMeetViewListener
`JitsiMeetViewListener` provides an interface apps can implement to listen to
the state of the Jitsi Meet conference displayed in a `JitsiMeetView`.
#### onConferenceJoined
Called when a conference was joined.
The `data` `Map` contains a "url" key with the conference URL.
#### onConferenceTerminated
Called when a conference was terminated either by user choice or due to a
failure.
The `data` `Map` contains an "error" key with the error and a "url" key
with the conference URL. If the conference finished gracefully no `error`
key will be present.
#### onConferenceWillJoin
Called before a conference is joined.
The `data` `Map` contains a "url" key with the conference URL.
## ProGuard rules
When using the SDK on a project some proguard rules have to be added in order
to avoid necessary code being stripped. Add the following to your project's
rules file: https://github.com/jitsi/jitsi-meet/blob/master/android/app/proguard-rules.pro
## Picture-in-Picture
`JitsiMeetView` will automatically adjust its UI when presented in a
Picture-in-Picture style scenario, in a rectangle too small to accommodate its
"full" UI.
## Dropbox integration
To setup the Dropbox integration, follow these steps:
1. Add the following to the app's AndroidManifest.xml and change `<APP_KEY>` to
your Dropbox app key:
```
<activity
android:configChanges="keyboard|orientation"
android:launchMode="singleTask"
android:name="com.dropbox.core.android.AuthActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="db-<APP_KEY>" />
</intent-filter>
</activity>
```
2. Add the following to the app's strings.xml and change `<APP_KEY>` to your
Dropbox app key:
```
<string name="dropbox_app_key"><APP_KEY></string>
```
This document has been moved to [The Handbook](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-android-sdk).

View File

@@ -1,8 +1,5 @@
apply plugin: 'com.android.application'
boolean googleServicesEnabled \
= project.file('google-services.json').exists() && !rootProject.ext.libreBuild
// Crashlytics integration is done as part of Firebase now, so it gets
// automagically activated with google-services.json
if (googleServicesEnabled) {
@@ -13,7 +10,7 @@ if (googleServicesEnabled) {
// This lets us upload a new build at most every 10 seconds for the
// next ~680 years.
// https://stackoverflow.com/a/38643838
def vcode = (int)(((new Date().getTime()/1000) - 1546297200) / 10)
def vcode = (int) (((new Date().getTime() / 1000) - 1546297200) / 10)
android {
compileSdkVersion rootProject.ext.compileSdkVersion
@@ -143,8 +140,8 @@ gradle.projectsEvaluated {
def targetName = variant.name.capitalize()
def currentRunPackagerTask = tasks.create(
name: "run${targetName}ReactPackager",
type: Exec) {
name: "run${targetName}ReactPackager",
type: Exec) {
group = "react"
description = "Run the React packager."
@@ -175,5 +172,5 @@ gradle.projectsEvaluated {
}
if (googleServicesEnabled) {
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.gms.google-services'
}

View File

@@ -7,6 +7,7 @@ import com.crashlytics.android.Crashlytics;
import com.google.firebase.dynamiclinks.FirebaseDynamicLinks;
import io.fabric.sdk.android.Fabric;
import org.jitsi.meet.sdk.JitsiMeet;
import org.jitsi.meet.sdk.JitsiMeetActivity;
/**
@@ -21,7 +22,9 @@ final class GoogleServicesHelper {
if (BuildConfig.GOOGLE_SERVICES_ENABLED) {
Log.d(activity.getClass().getSimpleName(), "Initializing Google Services");
Fabric.with(activity, new Crashlytics());
if (!JitsiMeet.isCrashReportingDisabled(activity)) {
Fabric.with(activity, new Crashlytics());
}
FirebaseDynamicLinks.getInstance().getDynamicLink(activity.getIntent())
.addOnSuccessListener(activity, pendingDynamicLinkData -> {

View File

@@ -161,6 +161,8 @@ ext {
// Libre build
libreBuild = (System.env.LIBRE_BUILD ?: "false").toBoolean()
googleServicesEnabled = project.file('app/google-services.json').exists() && !libreBuild
}
// Force the version of the Android build tools we have chosen on all

View File

@@ -20,5 +20,5 @@
android.useAndroidX=true
android.enableJetifier=true
appVersion=20.2.0
sdkVersion=2.8.0
appVersion=20.3.0
sdkVersion=2.9.0

View File

@@ -14,11 +14,13 @@ android {
buildTypes {
debug {
buildConfigField "boolean", "LIBRE_BUILD", "${rootProject.ext.libreBuild}"
buildConfigField "boolean", "GOOGLE_SERVICES_ENABLED", "${rootProject.ext.googleServicesEnabled}"
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField "boolean", "LIBRE_BUILD", "${rootProject.ext.libreBuild}"
buildConfigField "boolean", "GOOGLE_SERVICES_ENABLED", "${rootProject.ext.googleServicesEnabled}"
}
}
@@ -70,6 +72,7 @@ dependencies {
implementation project(':react-native-calendar-events')
implementation project(':react-native-community-async-storage')
implementation project(':react-native-community_netinfo')
implementation project(':react-native-default-preference')
implementation project(':react-native-immersive')
implementation project(':react-native-keep-awake')
implementation project(':react-native-linear-gradient')

View File

@@ -17,6 +17,8 @@
package org.jitsi.meet.sdk;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.provider.Settings;
import android.text.TextUtils;
@@ -40,6 +42,8 @@ class AmplitudeModule
extends ReactContextBaseJavaModule {
public static final String NAME = "Amplitude";
public static final String JITSI_PREFERENCES = "jitsi-preferences";
public static final String AMPLITUDE_DEVICE_ID_KEY = "amplitudeDeviceId";
public AmplitudeModule(ReactApplicationContext reactContext) {
super(reactContext);
@@ -58,10 +62,14 @@ class AmplitudeModule
Amplitude.getInstance(instanceName).initialize(getCurrentActivity(), apiKey);
// Set the device ID to something consistent.
String android_id
= Settings.Secure.getString(getReactApplicationContext().getContentResolver(), Settings.Secure.ANDROID_ID);
SharedPreferences sharedPreferences = getReactApplicationContext().getSharedPreferences(JITSI_PREFERENCES, Context.MODE_PRIVATE);
String android_id = sharedPreferences.getString(AMPLITUDE_DEVICE_ID_KEY, "");
if (!TextUtils.isEmpty(android_id)) {
Amplitude.getInstance(instanceName).setDeviceId(android_id);
} else {
String amplitudeId = Amplitude.getInstance(instanceName).getDeviceId();
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(JITSI_PREFERENCES, amplitudeId).apply();
}
}

View File

@@ -76,6 +76,7 @@ class AppInfoModule
"version",
packageInfo == null ? "" : packageInfo.versionName);
constants.put("LIBRE_BUILD", BuildConfig.LIBRE_BUILD);
constants.put("GOOGLE_SERVICES_ENABLED", BuildConfig.GOOGLE_SERVICES_ENABLED);
return constants;
}

View File

@@ -16,11 +16,14 @@
*/
package org.jitsi.meet.sdk;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import com.facebook.react.ReactInstanceManager;
public class JitsiMeet {
/**
* Default {@link JitsiMeetConferenceOptions} which will be used for all conferences. When
* joining a conference these options will be merged with the ones passed to
@@ -72,4 +75,10 @@ public class JitsiMeet {
reactInstanceManager.showDevOptionsDialog();
}
}
}
public static boolean isCrashReportingDisabled(Context context) {
SharedPreferences preferences = context.getSharedPreferences("jitsi-default-preferences", Context.MODE_PRIVATE);
String value = preferences.getString("isCrashReportingDisabled", "");
return Boolean.parseBoolean(value);
}
}

View File

@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
@@ -67,6 +68,9 @@ public class JitsiMeetActivity extends FragmentActivity
setContentView(R.layout.activity_jitsi_meet);
// Listen for conference events.
getJitsiView().setListener(this);
if (!extraInitialize()) {
initialize();
}
@@ -151,9 +155,6 @@ public class JitsiMeetActivity extends FragmentActivity
}
protected void initialize() {
// Listen for conference events.
getJitsiView().setListener(this);
// Join the room specified by the URL the app was launched with.
// Joining without the room option displays the welcome page.
join(getConferenceOptions(getIntent()));
@@ -164,6 +165,8 @@ public class JitsiMeetActivity extends FragmentActivity
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
JitsiMeetActivityDelegate.onActivityResult(this, requestCode, resultCode, data);
}

View File

@@ -22,7 +22,6 @@ import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import com.calendarevents.CalendarEventsPackage;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactContext;
@@ -167,13 +166,7 @@ public class JitsiMeetActivityDelegate {
}
public static void onRequestPermissionsResult(
final int requestCode,
final String[] permissions,
final int[] grantResults) {
CalendarEventsPackage.onRequestPermissionsResult(
requestCode,
permissions,
grantResults);
final int requestCode, final String[] permissions, final int[] grantResults) {
permissionsCallback = new Callback() {
@Override
public void invoke(Object... args) {

View File

@@ -288,6 +288,7 @@ public class JitsiMeetConferenceOptions implements Parcelable {
}
private JitsiMeetConferenceOptions(Parcel in) {
serverURL = (URL) in.readSerializable();
room = in.readString();
subject = in.readString();
token = in.readString();
@@ -376,6 +377,7 @@ public class JitsiMeetConferenceOptions implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeSerializable(serverURL);
dest.writeString(room);
dest.writeString(subject);
dest.writeString(token);

View File

@@ -57,22 +57,6 @@ public class JitsiMeetFragment extends Fragment {
return view;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
JitsiMeetActivityDelegate.onActivityResult(
getActivity(), requestCode, resultCode, data);
}
@Override
public void onDestroyView() {
if (view != null) {
view.dispose();
view = null;
}
super.onDestroyView();
}
@Override
public void onDestroy() {
super.onDestroy();

View File

@@ -201,4 +201,10 @@ public class JitsiMeetView extends BaseReactView<JitsiMeetViewListener>
protected void onExternalAPIEvent(String name, ReadableMap data) {
onExternalAPIEvent(LISTENER_METHODS, name, data);
}
@Override
protected void onDetachedFromWindow() {
dispose();
super.onDetachedFromWindow();
}
}

View File

@@ -190,6 +190,7 @@ class ReactInstanceManagerHolder {
new com.corbt.keepawake.KCKeepAwakePackage(),
new com.facebook.react.shell.MainReactPackage(),
new com.horcrux.svg.SvgPackage(),
new com.kevinresol.react_native_default_preference.RNDefaultPreferencePackage(),
new com.ocetnik.timer.BackgroundTimerPackage(),
new com.reactnativecommunity.asyncstorage.AsyncStoragePackage(),
new com.reactnativecommunity.netinfo.NetInfoPackage(),

View File

@@ -9,6 +9,8 @@ include ':react-native-community-async-storage'
project(':react-native-community-async-storage').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/async-storage/android')
include ':react-native-community_netinfo'
project(':react-native-community_netinfo').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/netinfo/android')
include ':react-native-default-preference'
project(':react-native-default-preference').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-default-preference/android')
include ':react-native-google-signin'
project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/google-signin/android')
include ':react-native-immersive'
@@ -24,4 +26,4 @@ project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../
include ':react-native-webrtc'
project(':react-native-webrtc').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webrtc/android')
include ':react-native-webview'
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')

2
app.js
View File

@@ -6,10 +6,10 @@ import 'jQuery-Impromptu';
import conference from './conference';
import API from './modules/API';
import UI from './modules/UI/UI';
import keyboardshortcut from './modules/keyboardshortcut/keyboardshortcut';
import remoteControl from './modules/remotecontrol/RemoteControl';
import translation from './modules/translation/translation';
import UI from './modules/UI/UI';
window.APP = {
API,

View File

@@ -1,25 +1,20 @@
/* global $, APP, JitsiMeetJS, config, interfaceConfig */
import { openConnection } from './connection';
import EventEmitter from 'events';
import Logger from 'jitsi-meet-logger';
import * as JitsiMeetConferenceEvents from './ConferenceEvents';
import { openConnection } from './connection';
import { ENDPOINT_TEXT_MESSAGE_NAME } from './modules/API/constants';
import AuthHandler from './modules/UI/authentication/AuthHandler';
import Recorder from './modules/recorder/Recorder';
import mediaDeviceHelper from './modules/devices/mediaDeviceHelper';
import * as RemoteControlEvents
from './service/remotecontrol/RemoteControlEvents';
import UIEvents from './service/UI/UIEvents';
import UIUtil from './modules/UI/util/UIUtil';
import mediaDeviceHelper from './modules/devices/mediaDeviceHelper';
import Recorder from './modules/recorder/Recorder';
import { createTaskQueue } from './modules/util/helpers';
import * as JitsiMeetConferenceEvents from './ConferenceEvents';
import {
createDeviceChangedEvent,
createStartSilentEvent,
createScreenSharingEvent,
createStreamSwitchDelayEvent,
createTrackMutedEvent,
sendAnalytics
} from './react/features/analytics';
@@ -28,9 +23,6 @@ import {
redirectToStaticPage,
reloadWithStoredParams
} from './react/features/app';
import EventEmitter from 'events';
import {
AVATAR_ID_COMMAND,
AVATAR_URL_COMMAND,
@@ -56,6 +48,7 @@ import {
import {
checkAndNotifyForNewDevice,
getAvailableDevices,
getDefaultDeviceId,
notifyCameraError,
notifyMicError,
setAudioOutputDeviceId,
@@ -80,7 +73,6 @@ import {
setVideoAvailable,
setVideoMuted
} from './react/features/base/media';
import { showNotification } from './react/features/notifications';
import {
dominantSpeakerChanged,
getLocalParticipant,
@@ -110,29 +102,53 @@ import {
trackAdded,
trackRemoved
} from './react/features/base/tracks';
import { getJitsiMeetGlobalNS } from './react/features/base/util';
import {
getBackendSafePath,
getJitsiMeetGlobalNS
} from './react/features/base/util';
import { showDesktopPicker } from './react/features/desktop-picker';
import { appendSuffix } from './react/features/display-name';
import { setE2EEKey } from './react/features/e2ee';
import {
maybeOpenFeedbackDialog,
submitFeedback
} from './react/features/feedback';
import { showNotification } from './react/features/notifications';
import { mediaPermissionPromptVisibilityChanged } from './react/features/overlay';
import { suspendDetected } from './react/features/power-monitor';
import {
initPrejoin,
isPrejoinPageEnabled,
isPrejoinPageVisible,
replacePrejoinAudioTrack,
replacePrejoinVideoTrack
} from './react/features/prejoin';
import { createRnnoiseProcessorPromise } from './react/features/rnnoise';
import { toggleScreenshotCaptureEffect } from './react/features/screenshot-capture';
import { setSharedVideoStatus } from './react/features/shared-video';
import { AudioMixerEffect } from './react/features/stream-effects/audio-mixer/AudioMixerEffect';
import { createPresenterEffect } from './react/features/stream-effects/presenter';
import { endpointMessageReceived } from './react/features/subtitles';
import { createRnnoiseProcessorPromise } from './react/features/rnnoise';
import { toggleScreenshotCaptureEffect } from './react/features/screenshot-capture';
import UIEvents from './service/UI/UIEvents';
import * as RemoteControlEvents
from './service/remotecontrol/RemoteControlEvents';
const logger = require('jitsi-meet-logger').getLogger(__filename);
const logger = Logger.getLogger(__filename);
const eventEmitter = new EventEmitter();
let room;
let connection;
/**
* The promise is used when the prejoin screen is shown.
* While the user configures the devices the connection can be made.
*
* @type {Promise<Object>}
* @private
*/
let _connectionPromise;
/**
* This promise is used for chaining mutePresenterVideo calls in order to avoid calling GUM multiple times if it takes
* a while to finish.
@@ -280,12 +296,6 @@ class ConferenceConnector {
logger.error('CONFERENCE FAILED:', err, ...params);
switch (err) {
case JitsiConferenceErrors.CONNECTION_ERROR: {
const [ msg ] = params;
APP.UI.notifyConnectionFailed(msg);
break;
}
case JitsiConferenceErrors.NOT_ALLOWED_ERROR: {
// let's show some auth not allowed page
@@ -320,14 +330,6 @@ class ConferenceConnector {
APP.UI.notifyGracefulShutdown();
break;
case JitsiConferenceErrors.CONFERENCE_DESTROYED: {
const [ reason ] = params;
APP.UI.hideStats();
APP.UI.notifyConferenceDestroyed(reason);
break;
}
// FIXME FOCUS_DISCONNECTED is a confusing event name.
// What really happens there is that the library is not ready yet,
// because Jicofo is not available, but it is going to give it another
@@ -340,6 +342,7 @@ class ConferenceConnector {
}
case JitsiConferenceErrors.FOCUS_LEFT:
case JitsiConferenceErrors.ICE_FAILED:
case JitsiConferenceErrors.VIDEOBRIDGE_NOT_AVAILABLE:
case JitsiConferenceErrors.OFFER_ANSWER_FAILED:
APP.store.dispatch(conferenceWillLeave(room));
@@ -471,28 +474,13 @@ export default {
localVideo: null,
/**
* Creates local media tracks and connects to a room. Will show error
* dialogs in case accessing the local microphone and/or camera failed. Will
* show guidance overlay for users on how to give access to camera and/or
* microphone.
* @param {string} roomName
* @param {object} options
* @param {boolean} options.startAudioOnly=false - if <tt>true</tt> then
* only audio track will be created and the audio only mode will be turned
* on.
* @param {boolean} options.startScreenSharing=false - if <tt>true</tt>
* should start with screensharing instead of camera video.
* @param {boolean} options.startWithAudioMuted - will start the conference
* without any audio tracks.
* @param {boolean} options.startWithVideoMuted - will start the conference
* without any video tracks.
* @returns {Promise.<JitsiLocalTrack[], JitsiConnection>}
* Returns an object containing a promise which resolves with the created tracks &
* the errors resulting from that process.
*
* @returns {Promise<JitsiLocalTrack[]>, Object}
*/
createInitialLocalTracksAndConnect(roomName, options = {}) {
let audioAndVideoError,
audioOnlyError,
screenSharingError,
videoOnlyError;
createInitialLocalTracks(options = {}) {
const errors = {};
const initialDevices = [ 'audio' ];
const requestedAudio = true;
let requestedVideo = false;
@@ -524,7 +512,7 @@ export default {
// FIXME is there any simpler way to rewrite this spaghetti below ?
if (options.startScreenSharing) {
tryCreateLocalTracks = this._createDesktopTrack()
.then(desktopStream => {
.then(([ desktopStream ]) => {
if (!requestedAudio) {
return [ desktopStream ];
}
@@ -533,21 +521,21 @@ export default {
.then(([ audioStream ]) =>
[ desktopStream, audioStream ])
.catch(error => {
audioOnlyError = error;
errors.audioOnlyError = error;
return [ desktopStream ];
});
})
.catch(error => {
logger.error('Failed to obtain desktop stream', error);
screenSharingError = error;
errors.screenSharingError = error;
return requestedAudio
? createLocalTracksF({ devices: [ 'audio' ] }, true)
: [];
})
.catch(error => {
audioOnlyError = error;
errors.audioOnlyError = error;
return [];
});
@@ -560,16 +548,16 @@ export default {
if (requestedAudio && requestedVideo) {
// Try audio only...
audioAndVideoError = err;
errors.audioAndVideoError = err;
return (
createLocalTracksF({ devices: [ 'audio' ] }, true));
} else if (requestedAudio && !requestedVideo) {
audioOnlyError = err;
errors.audioOnlyError = err;
return [];
} else if (requestedVideo && !requestedAudio) {
videoOnlyError = err;
errors.videoOnlyError = err;
return [];
}
@@ -580,7 +568,7 @@ export default {
if (!requestedAudio) {
logger.error('The impossible just happened', err);
}
audioOnlyError = err;
errors.audioOnlyError = err;
// Try video only...
return requestedVideo
@@ -592,7 +580,7 @@ export default {
if (!requestedVideo) {
logger.error('The impossible just happened', err);
}
videoOnlyError = err;
errors.videoOnlyError = err;
return [];
});
@@ -603,8 +591,44 @@ export default {
// cases, when auth is rquired, for instance, that won't happen until
// the user inputs their credentials, but the dialog would be
// overshadowed by the overlay.
tryCreateLocalTracks.then(() =>
APP.store.dispatch(mediaPermissionPromptVisibilityChanged(false)));
tryCreateLocalTracks.then(tracks => {
APP.store.dispatch(mediaPermissionPromptVisibilityChanged(false));
return tracks;
});
return {
tryCreateLocalTracks,
errors
};
},
/**
* Creates local media tracks and connects to a room. Will show error
* dialogs in case accessing the local microphone and/or camera failed. Will
* show guidance overlay for users on how to give access to camera and/or
* microphone.
* @param {string} roomName
* @param {object} options
* @param {boolean} options.startAudioOnly=false - if <tt>true</tt> then
* only audio track will be created and the audio only mode will be turned
* on.
* @param {boolean} options.startScreenSharing=false - if <tt>true</tt>
* should start with screensharing instead of camera video.
* @param {boolean} options.startWithAudioMuted - will start the conference
* without any audio tracks.
* @param {boolean} options.startWithVideoMuted - will start the conference
* without any video tracks.
* @returns {Promise.<JitsiLocalTrack[], JitsiConnection>}
*/
createInitialLocalTracksAndConnect(roomName, options = {}) {
const { tryCreateLocalTracks, errors } = this.createInitialLocalTracks(options);
const {
audioAndVideoError,
audioOnlyError,
screenSharingError,
videoOnlyError
} = errors;
return Promise.all([ tryCreateLocalTracks, connect(roomName) ])
.then(([ tracks, con ]) => {
@@ -636,103 +660,132 @@ export default {
});
},
startConference(con, tracks) {
tracks.forEach(track => {
if ((track.isAudioTrack() && this.isLocalAudioMuted())
|| (track.isVideoTrack() && this.isLocalVideoMuted())) {
const mediaType = track.getType();
sendAnalytics(
createTrackMutedEvent(mediaType, 'initial mute'));
logger.log(`${mediaType} mute: initially muted.`);
track.mute();
}
});
logger.log(`Initialized with ${tracks.length} local tracks`);
this._localTracksInitialized = true;
con.addEventListener(JitsiConnectionEvents.CONNECTION_FAILED, _connectionFailedHandler);
APP.connection = connection = con;
// Desktop sharing related stuff:
this.isDesktopSharingEnabled
= JitsiMeetJS.isDesktopSharingEnabled();
eventEmitter.emit(JitsiMeetConferenceEvents.DESKTOP_SHARING_ENABLED_CHANGED, this.isDesktopSharingEnabled);
APP.store.dispatch(
setDesktopSharingEnabled(this.isDesktopSharingEnabled));
this._createRoom(tracks);
APP.remoteControl.init();
// if user didn't give access to mic or camera or doesn't have
// them at all, we mark corresponding toolbar buttons as muted,
// so that the user can try unmute later on and add audio/video
// to the conference
if (!tracks.find(t => t.isAudioTrack())) {
this.setAudioMuteStatus(true);
}
if (!tracks.find(t => t.isVideoTrack())) {
this.setVideoMuteStatus(true);
}
if (config.iAmRecorder) {
this.recorder = new Recorder();
}
if (config.startSilent) {
sendAnalytics(createStartSilentEvent());
APP.store.dispatch(showNotification({
descriptionKey: 'notify.startSilentDescription',
titleKey: 'notify.startSilentTitle'
}));
}
// XXX The API will take care of disconnecting from the XMPP
// server (and, thus, leaving the room) on unload.
return new Promise((resolve, reject) => {
(new ConferenceConnector(resolve, reject)).connect();
});
},
/**
* Open new connection and join to the conference.
* @param {object} options
* @param {string} roomName - The name of the conference.
* Open new connection and join the conference when prejoin page is not enabled.
* If prejoin page is enabled open an new connection in the background
* and create local tracks.
*
* @param {{ roomName: string }} options
* @returns {Promise}
*/
init(options) {
this.roomName = options.roomName;
async init({ roomName }) {
const initialOptions = {
startAudioOnly: config.startAudioOnly,
startScreenSharing: config.startScreenSharing,
startWithAudioMuted: config.startWithAudioMuted
|| config.startSilent
|| isUserInteractionRequiredForUnmute(APP.store.getState()),
startWithVideoMuted: config.startWithVideoMuted
|| isUserInteractionRequiredForUnmute(APP.store.getState())
};
return (
this.roomName = roomName;
window.addEventListener('hashchange', this.onHashChange.bind(this), false);
try {
// Initialize the device list first. This way, when creating tracks
// based on preferred devices, loose label matching can be done in
// cases where the exact ID match is no longer available, such as
// when the camera device has switched USB ports.
// when in startSilent mode we want to start with audio muted
this._initDeviceList()
.catch(error => logger.warn(
'initial device list initialization failed', error))
.then(() => this.createInitialLocalTracksAndConnect(
options.roomName, {
startAudioOnly: config.startAudioOnly,
startScreenSharing: config.startScreenSharing,
startWithAudioMuted: config.startWithAudioMuted
|| config.startSilent
|| isUserInteractionRequiredForUnmute(APP.store.getState()),
startWithVideoMuted: config.startWithVideoMuted
|| isUserInteractionRequiredForUnmute(APP.store.getState())
}))
.then(([ tracks, con ]) => {
tracks.forEach(track => {
if ((track.isAudioTrack() && this.isLocalAudioMuted())
|| (track.isVideoTrack() && this.isLocalVideoMuted())) {
const mediaType = track.getType();
await this._initDeviceList();
} catch (error) {
logger.warn('initial device list initialization failed', error);
}
sendAnalytics(
createTrackMutedEvent(mediaType, 'initial mute'));
logger.log(`${mediaType} mute: initially muted.`);
track.mute();
}
});
logger.log(`initialized with ${tracks.length} local tracks`);
this._localTracksInitialized = true;
con.addEventListener(
JitsiConnectionEvents.CONNECTION_FAILED,
_connectionFailedHandler);
APP.connection = connection = con;
if (isPrejoinPageEnabled(APP.store.getState())) {
_connectionPromise = connect(roomName);
// Desktop sharing related stuff:
this.isDesktopSharingEnabled
= JitsiMeetJS.isDesktopSharingEnabled();
eventEmitter.emit(
JitsiMeetConferenceEvents.DESKTOP_SHARING_ENABLED_CHANGED,
this.isDesktopSharingEnabled);
const { tryCreateLocalTracks, errors } = this.createInitialLocalTracks(initialOptions);
const tracks = await tryCreateLocalTracks;
APP.store.dispatch(
setDesktopSharingEnabled(this.isDesktopSharingEnabled));
// Initialize device list a second time to ensure device labels
// get populated in case of an initial gUM acceptance; otherwise
// they may remain as empty strings.
this._initDeviceList(true);
this._createRoom(tracks);
APP.remoteControl.init();
return APP.store.dispatch(initPrejoin(tracks, errors));
}
// if user didn't give access to mic or camera or doesn't have
// them at all, we mark corresponding toolbar buttons as muted,
// so that the user can try unmute later on and add audio/video
// to the conference
if (!tracks.find(t => t.isAudioTrack())) {
this.setAudioMuteStatus(true);
}
const [ tracks, con ] = await this.createInitialLocalTracksAndConnect(
roomName, initialOptions);
if (!tracks.find(t => t.isVideoTrack())) {
this.setVideoMuteStatus(true);
}
this._initDeviceList(true);
// Initialize device list a second time to ensure device labels
// get populated in case of an initial gUM acceptance; otherwise
// they may remain as empty strings.
this._initDeviceList(true);
return this.startConference(con, tracks);
},
if (config.iAmRecorder) {
this.recorder = new Recorder();
}
/**
* Joins conference after the tracks have been configured in the prejoin screen.
*
* @param {Object[]} tracks - An array with the configured tracks
* @returns {Promise}
*/
async prejoinStart(tracks) {
const con = await _connectionPromise;
if (config.startSilent) {
sendAnalytics(createStartSilentEvent());
APP.store.dispatch(showNotification({
descriptionKey: 'notify.startSilentDescription',
titleKey: 'notify.startSilentTitle'
}));
}
// XXX The API will take care of disconnecting from the XMPP
// server (and, thus, leaving the room) on unload.
return new Promise((resolve, reject) => {
(new ConferenceConnector(resolve, reject)).connect();
});
})
);
return this.startConference(con, tracks);
},
/**
@@ -1177,6 +1230,34 @@ export default {
}));
},
/**
* Handled location hash change events.
*/
onHashChange() {
const items = {};
const parts = window.location.hash.substr(1).split('&');
for (const part of parts) {
const param = part.split('=');
const key = param[0];
if (!key) {
continue; // eslint-disable-line no-continue
}
items[key] = param[1];
}
if (typeof items.e2eekey !== 'undefined') {
APP.store.dispatch(setE2EEKey(items.e2eekey));
// Clean URL in browser history.
const cleanUrl = window.location.href.split('#')[0];
history.replaceState(history.state, document.title, cleanUrl);
}
},
/**
* Exposes a Command(s) API on this instance. It is necessitated by (1) the
* desire to keep room private to this instance and (2) the need of other
@@ -1273,7 +1354,13 @@ export default {
const options = config;
const { email, name: nick } = getLocalParticipant(APP.store.getState());
const { locationURL } = APP.store.getState()['features/base/connection'];
const state = APP.store.getState();
const { locationURL } = state['features/base/connection'];
const { tenant } = state['features/base/jwt'];
if (tenant) {
options.siteID = tenant;
}
if (options.enableDisplayNameInStats && nick) {
options.statisticsDisplayName = nick;
@@ -1285,7 +1372,7 @@ export default {
options.applicationName = interfaceConfig.APP_NAME;
options.getWiFiStatsMethod = this._getWiFiStatsMethod;
options.confID = `${locationURL.host}${locationURL.pathname}`;
options.confID = `${locationURL.host}${getBackendSafePath(locationURL.pathname)}`;
options.createVADProcessor = createRnnoiseProcessorPromise;
// Disable CallStats, if requessted.
@@ -1322,6 +1409,18 @@ export default {
useVideoStream(newStream) {
return new Promise((resolve, reject) => {
_replaceLocalVideoTrackQueue.enqueue(onFinish => {
/**
* When the prejoin page is visible there is no conference object
* created. The prejoin tracks are managed separately,
* so this updates the prejoin video track.
*/
if (isPrejoinPageVisible(APP.store.getState())) {
return APP.store.dispatch(replacePrejoinVideoTrack(newStream))
.then(resolve)
.catch(reject)
.then(onFinish);
}
APP.store.dispatch(
replaceLocalTrack(this.localVideo, newStream, room))
.then(() => {
@@ -1375,6 +1474,18 @@ export default {
useAudioStream(newStream) {
return new Promise((resolve, reject) => {
_replaceLocalAudioTrackQueue.enqueue(onFinish => {
/**
* When the prejoin page is visible there is no conference object
* created. The prejoin tracks are managed separately,
* so this updates the prejoin audio stream.
*/
if (isPrejoinPageVisible(APP.store.getState())) {
return APP.store.dispatch(replacePrejoinAudioTrack(newStream))
.then(resolve)
.catch(reject)
.then(onFinish);
}
APP.store.dispatch(
replaceLocalTrack(this.localAudio, newStream, room))
.then(() => {
@@ -1786,7 +1897,7 @@ export default {
const desktopVideoStream = streams.find(stream => stream.getType() === MEDIA_TYPE.VIDEO);
if (desktopVideoStream) {
this.useVideoStream(desktopVideoStream);
await this.useVideoStream(desktopVideoStream);
}
this._desktopAudioStream = streams.find(stream => stream.getType() === MEDIA_TYPE.AUDIO);
@@ -1975,6 +2086,7 @@ export default {
logger.info(`My role changed, new role: ${role}`);
APP.store.dispatch(localParticipantRoleChanged(role));
APP.API.notifyUserRoleChanged(id, role);
} else {
APP.store.dispatch(participantRoleChanged(id, role));
}
@@ -2232,18 +2344,6 @@ export default {
});
});
/* eslint-disable max-params */
APP.UI.addListener(
UIEvents.RESOLUTION_CHANGED,
(id, oldResolution, newResolution, delay) => {
sendAnalytics(createStreamSwitchDelayEvent(
{
'old_resolution': oldResolution,
'new_resolution': newResolution,
value: delay
}));
});
APP.UI.addListener(UIEvents.AUTH_CLICKED, () => {
AuthHandler.authenticate(room);
});
@@ -2321,11 +2421,20 @@ export default {
micDeviceId => {
const audioWasMuted = this.isLocalAudioMuted();
// When the 'default' mic needs to be selected, we need to
// pass the real device id to gUM instead of 'default' in order
// to get the correct MediaStreamTrack from chrome because of the
// following bug.
// https://bugs.chromium.org/p/chromium/issues/detail?id=997689
const hasDefaultMicChanged = micDeviceId === 'default';
sendAnalytics(createDeviceChangedEvent('audio', 'input'));
createLocalTracksF({
devices: [ 'audio' ],
cameraDeviceId: null,
micDeviceId
micDeviceId: hasDefaultMicChanged
? getDefaultDeviceId(APP.store.getState(), 'audioInput')
: micDeviceId
})
.then(([ stream ]) => {
// if audio was muted before changing the device, mute
@@ -2349,6 +2458,12 @@ export default {
return this.useAudioStream(stream);
})
.then(() => {
if (hasDefaultMicChanged) {
// workaround for the default device to be shown as selected in the
// settings even when the real device id was passed to gUM because of the
// above mentioned chrome bug.
this.localAudio._realDeviceId = this.localAudio.deviceId = 'default';
}
logger.log(`switched local audio device: ${this.localAudio?.getDeviceId()}`);
this._updateAudioDeviceId();
@@ -2650,11 +2765,20 @@ export default {
checkAndNotifyForNewDevice(newAvailDevices.videoInput, oldDevices.videoInput));
}
// When the 'default' mic needs to be selected, we need to
// pass the real device id to gUM instead of 'default' in order
// to get the correct MediaStreamTrack from chrome because of the
// following bug.
// https://bugs.chromium.org/p/chromium/issues/detail?id=997689
const hasDefaultMicChanged = newDevices.audioinput === 'default';
promises.push(
mediaDeviceHelper.createLocalTracksAfterDeviceListChanged(
createLocalTracksF,
newDevices.videoinput,
newDevices.audioinput)
hasDefaultMicChanged
? getDefaultDeviceId(APP.store.getState(), 'audioInput')
: newDevices.audioinput)
.then(tracks => {
// If audio or video muted before, or we unplugged current
// device and selected new one, then mute new track.
@@ -2679,6 +2803,12 @@ export default {
// Use the new stream or null if we failed to obtain it.
return useStream(tracks.find(track => track.getType() === mediaType) || null)
.then(() => {
if (hasDefaultMicChanged) {
// workaround for the default device to be shown as selected in the
// settings even when the real device id was passed to gUM because of
// the above mentioned chrome bug.
this.localAudio._realDeviceId = this.localAudio.deviceId = 'default';
}
mediaType === 'audio'
? this._updateAudioDeviceId()
: this._updateVideoDeviceId();
@@ -2811,7 +2941,7 @@ export default {
leaveRoomAndDisconnect() {
APP.store.dispatch(conferenceWillLeave(room));
if (room.isJoined()) {
if (room && room.isJoined()) {
return room.leave().then(disconnect, disconnect);
}

View File

@@ -44,9 +44,6 @@ var config = {
//
testing: {
// Enables experimental simulcast support on Firefox.
enableFirefoxSimulcast: false,
// P2P test mode disables automatic switching to P2P when there are 2
// participants in the conference.
p2pTestMode: false
@@ -57,6 +54,13 @@ var config = {
// Disables the auto-play behavior of *all* newly created video element.
// This is useful when the client runs on a host with limited resources.
// noAutoPlayVideo: false
// Enable / disable 500 Kbps bitrate cap on desktop tracks. When enabled,
// simulcast is turned off for the desktop share. If presenter is turned
// on while screensharing is in progress, the max bitrate is automatically
// adjusted to 2.5 Mbps. This takes a value between 0 and 1 which determines
// the probability for this to be enabled.
// capScreenshareBitrate: 1 // 0 to disable
},
// Disables ICE/UDP by filtering out local and remote UDP candidates in
@@ -111,11 +115,10 @@ var config = {
// w3c spec-compliant video constraints to use for video capture. Currently
// used by browsers that return true from lib-jitsi-meet's
// util#browser#usesNewGumFlow. The constraints are independent from
// this config's resolution value. Defaults to requesting an ideal aspect
// ratio of 16:9 with an ideal resolution of 720.
// this config's resolution value. Defaults to requesting an ideal
// resolution of 720p.
// constraints: {
// video: {
// aspectRatio: 16 / 9,
// height: {
// ideal: 720,
// max: 720,
@@ -214,6 +217,21 @@ var config = {
// Default value for the channel "last N" attribute. -1 for unlimited.
channelLastN: -1,
// // Options for the recording limit notification.
// recordingLimit: {
//
// // The recording limit in minutes. Note: This number appears in the notification text
// // but doesn't enforce the actual recording time limit. This should be configured in
// // jibri!
// limit: 60,
//
// // The name of the app with unlimited recordings.
// appName: 'Unlimited recordings APP',
//
// // The URL of the app with unlimited recordings.
// appURL: 'https://unlimited.recordings.app.com/'
// },
// Disables or enables RTX (RFC 4588) (defaults to false).
// disableRtx: false,
@@ -230,6 +248,14 @@ var config = {
// disabled, then bandwidth estimations are disabled.
// enableRemb: false,
// Enables ICE restart logic in LJM and displays the page reload overlay on
// ICE failure. Current disabled by default because it's causing issues with
// signaling when Octo is enabled. Also when we do an "ICE restart"(which is
// not a real ICE restart), the client maintains the TCC sequence number
// counter, but the bridge resets it. The bridge sends media packets with
// TCC sequence numbers starting from 0.
// enableIceRestart: false,
// Defines the minimum number of participants to start a call (the default
// is set in Jicofo and set to 2).
// minParticipants: 2,
@@ -293,6 +319,9 @@ var config = {
// and microsoftApiApplicationClientID
// enableCalendarIntegration: false,
// When 'true', it shows an intermediate page before joining, where the user can configure its devices.
// prejoinPageEnabled: false,
// Stats
//
@@ -343,9 +372,9 @@ var config = {
// The STUN servers that will be used in the peer to peer connections
stunServers: [
// { urls: 'stun:jitsi-meet.example.com:443' },
// { urls: 'stun:jitsi-meet.example.com:4446' },
{ urls: 'stun:meet-jit-si-turnrelay.jitsi.net:443' }
],
]
// Sets the ICE transport policy for the p2p connection. At the time
// of this writing the list of possible values are 'all' and 'relay',
@@ -357,7 +386,7 @@ var config = {
// If set to true, it will prefer to use H.264 for P2P calls (if H.264
// is supported).
preferH264: true
// preferH264: true
// If set to true, disable H.264 video codec by stripping it out of the
// SDP.
@@ -372,6 +401,10 @@ var config = {
// The Google Analytics Tracking ID:
// googleAnalyticsTrackingId: 'your-tracking-id-UA-123456-1'
// Matomo configuration:
// matomoEndpoint: 'https://your-matomo-endpoint/',
// matomoSiteID: '42',
// The Amplitude APP Key:
// amplitudeAPPKey: '<APP_KEY>'
@@ -452,6 +485,14 @@ var config = {
// the menu has option to flip the locally seen video for local presentations
// disableLocalVideoFlip: false,
// Mainly privacy related settings
// Disables all invite functions from the app (share, invite, dial out...etc)
// disableInviteFunctions: true,
// Disables storing the room name to the recents list
// doNotStoreRoom: true,
// Deployment specific URLs.
// deploymentUrls: {
// // If specified a 'Help' button will be displayed in the overflow menu with a link to the specified URL for
@@ -471,6 +512,23 @@ var config = {
// If set to true all muting operations of remote participants will be disabled.
// disableRemoteMute: true,
/**
External API url used to receive branding specific information.
If there is no url set or there are missing fields, the defaults are applied.
None of the fieds are mandatory and the response must have the shape:
{
// The hex value for the colour used as background
backgroundColor: '#fff',
// The url for the image used as background
backgroundImageUrl: 'https://example.com/background-img.png',
// The anchor url used when clicking the logo image
logoClickUrl: 'https://example-company.org',
// The url used for the image used as logo
logoImageUrl: 'https://example.com/logo-img.png'
}
*/
// brandingDataUrl: '',
// List of undocumented settings used in jitsi-meet
/**
_immediateReloadThreshold

View File

@@ -1,8 +1,9 @@
/* global APP, JitsiMeetJS, config */
import AuthHandler from './modules/UI/authentication/AuthHandler';
import jitsiLocalStorage from './modules/util/JitsiLocalStorage';
import Logger from 'jitsi-meet-logger';
import { jitsiLocalStorage } from 'js-utils';
import AuthHandler from './modules/UI/authentication/AuthHandler';
import {
connectionEstablished,
connectionFailed
@@ -13,7 +14,7 @@ import {
JitsiConnectionEvents
} from './react/features/base/lib-jitsi-meet';
const logger = require('jitsi-meet-logger').getLogger(__filename);
const logger = Logger.getLogger(__filename);
/**
* The feature announced so we can distinguish jibri participants.

View File

@@ -1,7 +1,7 @@
/* global config, createConnectionExternally */
import getRoomName from '../react/features/base/config/getRoomName';
import parseURLParams from '../react/features/base/config/parseURLParams';
import { parseURLParams } from '../react/features/base/util/parseURLParams';
/**
* Implements external connect using createConnectionExternally function defined

View File

@@ -1,5 +1,6 @@
.audio-preview {
&-content {
background: #2A3A4B;
font-size: 15px;
line-height: 24px;
max-height: 456px;
@@ -13,6 +14,7 @@
padding: 16px;
&-icon {
color: #A4B8D1;
display: inline-block;
}
@@ -31,7 +33,7 @@
margin-left: 48px;
&--selected {
background: rgba(28,32,37,0.5);
background: #1C2025;
cursor: initial;
margin-left: 0;
padding-left: 21px;
@@ -54,7 +56,7 @@
&:hover {
.audio-preview-entry {
background: rgba(255,255,255, 0.2);
background: #3F4E5E;
margin-left: 0;
padding-left: 48px;
@@ -66,6 +68,10 @@
.audio-preview-test-button {
display: inline-block;
}
.audio-preview-entry-text {
max-width: 196px;
}
}
.audio-preview-entry-text {
@@ -75,8 +81,23 @@
&-microphone {
position: relative;
}
&:hover {
.audio-preview-entry {
background: #3F4E5E;
margin-left: 0;
padding-left: 48px;
&--selected {
padding-left: 21px;
}
}
}
.audio-preview-entry-text {
max-width: 196px;
}
}
&-icon {
border-radius: 50%;

View File

@@ -20,18 +20,6 @@
}
}
.avatar-foreign {
align-items: center;
bottom: 0;
display: flex;
font-size: 40pt;
justify-content: center;
left: 0;
position: absolute;
right: 0;
top: 0;
}
.avatar-svg {
height: 100%;
width: 100%;
@@ -63,4 +51,4 @@
@include avatarBadge;
background-color: $presence-idle;
}
}
}

View File

@@ -115,8 +115,9 @@ form {
.leftwatermark {
left: 32px;
top: 32px;
background-image: url($defaultWatermarkLink);
background-position: center left;
background-repeat: no-repeat;
background-size: contain;
}
.rightwatermark {

75
css/_country-picker.scss Normal file
View File

@@ -0,0 +1,75 @@
.cpick {
border: 1px solid #A4B8D1;
color: #fff;
display: flex;
font-size: 15px;
height: 38px;
line-height: 24px;
&-selector {
align-items: center;
background-color: #283447;
border-right: 1px solid #A4B8D1;
cursor: pointer;
display: flex;
padding: 8px 10px;
position: relative;
width: 88px;
}
&-icon {
margin-right: 8px;
position: absolute;
right: 0;
top: 12px;
& > svg {
fill: #fff;
}
}
&-input {
padding: 8px;
background: #1C2025;
border: 0;
margin: 0;
color: #fff;
caret-color: #0376DA;
flex-grow: 1;
}
&-dropdown {
height: 190px;
overflow-y: auto;
width: 343px;
}
&-dropdown-entry {
align-items: center;
cursor: pointer;
display: flex;
height: 40px;
padding: 0 10px;
&:hover {
background-color: #66768b;
}
&-text {
color: #fff;
flex-grow: 1;
font-size: 15px;
line-height: 24px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
// Override @Atlaskit/inline-dialog styles
.cpick-container > div > div:nth-child(2) > div > div {
outline: none;
padding: 8px 0 0 0;
}

68
css/_labels.scss Normal file
View File

@@ -0,0 +1,68 @@
.large-video-labels {
display: flex;
position: absolute;
top: 30px;
right: 30px;
transition: right 0.5s;
z-index: $zindex3;
.circular-label {
align-items: center;
color: white;
display: flex;
font-weight: bold;
justify-content: center;
margin-left: 8px;
opacity: 0.8;
}
.circular-label {
background: #B8C7E0;
}
.circular-label.e2ee {
align-items: center;
background: #76CF9C;
display: flex;
justify-content: center;
}
.circular-label.file {
background: #FF5630;
}
.circular-label.local-rec {
background: #FF5630;
}
.circular-label.stream {
background: #0065FF;
}
.circular-label.insecure {
background: $defaultWarningColor;
}
.recording-label.center-message {
background: $videoStateIndicatorBackground;
bottom: 50%;
display: block;
left: 50%;
padding: 10px;
position: fixed;
transform: translate(-50%, -50%);
z-index: $centeredVideoLabelZ;
}
}
.circular-label {
background: $videoStateIndicatorBackground;
border-radius: 50%;
box-sizing: border-box;
cursor: default;
font-size: 13px;
height: $videoStateIndicatorSize;
line-height: $videoStateIndicatorSize;
text-align: center;
min-width: $videoStateIndicatorSize;
}

140
css/_lobby.scss Normal file
View File

@@ -0,0 +1,140 @@
#lobby-screen {
.content {
.container {
align-items: center;
display: flex;
flex-direction: column;
.spinner {
margin: 30px;
}
.joining-message {
margin: 10px;
}
}
.form {
align-items: stretch;
display: flex;
flex-direction: column;
min-width: 400px;
}
.participant-info {
align-items: center;
display: flex;
flex-direction: column;
}
}
}
#lobby-section {
display: flex;
flex-direction: column;
.control-row {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 15px;
label {
font-size: 14px;
font-weight: bold;
}
}
}
#knocking-participant-list {
background-color: $newToolbarBackgroundColor;
border: 1px solid rgba(255, 255, 255, .4);
border-radius: 8px;
display: flex;
flex-direction: column;
left: 0;
margin: 20px;
position: fixed;
top: 20;
transition: top 1s ease;
z-index: 100;
&.toolbox-visible {
// Same as toolbox subject position
top: 120px;
}
.title {
background-color: rgba(0, 0, 0, .2);
font-size: 1.2em;
padding: 15px
}
ul {
list-style-type: none;
padding: 0 15px 15px 15px;
li {
align-items: center;
display: flex;
flex-direction: row;
margin: 8px 0;
.details {
display: flex;
flex: 1;
flex-direction: column;
justify-content: space-evenly;
margin: 0 30px 0 10px;
}
button {
align-self: unset;
margin: 0 5px;
}
}
}
input {
align-self: stretch;
background-color: transparent;
border: 1px solid #B8C7E0;
border-radius: 4px;
color: white;
padding: 12px 8px;
&:focus {
border-color: rgb(3, 118, 218);
}
}
button {
align-self: stretch;
margin: 8px 0;
padding: 12px;
transition: .2s transform ease;
&:disabled {
opacity: .5;
}
&:hover {
transform: scale(1.05);
&:disabled {
transform: none;
}
}
&.borderLess {
background-color: transparent;
border-width: 0;
}
&.primary {
background-color: rgb(3, 118, 218);
border-width: 0;
}
}
}

182
css/_prejoin-dialog.scss Normal file
View File

@@ -0,0 +1,182 @@
.prejoin-dialog {
background: #1C2025;
box-shadow: 0px 2px 20px rgba(0, 0, 0, 0.5);
border-radius: 5px;
color: #fff;
height: 400px;
width: 375px;
&--small {
height: 300;
width: 400;
}
&-label {
font-size: 15px;
line-height: 24px;
&-num {
background: #2b3b4b;
border: 1px solid #A4B8D1;
border-radius: 50%;
color: #fff;
display: inline-block;
height: 24px;
margin-right: 8px;
width: 24px;
}
}
&-container {
align-items: center;
background: rgba(0,0,0,0.6);
display: flex;
height: 100vh;
justify-content: center;
left: 0;
position: absolute;
top: 0;
width: 100vw;
z-index: 3;
}
&-flag {
display: inline-block;
margin-right: 8px;
transform: scale(1.2);
}
&-title {
display: inline-block;
font-size: 24px;
line-height: 32px;
}
&-icon {
cursor: pointer;
> svg {
fill: #A4B8D1;
}
}
&-btn {
width: 309px;
}
&-dialin-container {
text-align: center;
}
&-delimiter {
background: #5f6266;
border: 0;
height: 1px;
margin: 0;
padding: 0;
width: 100%;
&-container {
margin: 16px 0 24px 0;
position: relative;
}
&-txt-container {
position: absolute;
text-align: center;
top: -8px;
width: 100%;
}
&-txt {
background: #1C2025;
color: #5f6266;
font-size: 11px;
text-transform: uppercase;
padding: 0 8px;
}
}
}
.prejoin-dialog-callout {
padding: 16px;
&-header {
display: flex;
justify-content: space-between;
margin-bottom: 24px;
}
&-picker {
margin: 8px 0 16px 0;
}
}
.prejoin-dialog-dialin {
text-align: center;
&-header {
align-items: center;
margin: 16px 0 32px 16px;
display: flex;
}
&-icon {
margin-right: 16px;
}
&-num {
background: #3e474f;
border-radius: 4px;
display: inline-block;
font-size: 15px;
line-height: 24px;
margin: 4px;
padding: 8px;
&-container {
min-height: 48px;
margin: 8px 0;
}
}
&-link {
color: #6FB1EA;
cursor: pointer;
display: inline-block;
font-size: 13px;
line-height: 20px;
margin-bottom: 24px;
}
&-spaced-label {
margin-bottom: 16px;
margin-top: 28px;
}
&-btns {
&> div {
margin-bottom: 16px;
}
}
}
.prejoin-dialog-calling {
padding: 16px;
text-align: center;
&-header {
text-align: right;
}
&-label {
font-size: 15px;
margin: 8px 0 16px 0;
}
&-number {
font-size: 19px;
line-height: 28px;
margin: 16px 0;
}
}

199
css/_prejoin.scss Normal file
View File

@@ -0,0 +1,199 @@
.prejoin {
&-input-area {
margin: 0 auto;
text-align: center;
width: 320px;
}
&-title {
color: #fff;
font-size: 24px;
line-height: 32px;
margin-bottom: 16px;
}
&-text-btns {
display: flex;
justify-content: space-between;
}
&-input-label {
color: #A4B8D1;
font-size: 13px;
line-height: 20px;
margin-top: 32px 0 8px 0;
text-align: center;
width: 100%;
}
&-checkbox {
border: 0;
height: 16px;
margin-right: 8px;
padding: 0;
width: 16px;
}
&-checkbox-container {
align-items: center;
color: #fff;
display: none;
font-size: 13px;
justify-content: center;
line-height: 20px;
margin-top: 16px;
width: 100%;
}
}
@mixin name-placeholder {
color: #fff;
font-weight: 300;
opacity: 0.6;
}
.prejoin-preview {
height: 100%;
position: absolute;
width: 100%;
&--no-video {
background: radial-gradient(50% 50% at 50% 50%, #5B6F80 0%, #365067 100%), #FFFFFF;
text-align: center;
}
&-video {
height: 100%;
object-fit: cover;
position: absolute;
width: 100%;
}
&-name {
color: #fff;
font-size: 19px;
line-height: 28px;
&--editable {
background: none;
border: 0;
border-bottom: 1px solid #D1DBE8;
margin: 24px 0 16px 0;
outline: none;
text-align: center;
width: 100%;
&::-webkit-input-placeholder {
@include name-placeholder;
}
&::-moz-placeholder {
@include name-placeholder;
}
&:-ms-input-placeholder {
@include name-placeholder;
}
}
&--text {
margin: 16px 0;
outline: none;
}
}
&-avatar.avatar {
background: #A4B8D1;
margin: 200px auto 0 auto;
}
&-overlay {
height: 100%;
position: absolute;
width: 100%;
z-index: 1;
background: linear-gradient(0deg, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3));
}
&-bottom-overlay {
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.9) 100%);
bottom: 0;
height: 50%;
position: absolute;
width: 100%;
z-index: 1;
}
&-status {
align-items: center;
align-self: stretch;
color: #fff;
display: flex;
font-size: 13px;
min-height: 24px;
justify-content: center;
text-align: center;
z-index: 1;
&--warning {
background: rgba(241, 173, 51, 0.7)
}
&--ok {
background: rgba(49, 183, 106, 0.7);
}
}
&-icon {
background-position: center;
background-repeat: no-repeat;
display: inline-block;
height: 16px;
margin-right: 8px;
width: 16px;
}
&-error-desc {
margin-right: 4px;
}
.settings-button-container {
width: 49px;
margin: 0 8px;
}
&-dropdown-btns {
width: 320px;
padding: 8px 0;
}
&-dropdown-btn {
align-items: center;
color: #1C2025;
cursor: pointer;
display: flex;
height: 40px;
font-size: 15px;
line-height: 24px;
padding: 0 16px;
&:hover {
background-color: #DAEBFA;
}
}
&-dropdown-icon {
display: inline-block;
margin-right: 16px;
& > svg {
fill: #1C2025;
}
}
&-dropdown-container {
& > div > div:nth-child(2) > div > div {
background: #fff;
padding: 0;
}
}
}

View File

@@ -0,0 +1,194 @@
/**
* Shared style for full screen local track based dialogs/modals.
*/
.premeeting-screen {
align-items: stretch;
background: #1C2025;
bottom: 0;
display: flex;
flex-direction: column;
font-size: 1.3em;
left: 0;
position: absolute;
right: 0;
top: 0;
z-index: $toolbarZ + 1;
.content {
align-items: center;
background-image: linear-gradient(transparent, black);
display: flex;
flex: 1;
flex-direction: column;
justify-content: flex-end;
z-index: $toolbarZ + 2;
.title {
color: #fff;
font-size: 24px;
line-height: 32px;
margin-bottom: 16px;
}
.copy-meeting {
align-items: center;
cursor: pointer;
color: #fff;
display: flex;
flex-direction: row;
font-size: 15px;
font-weight: 300;
justify-content: center;
line-height: 24px;
.url {
display: flex;
padding: 8px 10px;
&:hover {
background: #1C2025;
border-radius: 4px;
}
&.done {
background: #31B76A;
}
.jitsi-icon {
margin-left: 10px;
}
}
&:hover {
align-self: stretch;
}
textarea {
border-width: 0;
height: 0;
opacity: 0;
padding: 0;
width: 0;
}
}
input.field {
background-color: transparent;
border: 1px solid transparent;
color: white;
outline-width: 0;
padding: 20px;
text-align: center;
&.focused {
border-bottom: 1px solid white;
}
&.error::placeholder {
color: $defaultWarningColor;
}
}
.action-btn {
border-radius: 3px;
color: #fff;
cursor: pointer;
display: inline-block;
font-size: 15px;
line-height: 24px;
margin: 10px;
padding: 7px 16px;
position: relative;
text-align: center;
width: 286px;
&.primary {
background: #0376DA;
border: 1px solid #0376DA;
}
&.secondary {
background: transparent;
border: 1px solid #5E6D7A;
}
&.text {
width: auto;
font-size: 13px;
margin: 0;
padding: 0;
}
&.disabled {
background: #5E6D7A;
border: 1px solid #5E6D7A;
color: #AFB6BC;
cursor: initial;
.icon {
& > svg {
fill: #AFB6BC;
}
}
.options {
border-left: 1px solid #AFB6BC;
}
}
.options {
align-items: center;
border-left: 1px solid #fff;
display: flex;
height: 100%;
justify-content: center;
position: absolute;
right: 0;
top: 0;
width: 40px;
}
}
}
.media-btn-container {
display: flex;
justify-content: center;
margin: 32px 0;
width: 100%;
&> div {
margin: 0 12px;
}
.settings-button-small-icon {
right: -8px;
&--hovered {
right: -10px;
}
}
}
}
#preview {
height: 100%;
position: absolute;
width: 100%;
&.no-video {
background: radial-gradient(50% 50% at 50% 50%, #5B6F80 0%, #365067 100%), #FFFFFF;
text-align: center;
}
.avatar {
background: #A4B8D1;
margin: 200px auto 0 auto;
}
video {
height: 100%;
object-fit: cover;
position: absolute;
width: 100%;
}
}

View File

@@ -71,6 +71,11 @@
display: flex;
margin-top: 5px;
text-align: right;
flex-direction: column;
.help-container {
display: flex;
}
}
.live-stream-cta {

View File

@@ -57,6 +57,7 @@
width: 16px;
&> svg {
fill: #5e6d7a;
margin-top: 5px;
}

View File

@@ -101,7 +101,6 @@ $sidebarWidth: 375px;
* Misc.
*/
$borderRadius: 4px;
$defaultWatermarkLink: '../images/watermark.png';
$popoverMenuPadding: 13px;
$happySoftwareBackground: transparent;
$desktopAppDragBarHeight: 25px;
@@ -270,4 +269,3 @@ $chromeExtensionBannerTop: 80px;
$chromeExtensionBannerRight: 16px;
$chromeExtensionBannerTopInMeeting: 10px;
$chromeExtensionBannerRightInMeeeting: 10px;

View File

@@ -1,6 +1,11 @@
.video-preview {
background: none;
max-height: 290px;
overflow: auto;
&-container {
overflow: auto;
padding: 16px;
}
&-entry {
cursor: pointer;
@@ -60,6 +65,6 @@
// Override @atlaskit/InlineDialog container which is made with styled components
& > div > div:nth-child(2) > div > div {
outline: none;
padding: 16px;
padding: 0;
}
}

View File

@@ -71,9 +71,6 @@ body.welcome-page {
text-align: left;
color: #253858;
height: fit-content;
border-width: $welcomePageEnterRoomInputContainerBorderWidth;
border-style: $welcomePageEnterRoomInputContainerBorderStyle;
border-image: $welcomePageEnterRoomInputContainerBorderImage;
.enter-room-title {
display: $welcomePageEnterRoomTitleDisplay;
@@ -83,12 +80,26 @@ body.welcome-page {
}
.enter-room-input {
border: none;
border-width: $welcomePageEnterRoomInputContainerBorderWidth;
border-style: $welcomePageEnterRoomInputContainerBorderStyle;
border-image: $welcomePageEnterRoomInputContainerBorderImage;
display: inline-block;
width: 100%;
font-size: 14px;
}
.insecure-room-name-warning {
align-items: center;
color: $defaultWarningColor;
display: flex;
flex-direction: row;
margin-top: 5px;
svg {
fill: $defaultWarningColor
}
}
::placeholder {
color: #253858;
}

View File

@@ -15,8 +15,9 @@
box-sizing: border-box;
display: flex;
flex-direction: column;
height: 100vh;
height: calc(100vh - 200px);
width: 100vw;
margin: 100px 0px;
}
.filmstrip__videos .videocontainer {
@@ -77,9 +78,9 @@
box-sizing: border-box;
display: flex;
flex-wrap: wrap;
height: 100vh;
margin-top: auto;
margin-bottom: auto;
justify-content: center;
padding: 100px 0;
.videocontainer {
border: 0;

View File

@@ -40,9 +40,6 @@
#remotePresenceMessage {
display: none !important;
}
#largeVideoContainer {
background-color: $defaultBackground !important;
}
/**
* Thumbnail popover menus can overlap other thumbnails. Setting an auto

View File

@@ -75,6 +75,8 @@ $flagsImagePath: "../images/";
@import 'filmstrip/tile_view_overrides';
@import 'filmstrip/vertical_filmstrip';
@import 'filmstrip/vertical_filmstrip_overrides';
@import 'labels';
@import 'lobby';
@import 'unsupported-browser/main';
@import 'modals/invite/add-people';
@import 'deep-linking/main';
@@ -90,5 +92,11 @@ $flagsImagePath: "../images/";
@import 'meter';
@import 'audio-preview';
@import 'video-preview';
@import 'prejoin';
@import 'prejoin-dialog';
@import 'country-picker';
@import 'modals/invite/invite_more';
@import 'modals/security/security';
@import 'premeeting-screens';
/* Modules END */

View File

@@ -3,6 +3,7 @@
*/
.modal-dialog-form {
.add-people-form-wrap {
margin-top: 8px;
.error {
padding-left: 5px;

View File

@@ -3,47 +3,6 @@
display: flex;
font-size: 14px;
.info-dialog-action-link {
display: inline-block;
line-height: 1.5em;
a {
cursor: pointer;
vertical-align: middle;
}
}
.info-dialog-action-link:before {
color: $linkFontColor;
content: '\2022';
font-size: 1.5em;
padding: 0 10px;
vertical-align: middle;
}
.info-dialog-action-link:first-child:before {
content: '';
padding: 0;
}
.info-dialog-action-links {
font-weight: bold;
margin-top: 10px;
white-space: nowrap;
}
.info-dialog-action-separator {
display: inline-block;
}
.info-dialog-copy-element {
opacity: 0;
pointer-events: none;
position: absolute;
-webkit-user-select: text;
user-select: text;
}
.info-dialog-column {
margin-right: 10px;
overflow: hidden;
@@ -56,52 +15,6 @@
}
}
.info-dialog-conference-url,
.info-dialog-live-stream-url {
width: max-content;
width: -moz-max-content;
width: -webkit-max-content;
word-break: break-all;
max-width: 400px;
display: flex;
align-items: center;
}
.info-dialog-dial-in {
word-break: break-all;
.conference-id,
.phone-number {
user-select: text;
}
}
.info-dialog-icon {
color: #6453C0;
font-size: 16px;
min-width: 30px;
}
.info-dialog-url-text,
.info-dialog-url-text:hover {
color: inherit;
cursor: inherit;
}
.info-dialog-url-icon {
display: inline-block;
margin-left: 5px;
svg {
cursor: pointer;
}
}
.info-dialog-title {
font-weight: bold;
margin-bottom: 10px;
}
.info-dialog-password,
.info-password,
.info-password-form {
@@ -125,6 +38,7 @@
}
.info-password-input {
width: 100%;
background-color: transparent;
border: none;
color: inherit;
@@ -223,10 +137,4 @@
-moz-user-select: text;
-webkit-user-select: text;
}
.info-dialog-url-text-unselectable {
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
}
}

View File

@@ -0,0 +1,252 @@
.invite-more {
&-container {
color: #fff;
font-weight: 600;
position: absolute;
width: 100%;
text-align: center;
z-index: $zindex2;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
&.elevated {
z-index: $filmstripVideosZ + 1;
}
}
&-header {
font-size: 19px;
line-height: 28px;
margin: 24px 0 16px 0;
}
&-button {
display: flex;
margin: auto;
padding: 8px 16px;
width: fit-content;
width: -moz-fit-content;
height: 24px;
background: #0376DA;
border-radius: 3px;
font-size: 14px;
line-height: 24px;
cursor: pointer;
&:hover {
background: #278ADF;
}
&-text {
margin-left: 8px;
font-size: 15px;
line-height: 24px;
}
}
&-dialog {
color: #fff;
font-size: 15px;
line-height: 24px;
& > span {
font-weight: 600;
}
&.header {
display: flex;
justify-content: space-between;
margin: 16px 16px 24px;
width: calc(100% - 32px);
color: #fff;
font-weight: 600;
font-size: 24px;
line-height: 32px;
& > div > svg {
cursor: pointer;
fill: #A4B8D1;
}
}
&.copy-link {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 8px 8px 16px;
margin-top: 8px;
width: calc(100% - 24px);
height: 24px;
background: #0376DA;
border-radius: 4px;
cursor: pointer;
&:hover {
background: #278ADF;
font-weight: 600;
}
&-text {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 292px;
&.selected {
font-weight: 600;
}
}
&.clicked {
background: #31B76A;
}
& > div > svg > path {
fill: #fff;
}
}
&.separator {
margin: 24px 0 24px -20px;
padding: 0 20px;
width: 100%;
height: 1px;
background: #5E6D7A;
}
&.email-container {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 8px 8px 16px;
margin-top: 24px;
width: calc(100% - 26px);
height: 22px;
background: #2A3A4B;
border: 1px solid #5E6D7A;
border-radius: 3px;
cursor: pointer;
&.active {
border-radius: 3px 3px 0 0;
}
}
&.icon-container {
display: none;
&.active {
display: flex;
width: calc(100% - 26px);
padding: 8px 8px 8px 16px;
background: #2A3A4B;
border: 1px solid #5E6D7A;
border-top: none;
border-radius: 0 0 3px 3px;
& > * {
display: flex;
justify-content: center;
align-items: center;
height: 40px;
width: 40px;
border-radius: 4px;
cursor: pointer;
}
&:hover > div:hover {
background-color: rgba(255, 255, 255, 0.2);
}
& > :not(:last-child) {
margin-right: 16px;
}
.copy-invite-icon > div > svg > path {
fill: #A4B8D1;
}
}
}
&.dial-in-display {
.info-label {
color: #A4B8D1;
}
.dial-in-copy {
display: inline-block;
vertical-align: middle;
margin-left: 21px;
cursor: pointer;
}
}
&.invite-buttons {
width: 100%;
text-align: right;
margin-top: 8px;
& > a {
display: inline-block;
height: 24px;
width: 48px;
border-radius: 3px;
text-align: center;
text-decoration: none;
cursor: pointer;
}
&-cancel {
margin-right: 16px;
padding: 7px 15px;
background: #2A3A4B;
border: 1px solid #5E6D7A;
}
&-add {
padding: 8px 16px;
background: #0376DA;
}
}
&.stream {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 8px 8px 16px;
margin-top: 8px;
width: calc(100% - 26px);
height: 22px;
background: #2A3A4B;
border: 1px solid #5E6D7A;
border-radius: 3px;
cursor: pointer;
&:hover {
font-weight: 600;
}
&-text {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 292px;
&.selected {
font-weight: 600;
}
}
&.clicked {
background: #31B76A;
border: 1px solid #31B76A;
}
& > div > svg > path {
fill: #fff;
}
}
}
}

View File

@@ -0,0 +1,59 @@
.security {
&-dialog {
color: #fff;
font-size: 15px;
line-height: 24px;
&.password-section {
display: flex;
flex-direction: column;
.password {
align-items: center;
display: flex;
justify-content: space-between;
margin-top: 15px;
&-actions {
a {
cursor: pointer;
text-decoration: none;
font-size: 14px;
color: #6FB1EA;
}
&>a+a {
margin-left: 24px;
}
}
}
}
&> :first-child:not(:last-child) {
margin-right: 24px;
}
.separator-line {
margin: 24px 0 24px -20px;
padding: 0 20px;
width: 100%;
height: 1px;
background: #5E6D7A;
&:last-child {
display: none;
}
}
}
}
.new-toolbox .toolbox-content .toolbox-icon.security-toolbar-button,
.new-toolbox .toolbox-content .toolbox-icon.toggled.security-toolbar-button {
background: rgba(241, 173, 51, 0.7);
border: 1px solid rgba(255, 255, 255, 0.4);
&:hover {
background: rgba(241, 173, 51, 0.7);
border: 1px solid rgba(255, 255, 255, 0.4);
}
}

View File

@@ -144,58 +144,3 @@
#videoResolutionLabel {
z-index: $zindex3 + 1;
}
.large-video-labels {
display: flex;
position: absolute;
top: 30px;
right: 30px;
transition: right 0.5s;
z-index: $zindex3;
.circular-label {
color: white;
font-weight: bold;
margin-left: 8px;
opacity: 0.8;
}
.circular-label {
background: #B8C7E0;
}
.circular-label.file {
background: #FF5630;
}
.circular-label.local-rec {
background: #FF5630;
}
.circular-label.stream {
background: #0065FF;
}
.recording-label.center-message {
background: $videoStateIndicatorBackground;
bottom: 50%;
display: block;
left: 50%;
padding: 10px;
position: fixed;
transform: translate(-50%, -50%);
z-index: $centeredVideoLabelZ;
}
}
.circular-label {
background: $videoStateIndicatorBackground;
border-radius: 50%;
box-sizing: border-box;
cursor: default;
font-size: 13px;
height: $videoStateIndicatorSize;
line-height: $videoStateIndicatorSize;
text-align: center;
min-width: $videoStateIndicatorSize;
}

3
debian/control vendored
View File

@@ -3,7 +3,7 @@ Section: net
Priority: extra
Maintainer: Jitsi Team <dev@jitsi.org>
Uploaders: Emil Ivov <emcho@jitsi.org>, Damian Minkov <damencho@jitsi.org>
Build-Depends: debhelper (>= 8.0.0)
Build-Depends: debhelper (>= 8.0.0), nodejs
Standards-Version: 3.9.6
Homepage: https://jitsi.org/meet
@@ -53,5 +53,6 @@ Description: Prosody token authentication plugin for Jitsi Meet
Package: jitsi-meet-turnserver
Architecture: all
Breaks: apache2
Pre-Depends: jitsi-meet-web-config
Depends: ${misc:Depends}, nginx (>= 1.13.10) | nginx-full (>= 1.13.10) | nginx-extras (>= 1.13.10), jitsi-meet-prosody, coturn, dnsutils
Description: Configures coturn to be used with Jitsi Meet

View File

@@ -17,6 +17,9 @@ set -e
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
function generateRandomPassword() {
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 16
}
case "$1" in
configure)
@@ -51,7 +54,7 @@ case "$1" in
db_get jicofo/jicofo-authpassword
if [ -z "$RET" ] ; then
# if password is missing generate it, and store it
JICOFO_AUTH_PASSWORD=`head -c 8 /dev/urandom | tr '\0-\377' 'a-zA-Z0-9a-zA-Z0-9a-zA-Z0-9a-zA-Z0-9@@@@####'`
JICOFO_AUTH_PASSWORD=`generateRandomPassword`
db_set jicofo/jicofo-authpassword "$JICOFO_AUTH_PASSWORD"
else
JICOFO_AUTH_PASSWORD="$RET"
@@ -60,7 +63,7 @@ case "$1" in
db_get jicofo/jicofosecret
if [ -z "$RET" ] ; then
# if secret is missing generate it, and store it
JICOFO_SECRET=`head -c 8 /dev/urandom | tr '\0-\377' 'a-zA-Z0-9a-zA-Z0-9a-zA-Z0-9a-zA-Z0-9@@@@####'`
JICOFO_SECRET=`generateRandomPassword`
db_set jicofo/jicofosecret "$JICOFO_SECRET"
else
JICOFO_SECRET="$RET"
@@ -83,7 +86,7 @@ case "$1" in
db_get jitsi-meet-prosody/turn-secret
if [ -z "$RET" ] ; then
# 8-chars random secret used for the turnserver
TURN_SECRET=`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1`
TURN_SECRET=`generateRandomPassword`
db_set jitsi-meet-prosody/turn-secret "$TURN_SECRET"
else
TURN_SECRET="$RET"
@@ -134,7 +137,7 @@ case "$1" in
# as we are migrating configs
if [ -f $PROSODY_HOST_CONFIG ] && ! grep -q "internal.auth.$JVB_HOSTNAME" $PROSODY_HOST_CONFIG; then
echo -e "\nComponent \"internal.auth.$JVB_HOSTNAME\" \"muc\"" >> $PROSODY_HOST_CONFIG
echo -e " storage = \"null\"" >> $PROSODY_HOST_CONFIG
echo -e " storage = \"memory\"" >> $PROSODY_HOST_CONFIG
echo -e " modules_enabled = { \"ping\"; }" >> $PROSODY_HOST_CONFIG
echo -e " admins = { \"$JICOFO_AUTH_USER@auth.$JVB_HOSTNAME\", \"jvb@auth.$JVB_HOSTNAME\" }" >> $PROSODY_HOST_CONFIG
fi
@@ -148,14 +151,13 @@ case "$1" in
ln -sf /var/lib/prosody/$JVB_HOSTNAME.crt /etc/prosody/certs/$JVB_HOSTNAME.crt
fi
PR11_INSTALL_CHECK="$(dpkg-query -f '${Status}' -W 'prosody-0.11' 2>/dev/null | awk '{print $3}' || true)"
PRTRUNK_INSTALL_CHECK="$(dpkg-query -f '${Status}' -W 'prosody-trunk' 2>/dev/null | awk '{print $3}' || true)"
PR10_INSTALL_CHECK="$(dpkg-query -f '${Status}' -W 'prosody-0.10' 2>/dev/null | awk '{print $3}' || true)"
PR_VER_INSTALLED=$(dpkg-query -f='${Version}\n' --show prosody 2>/dev/null || true)
if [ "$PR11_INSTALL_CHECK" = "installed" ] \
|| [ "$PR11_INSTALL_CHECK" = "unpacked" ] \
|| dpkg --compare-versions "$PR_VER_INSTALLED" gt "0.11" ; then
if [ "$PRTRUNK_INSTALL_CHECK" = "installed" ] \
|| [ "$PRTRUNK_INSTALL_CHECK" = "unpacked" ] ; then
if [ -f $PROSODY_HOST_CONFIG ]; then
sed -i 's/storage = \"null\"/storage = \"memory\"/g' $PROSODY_HOST_CONFIG
sed -i 's/storage = \"memory\"/storage = \"null\"/g' $PROSODY_HOST_CONFIG
# trigger a restart
PROSODY_CONFIG_PRESENT="false"
@@ -168,7 +170,7 @@ case "$1" in
# if the version is 0.10.X (>0.10 and <0.11)
if [ -f $PROSODY_HOST_CONFIG ] \
&& dpkg --compare-versions "$PR_VER_INSTALLED" lt "0.11" ; then
sed -i 's/storage = \"null\"/storage = \"none\"/g' $PROSODY_HOST_CONFIG
sed -i 's/storage = \"memory\"/storage = \"none\"/g' $PROSODY_HOST_CONFIG
# trigger a restart
PROSODY_CONFIG_PRESENT="false"

View File

@@ -69,12 +69,15 @@ case "$1" in
echo "Failed to install basexx - try installing it manually"
fi
PR11_INSTALL_CHECK="$(dpkg-query -f '${Status}' -W 'prosody-0.11' 2>/dev/null | awk '{print $3}' || true)"
PR10_INSTALL_CHECK="$(dpkg-query -f '${Status}' -W 'prosody-0.10' 2>/dev/null | awk '{print $3}' || true)"
PRTRUNK_INSTALL_CHECK="$(dpkg-query -f '${Status}' -W 'prosody-trunk' 2>/dev/null | awk '{print $3}' || true)"
PR_VER_INSTALLED=$(dpkg-query -f='${Version}\n' --show prosody 2>/dev/null || true)
if [ "$PR11_INSTALL_CHECK" = "installed" ] \
|| [ "$PR11_INSTALL_CHECK" = "unpacked" ] \
|| dpkg --compare-versions "$PR_VER_INSTALLED" gt "0.11" ; then
sed -i 's/module:hook/module:hook_global/g' /usr/share/jitsi-meet/prosody-plugins/mod_auth_token.lua
if [ "$PR10_INSTALL_CHECK" = "installed" ] \
|| "$PR10_INSTALL_CHECK" = "unpacked" \
|| "$PRTRUNK_INSTALL_CHECK" = "installed" \
|| "$PRTRUNK_INSTALL_CHECK" = "unpacked" \
|| dpkg --compare-versions "$PR_VER_INSTALLED" lt "0.11" ; then
sed -i 's/module:hook_global(/module:hook(/g' /usr/share/jitsi-meet/prosody-plugins/mod_auth_token.lua
fi
if [ -x "/etc/init.d/prosody" ]; then

View File

@@ -1,2 +1,3 @@
doc/debian/jitsi-meet-turn/turnserver.conf /usr/share/jitsi-meet-turnserver/
doc/debian/jitsi-meet/jitsi-meet.conf /usr/share/jitsi-meet-turnserver/
doc/debian/jitsi-meet-turn/turnserver.conf /usr/share/jitsi-meet-turnserver/
doc/debian/jitsi-meet/jitsi-meet.conf /usr/share/jitsi-meet-turnserver/
doc/debian/jitsi-meet-turn/coturn-certbot-deploy.sh /usr/share/jitsi-meet-turnserver/

View File

@@ -38,6 +38,7 @@ case "$1" in
NGINX_SITES_ENABLED="/etc/nginx/sites-enabled/"
NGINX_CONFIG_ENABLED="${NGINX_SITES_ENABLED}${JVB_HOSTNAME}.conf"
NGINX_MULTIPLEXING="true"
for site in ${NGINX_SITES_ENABLED}*; do
# if it is not a file continue
[ -f "${site}" ] || continue
@@ -48,11 +49,10 @@ case "$1" in
# nothing to do
echo "------------------------------------------------"
echo ""
echo "turnserver not configured as other nginx sites use port 443"
echo "turnserver is listening on tcp 4445 as other nginx sites use port 443"
echo ""
echo "------------------------------------------------"
db_stop
exit 0
NGINX_MULTIPLEXING="false"
fi
done
@@ -77,7 +77,7 @@ case "$1" in
# nothing to do
echo "------------------------------------------------"
echo ""
echo "turnserver not configured as no nginx found to multiplex traffic"
echo "turnserver not configured"
echo ""
echo "------------------------------------------------"
db_stop
@@ -106,18 +106,19 @@ case "$1" in
TURN_SECRET="$RET"
# no turn config exists, lt's copy template and fill it in
PUBLIC_IP=$(dig +short myip.opendns.com @resolver1.opendns.com)
PUBLIC_IP=$(dig -4 +short myip.opendns.com a @resolver1.opendns.com) || true
if [ -z "$PUBLIC_IP" ] ; then
PUBLIC_IP="127.0.0.1"
echo "------------------------------------------------"
echo "Warning! Could not resolve your external ip address! Error:^"
echo "Your turn server will not work till you edit your $TURN_CONFIG config file."
echo "You need to set your external ip address in external-ip and restart coturn service."
echo "------------------------------------------------"
fi
cp /usr/share/jitsi-meet-turnserver/turnserver.conf $TURN_CONFIG
sed -i "s/jitsi-meet.example.com/$JVB_HOSTNAME/g" $TURN_CONFIG
sed -i "s/__turnSecret__/$TURN_SECRET/g" $TURN_CONFIG
sed -i "s/__external_ip_address__/$JVB_HOSTNAME/g" $TURN_CONFIG
# Hack Debian Buster coturn to be able to bind privileged port 443
COTURN_UNIT_FILE="/lib/systemd/system/coturn.service"
if [[ -f $COTURN_UNIT_FILE ]] && ! grep -q "CAP_NET_BIND_SERVICE" "$COTURN_UNIT_FILE" ; then
sed -i "s/\[Service\]/\[Service\]\nAmbientCapabilities=CAP_NET_BIND_SERVICE/g" $COTURN_UNIT_FILE
systemctl daemon-reload
fi
sed -i "s/__external_ip_address__/$PUBLIC_IP/g" $TURN_CONFIG
# SSL for nginx
db_get jitsi-meet/cert-choice
@@ -142,11 +143,18 @@ case "$1" in
invoke-rc.d coturn restart || true
NGINX_STREAM_CONFIG="/etc/nginx/modules-enabled/60-jitsi-meet.conf"
if [ ! -f $NGINX_STREAM_CONFIG ] && [ -f $NGINX_CONFIG ] ; then
if [ $NGINX_MULTIPLEXING = "true" ] && [ ! -f $NGINX_STREAM_CONFIG ] && [ -f $NGINX_CONFIG ] ; then
ln -s /usr/share/jitsi-meet-turnserver/jitsi-meet.conf $NGINX_STREAM_CONFIG
sed -i "s/listen 443 ssl/listen 4444 ssl http2/g" $NGINX_CONFIG
sed -i "s/listen \[\:\:\]\:443 ssl/listen \[\:\:\]\:4444 ssl http2/g" $NGINX_CONFIG
invoke-rc.d nginx reload || true
else
PROSODY_HOST_CONFIG="/etc/prosody/conf.avail/$JVB_HOSTNAME.cfg.lua"
if [ -f $PROSODY_HOST_CONFIG ] ; then
# If we are not multiplexing we need to change the port in prosody config
sed -i 's/"443"/"4445"/g' $PROSODY_HOST_CONFIG
invoke-rc.d prosody restart || true
fi
fi
# Enable turn server in config.js

View File

@@ -1,43 +1,3 @@
# Documentation
This document is the entrypoint to different guides, divided in three groups:
* User guide: these documents are designed to help users of the service, to better
understand all the available features and how to use them.
* Developer guide: these documents are designed to help developers who want to either
integrate the Jitsi Meet API / SDK in their products or want to improve Jitsi Meet
itself by developing new features or fixing bugs.
* DevOps guide: these documents are designed for DevOps folks, system administrators
or anyone who wishes to deploy and operate their own Jitsi Meet instance.
## User guide
Work in progress.
## Developer guide
### Web
* [iframe API](https://github.com/jitsi/jitsi-meet/blob/master/doc/api.md)
* [Jitsi Meet development](https://github.com/jitsi/jitsi-meet/blob/master/doc/development.md)
### Mobile
* [Building the mobile apps](https://github.com/jitsi/jitsi-meet/blob/master/doc/mobile.md)
* [SDK usage examples](https://github.com/jitsi/jitsi-meet-sdk-samples)
* [Enabling Dropbox support](https://github.com/jitsi/jitsi-meet/blob/master/doc/mobile-dropbox.md)
* [Enabling Google authentication](https://github.com/jitsi/jitsi-meet/blob/master/doc/mobile-google-auth.md)
## DevOps guide
* [Quick install](https://github.com/jitsi/jitsi-meet/blob/master/doc/quick-install.md)
* [Docker install](https://github.com/jitsi/docker-jitsi-meet/blob/master/README.md)
* [Google Calendar, MS Calendar, Dropbox integrations](https://github.com/jitsi/jitsi-meet/blob/master/doc/integrations.md)
* [Video tutorials on deployment and scalability](https://jitsi.org/tutorials/)
* [Configuring a video SIP gateway](https://github.com/jitsi/jitsi-meet/blob/master/doc/sipgw-config.md)
* [Enabling speaker stats](https://github.com/jitsi/jitsi-meet/blob/master/doc/speakerstats-prosody.md)
* [Enabling TURN](https://github.com/jitsi/jitsi-meet/blob/master/doc/turn.md)
* [Networking FAQ](https://github.com/jitsi/jitsi-meet/blob/master/doc/faq.md)
* [Cloud APIs](https://github.com/jitsi/jitsi-meet/blob/master/doc/cloud-api.md)
The Jitsi documentation has been moved to [The Handbook](https://jitsi.github.io/handbook/).

View File

@@ -1,618 +1,3 @@
# Jitsi Meet API
You can use the Jitsi Meet API to embed Jitsi Meet in to your application. You are also welcome to use it for embedding the globally distributed and highly available deployment on meet.jit.si itself. The only thing we ask for in that case is that you please DO NOT remove the jitsi.org logo from the top left corner.
## Installation
To embed Jitsi Meet in your application you need to add the Jitsi Meet API library:
```javascript
<script src='https://meet.jit.si/external_api.js'></script>
```
## API
### `api = new JitsiMeetExternalAPI(domain, options)`
The next step for embedding Jitsi Meet is to create the Jitsi Meet API object.
Its constructor gets a number of options:
* **domain**: domain used to build the conference URL, 'meet.jit.si' for
example.
* **options**: object with properties - the optional arguments:
* **roomName**: (optional) name of the room to join.
* **width**: (optional) width for the iframe which will be created. If a number is specified it's treated as pixel units. If a string is specified the format is number followed by 'px', 'em', 'pt' or '%'.
* **height**: (optional) height for the iframe which will be created. If a number is specified it's treated as pixel units. If a string is specified the format is number followed by 'px', 'em', 'pt' or '%'.
* **parentNode**: (optional) HTML DOM Element where the iframe will be added as a child.
* **configOverwrite**: (optional) JS object with overrides for options defined in [config.js].
* **interfaceConfigOverwrite**: (optional) JS object with overrides for options defined in [interface_config.js].
* **noSSL**: (optional, defaults to true) Boolean indicating if the server should be contacted using HTTP or HTTPS.
* **jwt**: (optional) [JWT](https://jwt.io/) token.
* **onload**: (optional) handler for the iframe onload event.
* **invitees**: (optional) Array of objects containing information about new participants that will be invited in the call.
* **devices**: (optional) A map containing information about the initial devices that will be used in the call.
* **userInfo**: (optional) JS object containing information about the participant opening the meeting, such as `email`.
Example:
```javascript
const domain = 'meet.jit.si';
const options = {
roomName: 'JitsiMeetAPIExample',
width: 700,
height: 700,
parentNode: document.querySelector('#meet')
};
const api = new JitsiMeetExternalAPI(domain, options);
```
You can set the initial media devices for the call:
```javascript
const domain = 'meet.jit.si';
const options = {
...
devices: {
audioInput: '<deviceLabel>',
audioOutput: '<deviceLabel>',
videoInput: '<deviceLabel>'
},
...
};
const api = new JitsiMeetExternalAPI(domain, options);
```
You can overwrite options set in [config.js] and [interface_config.js].
For example, to enable the filmstrip-only interface mode, you can use:
```javascript
const options = {
...
interfaceConfigOverwrite: { filmStripOnly: true },
...
};
const api = new JitsiMeetExternalAPI(domain, options);
```
You can also pass a jwt token to Jitsi Meet:
```javascript
const options = {
...
jwt: '<jwt_token>',
noSsl: false,
...
};
const api = new JitsiMeetExternalAPI(domain, options);
```
You can set the userInfo(email) for the call:
```javascript
var domain = "meet.jit.si";
var options = {
...
userInfo: {
email: 'email@jitsiexamplemail.com'
}
}
var api = new JitsiMeetExternalAPI(domain, options);
```
### Controlling the embedded Jitsi Meet Conference
Device management `JitsiMeetExternalAPI` methods:
* **getAvailableDevices** - Retrieve a list of available devices.
```javascript
api.getAvailableDevices().then(devices => {
// devices = {
// audioInput: [{
// deviceId: 'ID'
// groupId: 'grpID'
// kind: 'audioinput'
// label: 'label'
// },....],
// audioOutput: [{
// deviceId: 'ID'
// groupId: 'grpID'
// kind: 'audioOutput'
// label: 'label'
// },....],
// videoInput: [{
// deviceId: 'ID'
// groupId: 'grpID'
// kind: 'videoInput'
// label: 'label'
// },....]
// }
...
});
```
* **getCurrentDevices** - Retrieve a list with the devices that are currently selected.
```javascript
api.getCurrentDevices().then(devices => {
// devices = {
// audioInput: {
// deviceId: 'ID'
// groupId: 'grpID'
// kind: 'videoInput'
// label: 'label'
// },
// audioOutput: {
// deviceId: 'ID'
// groupId: 'grpID'
// kind: 'videoInput'
// label: 'label'
// },
// videoInput: {
// deviceId: 'ID'
// groupId: 'grpID'
// kind: 'videoInput'
// label: 'label'
// }
// }
...
});
```
* **isDeviceChangeAvailable** - Resolves with true if the device change is available and with false if not.
```javascript
// The accepted deviceType values are - 'output', 'input' or undefined.
api.isDeviceChangeAvailable(deviceType).then(isDeviceChangeAvailable => {
...
});
```
* **isDeviceListAvailable** - Resolves with true if the device list is available and with false if not.
```javascript
api.isDeviceListAvailable().then(isDeviceListAvailable => {
...
});
```
* **isMultipleAudioInputSupported** - Resolves with true if multiple audio input is supported and with false if not.
```javascript
api.isMultipleAudioInputSupported().then(isMultipleAudioInputSupported => {
...
});
```
* **setAudioInputDevice** - Sets the audio input device to the one with the label or id that is passed.
```javascript
api.setAudioInputDevice(deviceLabel, deviceId);
```
* **setAudioOutputDevice** - Sets the audio output device to the one with the label or id that is passed.
```javascript
api.setAudioOutputDevice(deviceLabel, deviceId);
```
* **setVideoInputDevice** - Sets the video input device to the one with the label or id that is passed.
```javascript
api.setVideoInputDevice(deviceLabel, deviceId);
```
You can control the embedded Jitsi Meet conference using the `JitsiMeetExternalAPI` object by using `executeCommand`:
```javascript
api.executeCommand(command, ...arguments);
```
The `command` parameter is String object with the name of the command. The following commands are currently supported:
* **displayName** - Sets the display name of the local participant. This command requires one argument - the new display name to be set.
```javascript
api.executeCommand('displayName', 'New Nickname');
```
* **password** - Sets the password for the room. This command requires one argument - the password name to be set.
```javascript
api.executeCommand('password', 'The Password');
```
* **sendTones** - Play touch tones.
```javascript
api.executeCommand('sendTones', {
tones: string, // The dial pad touch tones to play. For example, '12345#'.
duration: number, // Optional. The number of milliseconds each tone should play. The default is 200.
pause: number // Optional. The number of milliseconds between each tone. The default is 200.
});
```
* **subject** - Sets the subject of the conference. This command requires one argument - the new subject to be set.
```javascript
api.executeCommand('subject', 'New Conference Subject');
```
* **toggleAudio** - Mutes / unmutes the audio for the local participant. No arguments are required.
```javascript
api.executeCommand('toggleAudio');
```
* **toggleVideo** - Mutes / unmutes the video for the local participant. No arguments are required.
```javascript
api.executeCommand('toggleVideo');
```
* **toggleFilmStrip** - Hides / shows the filmstrip. No arguments are required.
```javascript
api.executeCommand('toggleFilmStrip');
```
* **toggleChat** - Hides / shows the chat. No arguments are required.
```javascript
api.executeCommand('toggleChat');
```
* **toggleShareScreen** - Starts / stops screen sharing. No arguments are required.
```javascript
api.executeCommand('toggleShareScreen');
```
* **toggleTileView** - Enter / exit tile view layout mode. No arguments are required.
```javascript
api.executeCommand('toggleTileView');
```
* **hangup** - Hangups the call. No arguments are required.
```javascript
api.executeCommand('hangup');
```
* **email** - Changes the local email address. This command requires one argument - the new email address to be set.
```javascript
api.executeCommand('email', 'example@example.com');
```
* **avatarUrl** - Changes the local avatar URL. This command requires one argument - the new avatar URL to be set.
```javascript
api.executeCommand('avatarUrl', 'https://avatars0.githubusercontent.com/u/3671647');
```
* **sendEndpointTextMessage** - Sends a text message to another participant through the datachannels.
```javascript
api.executeCommand('receiverParticipantId', 'text');
```
You can also execute multiple commands using the `executeCommands` method:
```javascript
api.executeCommands(commands);
```
The `commands` parameter is an object with the names of the commands as keys and the arguments for the commands as values:
```javascript
api.executeCommands({
displayName: [ 'nickname' ],
toggleAudio: []
});
```
You can add event listeners to the embedded Jitsi Meet using the `addEventListener` method.
**NOTE: This method still exists but it is deprecated. JitsiMeetExternalAPI class extends [EventEmitter]. Use [EventEmitter] methods (`addListener` or `on`).**
```javascript
api.addEventListener(event, listener);
```
The `event` parameter is a String object with the name of the event.
The `listener` parameter is a Function object with one argument that will be notified when the event occurs with data related to the event.
The following events are currently supported:
* **cameraError** - event notifications about Jitsi-Meet having failed to access the camera. The listener will receive an object with the following structure:
```javascript
{
type: string, // A constant representing the overall type of the error.
message: string // Additional information about the error.
}
```
* **avatarChanged** - event notifications about avatar
changes. The listener will receive an object with the following structure:
```javascript
{
id: string, // the id of the participant that changed his avatar.
avatarURL: string // the new avatar URL.
}
```
* **audioAvailabilityChanged** - event notifications about audio availability status changes. The listener will receive an object with the following structure:
```javascript
{
available: boolean // new available status - boolean
}
```
* **audioMuteStatusChanged** - event notifications about audio mute status changes. The listener will receive an object with the following structure:
```javascript
{
muted: boolean // new muted status - boolean
}
```
* **endpointTextMessageReceived** - event notifications about a text message received through datachannels.
The listener will receive an object with the following structure:
```javascript
{
senderInfo: {
jid: string, // the jid of the sender
id: string // the participant id of the sender
},
eventData: {
name: string // the name of the datachannel event: `endpoint-text-message`
text: string // the received text from the sender
}
}
```
* **micError** - event notifications about Jitsi-Meet having failed to access the mic. The listener will receive an object with the following structure:
```javascript
{
type: string, // A constant representing the overall type of the error.
message: string // Additional information about the error.
}
```
* **screenSharingStatusChanged** - receives event notifications about turning on/off the local user screen sharing. The listener will receive object with the following structure:
```javascript
{
on: boolean, //whether screen sharing is on
details: {
// From where the screen sharing is capturing, if known. Values which are
// passed include 'window', 'screen', 'proxy', 'device'. The value undefined
// will be passed if the source type is unknown or screen share is off.
sourceType: string|undefined
}
}
```
* **dominantSpeakerChanged** - receives event notifications about change in the dominant speaker. The listener will receive object with the following structure:
```javascript
{
id: string //participantId of the new dominant speaker
}
```
* **tileViewChanged** - event notifications about tile view layout mode being entered or exited. The listener will receive object with the following structure:
```javascript
{
enabled: boolean, // whether tile view is not displayed or not
}
```
* **incomingMessage** - Event notifications about incoming
messages. The listener will receive an object with the following structure:
```javascript
{
from: string, // The id of the user that sent the message
nick: string, // the nickname of the user that sent the message
message: string // the text of the message
}
```
* **outgoingMessage** - Event notifications about outgoing
messages. The listener will receive an object with the following structure:
```javascript
{
message: string // the text of the message
}
```
* **displayNameChange** - event notifications about display name
changes. The listener will receive an object with the following structure:
```javascript
{
id: string, // the id of the participant that changed his display name
displayname: string // the new display name
}
```
* **deviceListChanged** - event notifications about device list changes. The listener will receive an object with the following structure:
```javascript
{
devices: Object // the new list of available devices.
}
```
NOTE: The devices object has the same format as the getAvailableDevices result format.
* **emailChange** - event notifications about email
changes. The listener will receive an object with the following structure:
```javascript
{
id: string, // the id of the participant that changed his email
email: string // the new email
}
```
* **feedbackSubmitted** - event notifications about conference feedback submission
```javascript
{
error: string // The error which occurred during submission, if any.
}
```
* **filmstripDisplayChanged** - event notifications about the visibility of the filmstrip being updated.
```javascript
{
visible: boolean // Whether or not the filmstrip is displayed or hidden.
}
```
* **participantJoined** - event notifications about new participants who join the room. The listener will receive an object with the following structure:
```javascript
{
id: string, // the id of the participant
displayName: string // the display name of the participant
}
```
* **participantKickedOut** - event notifications about a participants being removed from the room. The listener will receive an object with the following structure:
```javascript
{
kicked: {
id: string, // the id of the participant removed from the room
local: boolean // whether or not the participant is the local particiapnt
},
kicker: {
id: string // the id of the participant who kicked out the other participant
}
}
```
* **participantLeft** - event notifications about participants that leave the room. The listener will receive an object with the following structure:
```javascript
{
id: string // the id of the participant
}
```
* **passwordRequired** - event notifications fired when failing to join a room because it has a password.
* **videoConferenceJoined** - event notifications fired when the local user has joined the video conference. The listener will receive an object with the following structure:
```javascript
{
roomName: string, // the room name of the conference
id: string, // the id of the local participant
displayName: string, // the display name of the local participant
avatarURL: string // the avatar URL of the local participant
}
```
* **videoConferenceLeft** - event notifications fired when the local user has left the video conference. The listener will receive an object with the following structure:
```javascript
{
roomName: string // the room name of the conference
}
```
* **videoAvailabilityChanged** - event notifications about video availability status changes. The listener will receive an object with the following structure:
```javascript
{
available: boolean // new available status - boolean
}
```
* **videoMuteStatusChanged** - event notifications about video mute status changes. The listener will receive an object with the following structure:
```javascript
{
muted: boolean // new muted status - boolean
}
```
* **readyToClose** - event notification fired when Jitsi Meet is ready to be closed (hangup operations are completed).
* **subjectChange** - event notifications about subject of conference changes.
The listener will receive an object with the following structure:
```javascript
{
subject: string // the new subject
}
```
* **suspendDetected** - event notifications about detecting suspend event in host computer.
You can also add multiple event listeners by using `addEventListeners`.
This method requires one argument of type Object. The object argument must
have the names of the events as keys and the listeners of the events as values.
**NOTE: This method still exists but it is deprecated. JitsiMeetExternalAPI class extends [EventEmitter]. Use [EventEmitter] methods.**
```javascript
function incomingMessageListener(object)
{
// ...
}
function outgoingMessageListener(object)
{
// ...
}
api.addEventListeners({
incomingMessage: incomingMessageListener,
outgoingMessage: outgoingMessageListener
});
```
If you want to remove a listener you can use `removeEventListener` method with argument the name of the event.
**NOTE: This method still exists but it is deprecated. JitsiMeetExternalAPI class extends [EventEmitter]. Use [EventEmitter] methods( `removeListener`).**
```javascript
api.removeEventListener('incomingMessage');
```
If you want to remove more than one event you can use `removeEventListeners` method with an Array with the names of the events as an argument.
**NOTE: This method still exists but it is deprecated. JitsiMeetExternalAPI class extends [EventEmitter]. Use [EventEmitter] methods.**
```javascript
api.removeEventListeners([ 'incomingMessage', 'outgoingMessageListener' ]);
```
You can get the number of participants in the conference with the following API function:
```javascript
const numberOfParticipants = api.getNumberOfParticipants();
```
You can get the avatar URL of a participant in the conference with the following API function:
```javascript
const avatarURL = api.getAvatarURL(participantId);
```
You can get the display name of a participant in the conference with the following API function:
```javascript
const displayName = api.getDisplayName(participantId);
```
You can get the email of a participant in the conference with the following API function:
```javascript
const email = api.getEmail(participantId);
```
You can get the iframe HTML element where Jitsi Meet is loaded with the following API function:
```javascript
const iframe = api.getIFrame();
```
You can check whether the audio is muted with the following API function:
```javascript
api.isAudioMuted().then(muted => {
...
});
```
You can check whether the video is muted with the following API function:
```javascript
api.isVideoMuted().then(muted => {
...
});
```
You can check whether the audio is available with the following API function:
```javascript
api.isAudioAvailable().then(available => {
...
});
```
You can check whether the video is available with the following API function:
```javascript
api.isVideoAvailable().then(available => {
...
});
```
You can invite new participants to the call with the following API function:
```javascript
api.invite([ {...}, {...}, {...} ]).then(() => {
// success
}).catch(() => {
// failure
});
```
**NOTE: The format of the invitees in the array depends on the invite service used for the deployment.**
You can remove the embedded Jitsi Meet Conference with the following API function:
```javascript
api.dispose();
```
NOTE: It's a good practice to remove the conference before the page is unloaded.
[config.js]: https://github.com/jitsi/jitsi-meet/blob/master/config.js
[interface_config.js]: https://github.com/jitsi/jitsi-meet/blob/master/interface_config.js
[EventEmitter]: https://nodejs.org/api/events.html
This document has been moved [here](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-iframe).

View File

@@ -1,5 +0,0 @@
# Jitsi Meet Cloud API
The Jitsi Meet Cloud API is a specification for services which can support the integration of Jitsi Meet into other applications, for mapping conferences for dial-in support, and for supporting directory search and user invitations to conferences.
The swagger for these services is provided in [cloud-api.swagger](cloud-api.swagger) in this same repository and directory.

View File

@@ -1,93 +0,0 @@
# Comments
* Comments documenting the source code are required.
* Comments from which documentation is automatically generated are **not**
subject to case-by-case decisions. Such comments are used, for example, on
types and their members. Examples of tools which automatically generate
documentation from such comments include JSDoc, Javadoc, Doxygen.
* Comments which are not automatically processed are strongly encouraged. They
are subject to case-by-case decisions. Such comments are often observed in
function bodies.
* Comments should be formatted as proper English sentences. Such formatting pays
attention to, for example, capitalization and punctuation.
# Duplication
* Don't copy-paste source code. Reuse it.
# Formatting
* Line length is limited to 80 characters.
* Sort by alphabetical order in order to make the addition of new entities as
easy as looking a word up in a dictionary. Otherwise, one risks duplicate
entries (with conflicting values in the cases of key-value pairs). For
example:
* Within an `import` of multiple names from a module, sort the names in
alphabetical order. (Of course, the default name stays first as required by
the `import` syntax.)
````javascript
import {
DOMINANT_SPEAKER_CHANGED,
JITSI_CLIENT_CONNECTED,
JITSI_CLIENT_CREATED,
JITSI_CLIENT_DISCONNECTED,
JITSI_CLIENT_ERROR,
JITSI_CONFERENCE_JOINED,
MODERATOR_CHANGED,
PEER_JOINED,
PEER_LEFT,
RTC_ERROR
} from './actionTypes';
````
* Within a group of imports (e.g. groups of imports delimited by an empty line
may be: third-party modules, then project modules, and eventually the
private files of a module), sort the module names in alphabetical order.
````javascript
import React, { Component } from 'react';
import { connect } from 'react-redux';
````
# Indentation
* Align `switch` and `case`/`default`. Don't indent the `case`/`default` more
than its `switch`.
````javascript
switch (i) {
case 0:
...
break;
default:
...
}
````
# Naming
* An abstraction should have one name within the project and across multiple
projects. For example:
* The instance of lib-jitsi-meet's `JitsiConnection` type should be named
`connection` or `jitsiConnection` in jitsi-meet, not `client`.
* The class `ReducerRegistry` should be defined in ReducerRegistry.js and its
imports in other files should use the same name. Don't define the class
`Registry` in ReducerRegistry.js and then import it as `Reducers` in other
files.
* The names of global constants (including ES6 module-global constants) should
be written in uppercase with underscores to separate words. For example,
`BACKGROUND_COLOR`.
* The underscore character at the beginning of a name signals that the
respective variable, function, property is non-public i.e. private, protected,
or internal. In contrast, the lack of an underscore at the beginning of a name
signals public API.

View File

@@ -6,13 +6,20 @@ muc_mapper_domain_base = "jitmeet.example.com";
turncredentials_secret = "__turnSecret__";
turncredentials = {
{ type = "stun", host = "jitmeet.example.com", port = "443" },
{ type = "turn", host = "jitmeet.example.com", port = "443", transport = "udp" },
{ type = "stun", host = "jitmeet.example.com", port = "4446" },
{ type = "turn", host = "jitmeet.example.com", port = "4446", transport = "udp" },
{ type = "turns", host = "jitmeet.example.com", port = "443", transport = "tcp" }
};
cross_domain_bosh = false;
consider_bosh_secure = true;
-- https_ports = { }; -- Remove this line to prevent listening on port 5284
-- https://ssl-config.mozilla.org/#server=haproxy&version=2.1&config=intermediate&openssl=1.1.0g&guideline=5.4
ssl = {
protocol = "tlsv1_2+";
ciphers = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"
}
VirtualHost "jitmeet.example.com"
-- enabled = false -- Remove this line to enable this host
@@ -39,11 +46,15 @@ VirtualHost "jitmeet.example.com"
"speakerstats";
"turncredentials";
"conference_duration";
"muc_lobby_rooms";
}
c2s_require_encryption = false
lobby_muc = "lobby.jitmeet.example.com"
main_muc = "conference.jitmeet.example.com"
-- muc_lobby_whitelist = { "recorder.jitmeet.example.com" } -- Here we can whitelist jibri to enter lobby enabled rooms
Component "conference.jitmeet.example.com" "muc"
storage = "null"
storage = "memory"
modules_enabled = {
"muc_meeting_id";
"muc_domain_mapper";
@@ -55,11 +66,13 @@ Component "conference.jitmeet.example.com" "muc"
-- internal muc component
Component "internal.auth.jitmeet.example.com" "muc"
storage = "null"
storage = "memory"
modules_enabled = {
"ping";
}
admins = { "focusUser@auth.jitmeet.example.com", "jvb@auth.jitmeet.example.com" }
muc_room_locking = false
muc_room_default_public_jids = true
VirtualHost "auth.jitmeet.example.com"
authentication = "internal_plain"
@@ -72,3 +85,9 @@ Component "speakerstats.jitmeet.example.com" "speakerstats_component"
Component "conferenceduration.jitmeet.example.com" "conference_duration_component"
muc_component = "conference.jitmeet.example.com"
Component "lobby.jitmeet.example.com" "muc"
storage = "memory"
restrict_room_creation = true
muc_room_locking = false
muc_room_default_public_jids = true

View File

@@ -0,0 +1,45 @@
#!/bin/sh
set -e
COTURN_CERT_DIR="/etc/coturn/certs"
TURN_CONFIG="/etc/turnserver.conf"
# create a directory to store certs if it does not exists
if [ ! -d "$COTURN_CERT_DIR" ]; then
mkdir -p $COTURN_CERT_DIR
chown -R turnserver:turnserver /etc/coturn/
chmod -R 700 /etc/coturn/
fi
# This is a template and when copied to /etc/letsencrypt/renewal-hooks/deploy/
# during creating the Let's encrypt certs script
# jitsi-meet.example.com will be replaced with the real domain of deployment
for domain in $RENEWED_DOMAINS; do
case $domain in
jitsi-meet.example.com)
# Make sure the certificate and private key files are
# never world readable, even just for an instant while
# we're copying them into daemon_cert_root.
umask 077
cp "$RENEWED_LINEAGE/fullchain.pem" "$COTURN_CERT_DIR/$domain.fullchain.pem"
cp "$RENEWED_LINEAGE/privkey.pem" "$COTURN_CERT_DIR/$domain.privkey.pem"
# Apply the proper file ownership and permissions for
# the daemon to read its certificate and key.
chown turnserver "$COTURN_CERT_DIR/$domain.fullchain.pem" \
"$COTURN_CERT_DIR/$domain.privkey.pem"
chmod 400 "$COTURN_CERT_DIR/$domain.fullchain.pem" \
"$COTURN_CERT_DIR/$domain.privkey.pem"
if [ -f $TURN_CONFIG ] && grep -q "jitsi-meet coturn config" "$TURN_CONFIG" ; then
echo "Configuring turnserver"
sed -i "/^cert/c\cert=\/etc\/coturn\/certs\/${domain}.fullchain.pem" $TURN_CONFIG
sed -i "/^pkey/c\pkey=\/etc\/coturn\/certs\/${domain}.privkey.pem" $TURN_CONFIG
fi
service coturn restart
;;
esac
done

View File

@@ -1,5 +1,4 @@
# jitsi-meet coturn config. Do not modify this line
lt-cred-mech
use-auth-secret
keep-address-family
static-auth-secret=__turnSecret__
@@ -8,8 +7,12 @@ cert=/etc/jitsi/meet/jitsi-meet.example.com.crt
pkey=/etc/jitsi/meet/jitsi-meet.example.com.key
no-tcp
listening-port=443
listening-port=4446
tls-listening-port=4445
external-ip=__external_ip_address__
no-tlsv1
no-tlsv1_1
# https://ssl-config.mozilla.org/#server=haproxy&version=2.1&config=intermediate&openssl=1.1.0g&guideline=5.4
cipher-list=ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
syslog

View File

@@ -11,14 +11,14 @@ stream {
}
# since 1.13.10
map $ssl_preread_alpn_protocols $upstream {
"h2" web;
"http/1.1" web;
"h2,http/1.1" web;
~\bh2\b web;
~\bhttp/1\. web;
default turn;
}
server {
listen 443;
listen [::]:443;
# since 1.11.5
ssl_preread on;

View File

@@ -21,11 +21,16 @@ server {
listen [::]:443 ssl;
server_name jitsi-meet.example.com;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA256:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EDH+aRSA+AESGCM:EDH+aRSA+SHA256:EDH+aRSA:EECDH:!aNULL:!eNULL:!MEDIUM:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED";
# Mozilla Guideline v5.4, nginx 1.17.7, OpenSSL 1.1.1d, intermediate configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
add_header Strict-Transport-Security "max-age=31536000";
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m; # about 40000 sessions
ssl_session_tickets off;
add_header Strict-Transport-Security "max-age=63072000" always;
ssl_certificate /etc/jitsi/meet/jitsi-meet.example.com.crt;
ssl_certificate_key /etc/jitsi/meet/jitsi-meet.example.com.key;
@@ -39,6 +44,10 @@ server {
index index.html index.htm;
error_page 404 /static/404.html;
gzip on;
gzip_types text/plain text/css application/javascript application/json;
gzip_vary on;
location = /config.js {
alias /etc/jitsi/meet/jitsi-meet.example.com-config.js;
}

View File

@@ -11,14 +11,15 @@
ServerName jitsi-meet.example.com
SSLProtocol TLSv1 TLSv1.1 TLSv1.2
# enable HTTP/2, if available
Protocols h2 http/1.1
SSLEngine on
SSLProxyEngine on
SSLCertificateFile /etc/jitsi/meet/jitsi-meet.example.com.crt
SSLCertificateKeyFile /etc/jitsi/meet/jitsi-meet.example.com.key
SSLCipherSuite "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA256:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EDH+aRSA+AESGCM:EDH+aRSA+SHA256:EDH+aRSA:EECDH:!aNULL:!eNULL:!MEDIUM:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED"
SSLHonorCipherOrder on
Header set Strict-Transport-Security "max-age=31536000"
Header always set Strict-Transport-Security "max-age=63072000"
DocumentRoot "/usr/share/jitsi-meet"
<Directory "/usr/share/jitsi-meet">
@@ -48,3 +49,9 @@
RewriteEngine on
RewriteRule ^/([a-zA-Z0-9]+)$ /index.html
</VirtualHost>
# Mozilla Guideline v5.4, Apache 2.4.41, OpenSSL 1.1.1d, intermediate configuration, no OCSP
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
SSLSessionTickets off

View File

@@ -1,78 +0,0 @@
# Developing Jitsi Meet
## Building the sources
Node.js >= 10 and npm >= 6 are required.
On Debian/Ubuntu systems, the required packages can be installed with:
```
sudo apt-get install npm nodejs
cd jitsi-meet
npm install
```
To build the Jitsi Meet application, just type
```
make
```
### Working with the library sources (lib-jitsi-meet)
By default the library is build from its git repository sources. The default dependency path in package.json is :
```json
"lib-jitsi-meet": "jitsi/lib-jitsi-meet",
```
To work with local copy you must change the path to:
```json
"lib-jitsi-meet": "file:///Users/name/local-lib-jitsi-meet-copy",
```
To make the project you must force it to take the sources as 'npm update':
```
npm install lib-jitsi-meet --force && make
```
Or if you are making only changes to the library:
```
npm install lib-jitsi-meet --force && make deploy-lib-jitsi-meet
```
Alternative way is to use [npm link](https://docs.npmjs.com/cli/link).
It allows to link `lib-jitsi-meet` dependency to local source in few steps:
```bash
cd lib-jitsi-meet
#### create global symlink for lib-jitsi-meet package
npm link
cd ../jitsi-meet
#### create symlink from the local node_modules folder to the global lib-jitsi-meet symlink
npm link lib-jitsi-meet
```
After changes in local `lib-jitsi-meet` repository, you can rebuild it with `npm run install` and your `jitsi-meet` repository will use that modified library.
Note: when using node version 4.x, the make file of jitsi-meet do npm update which will delete the link. It is no longer the case with version 6.x.
If you do not want to use local repository anymore you should run
```bash
cd jitsi-meet
npm unlink lib-jitsi-meet
npm install
```
### Running with webpack-dev-server for development
Use it at the CLI, type
```
make dev
```
By default the backend deployment used is `beta.meet.jit.si`. You can point the Jitsi-Meet app at a different backend by using a proxy server. To do this, set the WEBPACK_DEV_SERVER_PROXY_TARGET variable:
```
export WEBPACK_DEV_SERVER_PROXY_TARGET=https://your-example-server.com
make dev
```
The app should be running at https://localhost:8080/

View File

@@ -0,0 +1,27 @@
# Jitsi Conference Focus settings
# sets the host name of the XMPP server
JICOFO_HOST=localhost
# sets the XMPP domain (default: none)
JICOFO_HOSTNAME=meet.example.com
# sets the secret used to authenticate as an XMPP component
JICOFO_SECRET=$JICOFO_SECRET
# sets the port to use for the XMPP component connection
JICOFO_PORT=5347
# sets the XMPP domain name to use for XMPP user logins
JICOFO_AUTH_DOMAIN=auth.meet.example.com
# sets the username to use for XMPP user logins
JICOFO_AUTH_USER=focus
# sets the password to use for XMPP user logins
JICOFO_AUTH_PASSWORD=$JICOFO_PASSWORD
# extra options to pass to the jicofo daemon
JICOFO_OPTS=""
# adds java system props that are passed to jicofo (default are for home and logging config file)
JAVA_SYS_PROPS="-Dnet.java.sip.communicator.SC_HOME_DIR_LOCATION=/etc/jitsi -Dnet.java.sip.communicator.SC_HOME_DIR_NAME=jicofo -Dnet.java.sip.communicator.SC_LOG_DIR_LOCATION=/var/log/jitsi -Djava.util.logging.config.file=/etc/jitsi/jicofo/logging.properties"

View File

@@ -0,0 +1,6 @@
org.jitsi.jicofo.BRIDGE_MUC=JvbBrewery@internal.auth.meet.example.com
org.jitsi.jicofo.ALWAYS_TRUST_MODE_ENABLED=true
org.jitsi.jicofo.jibri.BREWERY=JibriBrewery@internal.auth.meet.example.com
org.jitsi.jicofo.jibri.PENDING_TIMEOUT=90

View File

@@ -0,0 +1,88 @@
plugin_paths = { "/usr/share/jitsi-meet/prosody-plugins/" }
-- domain mapper options, must at least have domain base set to use the mapper
muc_mapper_domain_base = "meet.example.com";
turncredentials_secret = "turncredentials_secret_test";
turncredentials = {
{ type = "stun", host = "meet.example.com", port = "443" },
{ type = "turn", host = "meet.example.com", port = "443", transport = "udp" },
{ type = "turns", host = "meet.example.com", port = "443", transport = "tcp" }
};
cross_domain_bosh = false;
consider_bosh_secure = true;
VirtualHost "meet.example.com"
-- enabled = false -- Remove this line to enable this host
authentication = "anonymous"
-- Properties below are modified by jitsi-meet-tokens package config
-- and authentication above is switched to "token"
--app_id="example_app_id"
--app_secret="example_app_secret"
-- Assign this host a certificate for TLS, otherwise it would use the one
-- set in the global section (if any).
-- Note that old-style SSL on port 5223 only supports one certificate, and will always
-- use the global one.
ssl = {
key = "/etc/prosody/certs/meet.example.com.key";
certificate = "/etc/prosody/certs/meet.example.com.crt";
}
speakerstats_component = "speakerstats.meet.example.com"
conference_duration_component = "conferenceduration.meet.example.com"
-- we need bosh
modules_enabled = {
"bosh";
"pubsub";
"ping"; -- Enable mod_ping
"speakerstats";
"turncredentials";
"conference_duration";
}
c2s_require_encryption = false
Component "conference.meet.example.com" "muc"
storage = "memory"
modules_enabled = {
"muc_meeting_id";
"muc_domain_mapper";
-- "token_verification";
}
admins = { "focus@auth.meet.example.com" }
muc_room_locking = false
muc_room_default_public_jids = true
-- internal muc component
-- Note: This is also used from jibris
Component "internal.auth.meet.example.com" "muc"
storage = "memory"
modules_enabled = {
"ping";
}
admins = { "focus@auth.meet.example.com", "jvb@auth.meet.example.com" }
VirtualHost "auth.meet.example.com"
ssl = {
key = "/etc/prosody/certs/auth.meet.example.com.key";
certificate = "/etc/prosody/certs/auth.meet.example.com.crt";
}
authentication = "internal_plain"
Component "focus.meet.example.com"
component_secret = "jicofo_secret_test"
Component "speakerstats.meet.example.com" "speakerstats_component"
muc_component = "conference.meet.example.com"
Component "conferenceduration.meet.example.com" "conference_duration_component"
muc_component = "conference.meet.example.com"
-- for Jibri
VirtualHost "recorder.meet.example.com"
modules_enabled = {
"ping";
}
authentication = "internal_plain"
c2s_require_encryption = false

View File

@@ -0,0 +1,114 @@
-- Prosody XMPP Server Configuration
---------- Server-wide settings ----------
-- Settings in this section apply to the whole server and are the default settings
-- for any virtual hosts
admins = { }
network_backend = "epoll"
-- This is the list of modules Prosody will load on startup.
-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too.
-- Documentation for bundled modules can be found at: https://prosody.im/doc/modules
modules_enabled = {
-- Generally required
"roster"; -- Allow users to have a roster. Recommended ;)
"saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
"tls"; -- Add support for secure TLS on c2s/s2s connections
"dialback"; -- s2s dialback support
"disco"; -- Service discovery
-- Not essential, but recommended
"carbons"; -- Keep multiple clients in sync
"pep"; -- Enables users to publish their avatar, mood, activity, playing music and more
"private"; -- Private XML storage (for room bookmarks, etc.)
"blocklist"; -- Allow users to block communications with other users
"vcard4"; -- User profiles (stored in PEP)
"vcard_legacy"; -- Conversion between legacy vCard and PEP Avatar, vcard
-- Nice to have
"version"; -- Replies to server version requests
"uptime"; -- Report how long server has been running
"time"; -- Let others know the time here on this server
"ping"; -- Replies to XMPP pings with pongs
"register"; -- Allow users to register on this server using a client and change passwords
--"mam"; -- Store messages in an archive and allow users to access it
--"csi_simple"; -- Simple Mobile optimizations
-- Admin interfaces
"admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
--"admin_telnet"; -- Opens telnet console interface on localhost port 5582
-- HTTP modules
--"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
--"websocket"; -- XMPP over WebSockets
--"http_files"; -- Serve static files from a directory over HTTP
-- Other specific functionality
--"limits"; -- Enable bandwidth limiting for XMPP connections
--"groups"; -- Shared roster support
--"server_contact_info"; -- Publish contact information for this service
--"announce"; -- Send announcement to all online users
--"welcome"; -- Welcome users who register accounts
--"watchregistrations"; -- Alert admins of registrations
--"motd"; -- Send a message to users when they log in
--"legacyauth"; -- Legacy authentication. Only used by some old clients and bots.
--"proxy65"; -- Enables a file transfer proxy service which clients behind NAT can use
}
-- These modules are auto-loaded, but should you want
-- to disable them then uncomment them here:
modules_disabled = {
-- "offline"; -- Store offline messages
-- "c2s"; -- Handle client connections
-- "s2s"; -- Handle server-to-server connections
-- "posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
}
-- Disable account creation by default, for security
-- For more information see https://prosody.im/doc/creating_accounts
allow_registration = false
-- Force clients to use encrypted connections? This option will
-- prevent clients from authenticating unless they are using encryption.
c2s_require_encryption = true
-- Force servers to use encrypted connections? This option will
-- prevent servers from authenticating unless they are using encryption.
s2s_require_encryption = true
-- Force certificate authentication for server-to-server connections?
s2s_secure_auth = false
-- Required for init scripts and prosodyctl
pidfile = "/var/run/prosody/prosody.pid"
-- Select the authentication backend to use. The 'internal' providers
-- use Prosody's configured data storage to store the authentication data.
authentication = "internal_hashed"
archive_expires_after = "1w" -- Remove archived messages after 1 week
-- Logging configuration
-- For advanced logging see https://prosody.im/doc/logging
log = {
info = "/var/log/prosody/prosody.log"; -- Change 'info' to 'debug' for verbose logging
error = "/var/log/prosody/prosody.err";
-- "*syslog"; -- Uncomment this for logging to syslog
-- "*console"; -- Log to the console, useful for debugging with daemonize=false
}
-- Location of directory to find certificates in (relative to main config file):
certificates = "certs"
VirtualHost "localhost"
Include "conf.d/*.cfg.lua"

View File

@@ -0,0 +1,20 @@
# Jitsi Videobridge settings
# sets the XMPP domain (default: none)
JVB_HOSTNAME=meet.example.com
# sets the hostname of the XMPP server (default: domain if set, localhost otherwise)
JVB_HOST=
# sets the port of the XMPP server (default: 5275)
JVB_PORT=5347
# sets the shared secret used to authenticate to the XMPP server
JVB_SECRET=$VP_SECRET
# extra options to pass to the JVB daemon
JVB_OPTS="--apis=rest,"
# adds java system props that are passed to jvb (default are for home and logging config file)
JAVA_SYS_PROPS="-Dnet.java.sip.communicator.SC_HOME_DIR_LOCATION=/etc/jitsi -Dnet.java.sip.communicator.SC_HOME_DIR_NAME=videobridge -Dnet.java.sip.communicator.SC_LOG_DIR_LOCATION=/var/log/jitsi -Djava.util.logging.config.file=/etc/jitsi/videobridge/logging.properties"

View File

@@ -0,0 +1,19 @@
org.ice4j.ice.harvest.DISABLE_AWS_HARVESTER=true
org.ice4j.ice.harvest.STUN_MAPPING_HARVESTER_ADDRESSES=meet-jit-si-turnrelay.jitsi.net:443
org.jitsi.jicofo.ALWAYS_TRUST_MODE_ENABLED=true
org.jitsi.videobridge.ENABLE_REST_SHUTDOWN=true
# Enable broadcasting stats/presence in a MUC
org.jitsi.videobridge.ENABLE_STATISTICS=true
org.jitsi.videobridge.STATISTICS_TRANSPORT=muc,colibri,rest
org.jitsi.videobridge.STATISTICS_INTERVAL=5000
org.jitsi.videobridge.xmpp.user.shard-1.HOSTNAME=meet.example.com
org.jitsi.videobridge.xmpp.user.shard-1.DOMAIN=auth.meet.example.com
org.jitsi.videobridge.xmpp.user.shard-1.USERNAME=jvb
org.jitsi.videobridge.xmpp.user.shard-1.PASSWORD=$VB_PASSWORD
org.jitsi.videobridge.xmpp.user.shard-1.MUC_JIDS=JvbBrewery@internal.auth.meet.example.com
org.jitsi.videobridge.xmpp.user.shard-1.MUC_NICKNAME=$NICKNAME_OF_VB
org.jitsi.videobridge.xmpp.user.shard-1.DISABLE_CERTIFICATE_VERIFICATION=true

View File

@@ -1,7 +0,0 @@
**1. How to tell if my server instance is behind NAT?**
A. In general, if the tool ifconfig (or ipconfig) shows the assigned IP address to be some local address (10.x.x.x or 192.x.x.x) but you know that its public IP address is different from that, the server is most probably behind NAT
**2. Clients could communicate well in room created at meet.jit.si . The same clients still could connect to my self-hosted instance but can neither hear nor see one another. What's wrong?**
A. Most probably, the server is behind NAT. See this [resolved question](https://community.jitsi.org/t/cannot-see-video-or-hear-audio-on-self-hosted-instance/). You need to follow the steps detailed [here](https://github.com/jitsi/jitsi-meet/blob/master/doc/quick-install.md#Advanced-configuration)

View File

@@ -1,38 +0,0 @@
Document describing enabling various jitsi-meet integrations.
## Creating the Google API client for Google Calendar and Youtube integration
1. Log into a Google admin account.
1. Go to Google cloud platform dashboard. https://console.cloud.google.com/apis/dashboard
1. In the Select a Project dropdown, click New Project.
1. Give the project a name.
1. Proceed to the Credentials settings of the new project.
1. In the Credentials tab of the Credentials settings, click Create Credentials and select the type OAuth client ID.
1. Proceed with creating a Web application and add the domains (origins) on which the application will be hosted. Local development environments (http://localhost:8000 for example) can be added here.
1. While still in the Google cloud platform dashboard, click the Library settings for the calendar project.
1. Search for the Google Calendar API (used for calendar accessing), click its result, and enable it.
1. Do the same for YouTube Data API v3
## Creating the Microsoft app for Microsoft Outlook integration
1. Go to https://apps.dev.microsoft.com/
1. Proceed through the "Add an app" flow. Once created, a page with several Graph Permissions fields should display.
1. Under "Platforms" add "Web"
1. Add a redirect URL for the Microsoft auth flow to visit once a user has confirmed authentication. Target domain if available is just 'yourdomain.com' (the deployment address) and the redirect URL is `https://yourdomain.com/static/msredirect.html`.
1. Add Microsoft Graph delegated permissions, if this option is available: Calendars.Read, Calendars.ReadWrite, Calendars.Read.Shared, Calendars.ReadWrite.Shared.
1. Check `Allow Implicit Flow` (and `Restrict token issuing to this app` if available).
1. Save the changes.
## Creating the Dropbox app for Dropbox recording integration
1. You need a Dropbox account (If you don't already have one, you can sign up for a free account [here](https://www.dropbox.com/register).)
1. Create new App as described in [Getting Started Guide](https://www.dropbox.com/developers/reference/getting-started?_tk=guides_lp&_ad=guides2&_camp=get_started#app%20console) in App Console section.
1. Choose
1. 'Dropbox API - For apps that need to access files in Dropbox.'
1. 'App folder Access to a single folder created specifically for your app.'
1. Fill in the name of your app
1. You need only, the newly created App key, goes in config.js in
```
dropbox: {
appKey: '__dropbox_app_key__'
}
```
1. Add your Redirect URIs in the form `https://yourdeployment.com//static/oauth.html`
1. Fill in Branding

View File

@@ -1,268 +0,0 @@
# Server Installation for Jitsi Meet
:warning: **WARNING:** Manual installation is not recommended. We recommend following the [quick-install](https://github.com/jitsi/jitsi-meet/blob/master/doc/quick-install.md) document. The current document describes the steps that are needed to install a working deployment, but steps are easy to mess up, and the debian packages are more up-to-date, where this document is sometimes not updated to reflect latest changes.
This describes configuring a server `jitsi.example.com` running Debian or a Debian Derivative. You will need to
change references to that to match your host, and generate some passwords for
`YOURSECRET1`, `YOURSECRET2` and `YOURSECRET3`.
There are also some complete [example config files](https://github.com/jitsi/jitsi-meet/tree/master/doc/example-config-files/) available, mentioned in each section.
## Network description
This is how the network looks:
```
+ +
| |
| |
v |
443 |
+-------+ |
| | |
| Nginx | |
| | |
+--+-+--+ |
| | |
+------------+ | | +--------------+ |
| | | | | | |
| jitsi-meet +<---+ +--->+ prosody/xmpp | |
| |files 5280 | | |
+------------+ +--------------+ v
5222,5347^ ^5347 4443,10000
+--------+ | | +-------------+
| | | | | |
| jicofo +----^ ^----+ videobridge |
| | | |
+--------+ +-------------+
```
## Install prosody
```sh
apt-get install prosody
```
## Configure prosody
Add config file in `/etc/prosody/conf.avail/jitsi.example.com.cfg.lua` :
- add your domain virtual host section:
```
VirtualHost "jitsi.example.com"
authentication = "anonymous"
ssl = {
key = "/var/lib/prosody/jitsi.example.com.key";
certificate = "/var/lib/prosody/jitsi.example.com.crt";
}
modules_enabled = {
"bosh";
"pubsub";
}
c2s_require_encryption = false
```
- add domain with authentication for conference focus user:
```
VirtualHost "auth.jitsi.example.com"
ssl = {
key = "/var/lib/prosody/auth.jitsi.example.com.key";
certificate = "/var/lib/prosody/auth.jitsi.example.com.crt";
}
authentication = "internal_plain"
```
- add focus user to server admins:
```
admins = { "focus@auth.jitsi.example.com" }
```
- and finally configure components:
```
Component "conference.jitsi.example.com" "muc"
Component "jitsi-videobridge.jitsi.example.com"
component_secret = "YOURSECRET1"
Component "focus.jitsi.example.com"
component_secret = "YOURSECRET2"
```
Add link for the added configuration
```sh
ln -s /etc/prosody/conf.avail/jitsi.example.com.cfg.lua /etc/prosody/conf.d/jitsi.example.com.cfg.lua
```
Generate certs for the domain:
```sh
prosodyctl cert generate jitsi.example.com
prosodyctl cert generate auth.jitsi.example.com
```
Add auth.jitsi.example.com to the trusted certificates on the local machine:
```sh
ln -sf /var/lib/prosody/auth.jitsi.example.com.crt /usr/local/share/ca-certificates/auth.jitsi.example.com.crt
update-ca-certificates -f
```
Note that the `-f` flag is necessary if there are symlinks left from a previous installation.
Create conference focus user:
```sh
prosodyctl register focus auth.jitsi.example.com YOURSECRET3
```
Restart prosody XMPP server with the new config
```sh
prosodyctl restart
```
## Install Nginx
```sh
apt-get install nginx
```
Add a new file `jitsi.example.com` in `/etc/nginx/sites-available` (see also the example config file):
```
server_names_hash_bucket_size 64;
server {
listen 0.0.0.0:443 ssl http2;
listen [::]:443 ssl http2;
# tls configuration that is not covered in this guide
# we recommend the use of https://certbot.eff.org/
server_name jitsi.example.com;
# set the root
root /srv/jitsi-meet;
index index.html;
location ~ ^/([a-zA-Z0-9=\?]+)$ {
rewrite ^/(.*)$ / break;
}
location / {
ssi on;
}
# BOSH, Bidirectional-streams Over Synchronous HTTP
# https://en.wikipedia.org/wiki/BOSH_(protocol)
location /http-bind {
proxy_pass http://localhost:5280/http-bind;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
}
# external_api.js must be accessible from the root of the
# installation for the electron version of Jitsi Meet to work
# https://github.com/jitsi/jitsi-meet-electron
location /external_api.js {
alias /srv/jitsi-meet/libs/external_api.min.js;
}
}
```
Add link for the added configuration
```sh
cd /etc/nginx/sites-enabled
ln -s ../sites-available/jitsi.example.com jitsi.example.com
```
## Install Jitsi Videobridge
Visit https://download.jitsi.org/jitsi-videobridge/linux to determine the current build number, download and unzip it:
```sh
wget https://download.jitsi.org/jitsi-videobridge/linux/jitsi-videobridge-linux-{arch-buildnum}.zip
unzip jitsi-videobridge-linux-{arch-buildnum}.zip
```
Install JRE if missing:
```
apt-get install openjdk-8-jre
```
_NOTE: When installing on older Debian releases keep in mind that you need JRE >= 1.7._
Create `~/.sip-communicator/sip-communicator.properties` in the home folder of the user that will be starting Jitsi Videobridge:
```sh
mkdir -p ~/.sip-communicator
cat > ~/.sip-communicator/sip-communicator.properties << EOF
org.jitsi.impl.neomedia.transform.srtp.SRTPCryptoContext.checkReplay=false
# The videobridge uses 443 by default with 4443 as a fallback, but since we're already
# running nginx on 443 in this example doc, we specify 4443 manually to avoid a race condition
org.jitsi.videobridge.TCP_HARVESTER_PORT=4443
EOF
```
Start the videobridge with:
```sh
./jvb.sh --host=localhost --domain=jitsi.example.com --port=5347 --secret=YOURSECRET1 &
```
Or autostart it by adding the line in `/etc/rc.local`:
```sh
/bin/bash /root/jitsi-videobridge-linux-{arch-buildnum}/jvb.sh --host=localhost --domain=jitsi.example.com --port=5347 --secret=YOURSECRET1 </dev/null >> /var/log/jvb.log 2>&1
```
## Install Jitsi Conference Focus (jicofo)
Install JDK and Maven if missing:
```
apt-get install openjdk-8-jdk maven
```
_NOTE: When installing on older Debian releases keep in mind that you need JDK >= 1.7._
Clone source from Github repo:
```sh
git clone https://github.com/jitsi/jicofo.git
```
Build the package.
```sh
cd jicofo
mvn package -DskipTests -Dassembly.skipAssembly=false
```
Run jicofo:
```sh
=======
unzip target/jicofo-1.1-SNAPSHOT-archive.zip
cd jicofo-1.1-SNAPSHOT-archive'
./jicofo.sh --host=localhost --domain=jitsi.example.com --secret=YOURSECRET2 --user_domain=auth.jitsi.example.com --user_name=focus --user_password=YOURSECRET3
```
## Deploy Jitsi Meet
Checkout and configure Jitsi Meet:
```sh
cd /srv
git clone https://github.com/jitsi/jitsi-meet.git
cd jitsi-meet
npm install
make
```
_NOTE: When installing on older distributions keep in mind that you need Node.js >= 10 and npm >= 6._
Edit host names in `/srv/jitsi-meet/config.js` (see also the example config file):
```
var config = {
hosts: {
domain: 'jitsi.example.com',
muc: 'conference.jitsi.example.com',
bridge: 'jitsi-videobridge.jitsi.example.com',
focus: 'focus.jitsi.example.com'
},
useNicks: false,
bosh: '//jitsi.example.com/http-bind', // FIXME: use xep-0156 for that
//chromeExtensionId: 'diibjkoicjeejcmhdnailmkgecihlobk', // Id of desktop streamer Chrome extension
//minChromeExtVersion: '0.1' // Required version of Chrome extension
};
```
Verify that nginx config is valid and reload nginx:
```sh
nginx -t && nginx -s reload
```
## Running behind NAT
Jitsi Videobridge can run behind a NAT, provided that both required ports are routed (forwarded) to the machine that it runs on. By default these ports are `TCP/4443` and `UDP/10000`.
If you do not route these two ports, Jitsi Meet will only work with video for two people, breaking upon 3 or more people trying to show video.
`TCP/443` is required for the webserver which can be running on another machine than the Jitsi Videobrige is running on.
The following extra lines need to be added to the file `~/.sip-communicator/sip-communicator.properties` (in the home directory of the user running the videobridge):
```
org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS=<Local.IP.Address>
org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS=<Public.IP.Address>
```
# Hold your first conference
You are now all set and ready to have your first meet by going to http://jitsi.example.com
## Enabling recording
[Jibri](https://github.com/jitsi/jibri) is a set of tools for recording and/or streaming a Jitsi Meet conference.

View File

@@ -1,28 +0,0 @@
# Setting up Dropbox integration
1. Create a Dropbox app.
2. Add the following to ```ios/app/src/Info.plist``` by replacing `<APP_KEY>`
with your own Dropbox app key (which can be found in the
[App Console](https://www.dropbox.com/developers/apps)):
```
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string></string>
<key>CFBundleURLSchemes</key>
<array>
<string>db-<APP_KEY></string>
</array>
</dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>dbapi-2</string>
<string>dbapi-8-emm</string>
</array>
```
**NOTE:** Both Android and iOS builds of the apps will parse the Dropbox app key
from ```ios/app/src/Info.plist```.
**NOTE:** See [Dropbox developer guide](https://www.dropbox.com/developers/reference/developer-guide) for more information

View File

@@ -1,22 +0,0 @@
# Setting up Google Authentication
- Create a Firebase project here: https://firebase.google.com/. You'll need a
signed Android build for that, that can be a debug self-signed build too, just
retrieve the signing hash. The key hash of an already signed ap can be obtained
as follows (on macOS): ```keytool -list -printcert -jarfile the-app.apk```
- Place the generated ```google-services.json``` file in ```android/app```
for Android and the ```GoogleService-Info.plist``` into ```ios/app``` for
iOS (you can stop at that step, no need for the driver and the code changes they
suggest in the wizard).
- You may want to exclude these files in YOUR GIT config (do not exclude them in
the ```.gitignore``` of the application itself!).
- Your web client ID is auto generated during the Firebase project
creation. Find them in the Google Developer console
(https://console.developers.google.com/)
- Make sure your config reflects this ID by setting
```googleApiApplicationClientID``` in config.js.
- Add your iOS client ID (the REVERSED_CLIENT_ID in the plist file) as an
application URL schema into ```ios/app/src/Info.plist```
(replacing placeholder).
- Enable YouTube API access on the developer console (see above) to enable live
streaming.

View File

@@ -1,107 +0,0 @@
# Jitsi Meet apps for Android and iOS
Jitsi Meet can be built as a standalone app for Android or iOS. It uses the
[React Native] framework.
**If you want to rebuild the SDK yourself look in [Android README] or [iOS README].**
First make sure the [React Native dependencies] are installed.
**NOTE**: This document assumes the app is being built on a macOS system.
**NOTE**: Node 10.X and npm 6.X are recommended for building.
## iOS
1. Install some extra dependencies
- Install ios-deploy globally (in case you want to use the React Native CLI
to deploy the app to the device)
```bash
npm install -g ios-deploy
```
- Install main dependencies:
```bash
npm install
```
- Install the required pods (CocoaPods must be installled first, it can
be done with Homebrew: `brew install cocoapods`)
```bash
cd ios
pod install
cd ..
```
2. Build the app
There are 2 ways to build the app: using the CLI or using Xcode.
Using the CLI:
```bash
react-native run-ios --device
```
When the app is launched from the CLI the output can be checked with the
following command:
```bash
react-native log-ios
```
Using Xcode
- Open **ios/jitsi-meet.xcworkspace** in Xcode. Make sure it's the workspace
file!
- Select your device from the top bar and hit the "play" button.
When the app is launched from Xcode the Debug console will show the output
logs the application creates.
3. Other remarks
It's likely you'll need to change the bundle ID for deploying to a device.
This can be changed in the "General" tab. Under "Identity" set
"Bundle Identifier" to a different value, and adjust the "Team" in the
"Signing" section to match your own.
## Android
The [React Native dependencies] page has very detailed information on how to
setup [Android Studio] and the required components for getting the necessary
build environment. Make sure you follow it closely.
1. Building the app
The app can be built using the CLI utility as follows:
```bash
react-native run-android
```
It will be launched on the connected Android device.
## Debugging
The official documentation on [debugging] is quite extensive and specifies the
preferred method for debugging.
**NOTE**: When using Chrome Developer Tools for debugging the JavaScript source
code is being interpreted by Chrome's V8 engine, instead of JSCore which React
Native uses. It's important to keep this in mind due to potential differences in
supported JavaScript features.
[Android README]: https://github.com/jitsi/jitsi-meet/blob/master/android/README.md
[iOS README]: https://github.com/jitsi/jitsi-meet/blob/master/ios/README.md
[Android Studio]: https://developer.android.com/studio/index.html
[debugging]: https://facebook.github.io/react-native/docs/debugging.html
[React Native]: https://facebook.github.io/react-native/
[React Native dependencies]: https://facebook.github.io/react-native/docs/getting-started.html#installing-dependencies

View File

@@ -1,154 +1,3 @@
# Jitsi Meet quick install
This guide helps you ___host your own Jitsi server___. If you want to have a video conference without setting up any infrastructure, use https://meet.jit.si instead.
This document describes the required steps for a quick Jitsi Meet installation on a Debian based GNU/Linux system. Debian 9 (Stretch) or later, and Ubuntu 18.04 (Bionic Beaver) or later are supported out-of-the-box.
On Ubuntu systems, Jitsi requires dependencies from Ubuntu's `universe` package repository. To ensure this is enabled, run `apt-add-repository universe` at the command-line.
_Note_: Many of the installation steps require elevated privileges. If you are logged in using a regular user account, you may need to temporarily increase your permissions (for example, by using `sudo` for individual commands).
## Basic Jitsi Meet install
### Set up the Fully Qualified Domain Name (FQDN) (optional)
If the machine used to host the Jitsi Meet instance has a FQDN (for example `meet.example.org`) already set up in DNS, `/etc/hostname` must contain this FQDN; if this is not the case yet, [change the hostname](https://wiki.debian.org/HowTo/ChangeHostname).
Then add the same FQDN in the `/etc/hosts` file, associating it with the loopback address:
127.0.0.1 localhost meet.example.org
Finally on the same machine test that you can ping the FQDN with: `ping "$(hostname)"`-
### Add the Jitsi package repository
```sh
echo 'deb https://download.jitsi.org stable/' >> /etc/apt/sources.list.d/jitsi-stable.list
wget -qO - https://download.jitsi.org/jitsi-key.gpg.key | sudo apt-key add -
```
### Install Jitsi Meet
_Note_: The installer will check if [Nginx](https://nginx.org/) or [Apache](https://httpd.apache.org/) is present (in that order) and configure a virtualhost within the web server it finds to serve Jitsi Meet. If none of the above is found it then defaults to Nginx.
If you are already running Nginx on port 443 on the same machine you better skip the turnserver configuration as it will conflict with your current port 443, so use the command `apt install --no-install-recommends jitsi-meet`.
```sh
# Ensure support is available for apt repositories served via HTTPS
apt-get install apt-transport-https
# Retrieve the latest package versions across all repositories
apt-get update
# Perform jitsi-meet installation
apt-get -y install jitsi-meet
```
During the installation, you will be asked to enter the hostname of the Jitsi Meet instance. If you have a [FQDN](https://en.wikipedia.org/wiki/Fully_qualified_domain_name) for the instance already set up in DNS, enter it there. If you don't have a resolvable hostname, you can enter the IP address of the machine (if it is static or doesn't change).
This hostname (or IP address) will be used for virtualhost configuration inside the Jitsi Meet and also, you and your correspondents will be using it to access the web conferences.
### Generate a Let's Encrypt certificate (optional, recommended)
In order to have encrypted communications, you need a [TLS certificate](https://en.wikipedia.org/wiki/Transport_Layer_Security). The easiest way is to use [Let's Encrypt](https://letsencrypt.org/).
_Note_: Jitsi Meet mobile apps *require* a valid certificate signed by a trusted [Certificate Authority](https://en.wikipedia.org/wiki/Certificate_authority) and will not be able to connect to your server if you choose a self-signed certificate.
Simply run the following in your shell:
```sh
/usr/share/jitsi-meet/scripts/install-letsencrypt-cert.sh
```
Note that this script uses the [HTTP-01 challenge type](https://letsencrypt.org/docs/challenge-types/) and thus your instance needs to be accessible from the public internet. If you want to use a different challenge type, don't use this script and instead choose ___I want to use my own certificate___ during jitsi-meet installation.
#### Advanced configuration
If the installation is on a machine [behind NAT](https://github.com/jitsi/jitsi-meet/blob/master/doc/faq.md) jitsi-videobridge should configure itself automatically on boot. If three way call does not work further configuration of jitsi-videobridge is needed in order for it to be accessible from outside.
Provided that all required ports are routed (forwarded) to the machine that it runs on. By default these ports are (TCP/443 or TCP/4443 and UDP/10000).
The following extra lines need to be added to the file `/etc/jitsi/videobridge/sip-communicator.properties`:
```
org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS=<Local.IP.Address>
org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS=<Public.IP.Address>
```
And comment the existing `org.ice4j.ice.harvest.STUN_MAPPING_HARVESTER_ADDRESSES`.
See [the documentation of ice4j](https://github.com/jitsi/ice4j/blob/master/doc/configuration.md)
for details.
Default deployments on systems using systemd will have low default values for maximum processes and open files. If the used bridge will expect higher number of participants the default values need to be adjusted (the default values are good for less than 100 participants).
To update the values edit `/etc/systemd/system.conf` and make sure you have the following values:
```
DefaultLimitNOFILE=65000
DefaultLimitNPROC=65000
DefaultTasksMax=65000
```
To load the values and check them look [here](#systemd-details) for details.
By default, anyone who has access to your jitsi instance will be able to start a conference: if your server is open to the world, anyone can have a chat with anyone else. If you want to limit the ability to start a conference to registered users, set up a "secure domain". Follow the instructions at https://github.com/jitsi/jicofo#secure-domain.
### Confirm that your installation is working
Launch a web browser (Chrome, Chromium or latest Opera) and enter the hostname or IP address from the previous step into the address bar.
If you used a self-signed certificate (as opposed to using Let's Encrypt), your web browser will ask you to confirm that you trust the certificate.
You should see a web page prompting you to create a new meeting. Make sure that you can successfully create a meeting and that other participants are able to join the session.
If this all worked, then congratulations! You have an operational Jitsi conference service.
## Adding sip-gateway to Jitsi Meet
### Install Jigasi
Jigasi is a server-side application acting as a gateway to Jitsi Meet conferences. It allows regular [SIP](https://en.wikipedia.org/wiki/Session_Initiation_Protocol) clients to join meetings and provides transcription capabilities.
```sh
apt-get -y install jigasi
```
or
```sh
wget https://download.jitsi.org/unstable/jigasi_1.0-107_amd64.deb
dpkg -i jigasi_1.0-107_amd64.deb
```
During the installation, you will be asked to enter your SIP account and password. This account will be used to invite the other SIP participants.
### Reload Jitsi Meet
Launch again a browser with the Jitsi Meet URL and you'll see a telephone icon on the right end of the toolbar. Use it to invite SIP accounts to join the current conference.
Enjoy!
## Uninstall
```sh
apt-get purge jigasi jitsi-meet jitsi-meet-web-config jitsi-meet-prosody jitsi-meet-turnserver jitsi-meet-web jicofo jitsi-videobridge2
```
Sometimes the following packages will fail to uninstall properly:
- jigasi
- jitsi-videobridge
When this happens, just run the uninstall command a second time and it should be ok.
The reason for the failure is that sometimes the uninstall script is faster than the process that stops the daemons. The second run of the uninstall command fixes this, as by then the jigasi or jitsi-videobridge daemons are already stopped.
#### Systemd details
To reload the systemd changes on a running system execute `systemctl daemon-reload` and `service jitsi-videobridge2 restart`.
To check the tasks part execute `service jitsi-videobridge2 status` and you should see `Tasks: XX (limit: 65000)`.
To check the files and process part execute ```cat /proc/`cat /var/run/jitsi-videobridge/jitsi-videobridge.pid`/limits``` and you should see:
```
Max processes 65000 65000 processes
Max open files 65000 65000 files
```
## Debugging problems
If you run into problems, one thing to try is using a different web browser. Some versions of some browsers are known to have issues with Jitsi Meet. You can also visit https://test.webrtc.org to test your browser's [WebRTC](https://en.wikipedia.org/wiki/WebRTC) support.
Another place to look is the various log files:
```
/var/log/jitsi/jvb.log
/var/log/jitsi/jicofo.log
/var/log/prosody/prosody.log
```
This document has been moved [here](https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-quickstart).

View File

@@ -1,53 +0,0 @@
# Configuring sipgw jibri with jitsi-meet
This document describes how you can configure jitsi-meet to use sipgw jibri and enable rooms in 'Add people dialog'
You will need a working deployment of jibri configured to use a regular sip video device, for more info check out the [jibri documentation](https://github.com/jitsi/jibri/blob/master/README.md).
This feature is available for non-guests of the system, so this relies on setting in config.js ``enableUserRolesBasedOnToken: true`` and providing a jwt token when accessing the conference.
* Jicofo configuration:
edit /etc/jitsi/jicofo/sip-communicator.properties (or similar), set the appropriate MUC to look for the Jibri Controllers. This should be the same MUC as is referenced in jibri's config.json file. Restart Jicofo after setting this property.
```
org.jitsi.jicofo.jibri.SIP_BREWERY=TheSipBrewery@conference.yourdomain.com
```
* Jitsi Meet configuration:
- config.js: add
```
enableUserRolesBasedOnToken: true,
peopleSearchQueryTypes: ['conferenceRooms'],
peopleSearchUrl: 'https://api.yourdomain.com/testpath/searchpeople',
```
The combination of the above settings and providing a jwt token will enable a button under invite option which will show the dialog 'Add people'.
## People search service
When searching in the dialog, a request for results is made to the `peopleSearchUrl` service.
The request is in the following format:
```
https://api.yourdomain.com/testpath/searchpeople?query=testroomname&queryTypes=[%22conferenceRooms%22]&jwt=somejwt
```
The parameters are:
- query - The text entered by the user.
- queryTypes - What type of results we want people, rooms, conferenceRooms. This is the value from config.js `peopleSearchQueryTypes`
- jwt - The token used by the user to access the conference.
The response of the service is a json in the following format:
```
[
{
"id": "address@sip.domain.com",
"name": "Some room name",
"type": "videosipgw"
},
{
"id": "address2@sip.domain.com",
"name": "Some room name2",
"type": "videosipgw"
}
]
```
Type should be `videosipgw`, `name` is the name shown to the user and `id` is the sip address to be called by the sipgw jibri.

View File

@@ -1,22 +0,0 @@
# Enabling speakerstats prosody module
To enable the speaker stats we need to enable speakerstats module under the main
virtual host, this is to enable the advertising the speaker stats component,
which address needs to be specified in `speakerstats_component` option.
We need to also enable the component with the address specified in `speakerstats_component`.
The component needs also to have the option with the muc component address in
`muc_component` option.
```lua
VirtualHost "jitsi.example.com"
speakerstats_component = "speakerstats.jitsi.example.com"
modules_enabled = {
"speakerstats";
}
Component "speakerstats.jitsi.example.com" "speakerstats_component"
muc_component = "conference.jitsi.example.com"
Component "conference.jitsi.example.com" "muc"
```

View File

@@ -1,15 +0,0 @@
One-to-one calls should avoid going throught the JVB for optimal performance and for optimal resource usage. This is why we've added the peer-to-peer mode where the two participants connect directly to each other. Unfortunately, a direct connection is not always possible between the participants. In those cases you can use a TURN server to relay the traffic (n.b. the JVB does much more than just relay the traffic, so this is not the same as using the JVB to "relay" the traffic).
This document describes how to enable TURN server support in one-to-one calls in Jitsi Meet, even though it gives some hints how to configure [prosody](prosody.im) and [coTURN](https://github.com/coturn/coturn), it assumes a properly configured TURN server and a proprely configured XMPP server.
One way to configure TURN support in meet with a static configuration. You can simply fill out the `p2p.stunServers` option with appropriate values, e.g.:
[
{ urls: 'turn:turn.example.com1', credential: 'user', password: 'pass' },
]
This technique doesn't require any special configuration on the XMPP server, but it exposes the credentials to your TURN server and other people can use your bandwidth freely, so while it's simple to implement, it's not recommended.
This [draft](https://tools.ietf.org/html/draft-uberti-behave-turn-rest-00) escribes a proposed standard REST API for obtaining access to TURN services via ephemeral (i.e. time-limited) credentials. These credentials are vended by a web service over HTTP, and then supplied to and checked by a TURN server using the standard TURN protocol. The usage of ephemeral credentials ensures that access to the TURN server can be controlled even if the credentials can be discovered by the user.
Jitsi Meet can fetch the TURN credentials from the XMPP server via [XEP-0215](https://xmpp.org/extensions/xep-0215.html). You can enable this functionality by setting `p2p.useStunTurn: true` in config.js. By properly configuring a common shared secret on your TURN server and your XMPP server, the XMPP server can deliver appropriate credentials and TURN urls to Jitsi Meet. coTURN natively supports shared secret authentication (--use-auth-secret-) and in prosody, you can use the [mod_turncredentials](https://modules.prosody.im/mod_turncredentials.html) module.

46
docker/Dockerfile Normal file
View File

@@ -0,0 +1,46 @@
ARG JITSI_REPO=jitsi
ARG JITSI_GIT_REPO=https://github.com/jitsi/jitsi-meet.git
ARG JITSI_GIT_REF=HEAD
FROM node:12 as builder
ARG JITSI_GIT_REPO
ARG JITSI_GIT_REF
WORKDIR /src
RUN \
git clone $JITSI_GIT_REPO && \
cd jitsi-meet && \
git reset --hard $JITSI_GIT_REF && \
npm install && \
make
FROM ${JITSI_REPO}/base
RUN \
apt-dpkg-wrap apt-get update && \
apt-dpkg-wrap apt-get install -y nginx-extras && \
apt-cleanup && \
rm -f /etc/nginx/conf.d/default.conf
COPY rootfs/ /
COPY --from=builder /src/jitsi-meet/libs /usr/share/jitsi-meet/libs
COPY --from=builder /src/jitsi-meet/static /usr/share/jitsi-meet/static
COPY --from=builder /src/jitsi-meet/sounds /usr/share/jitsi-meet/sounds
COPY --from=builder /src/jitsi-meet/fonts /usr/share/jitsi-meet/fonts
COPY --from=builder /src/jitsi-meet/images /usr/share/jitsi-meet/images
COPY --from=builder /src/jitsi-meet/lang /usr/share/jitsi-meet/lang
COPY --from=builder /src/jitsi-meet/connection_optimization /usr/share/jitsi-meet/connection_optimization
COPY --from=builder /src/jitsi-meet/css/all.css /usr/share/jitsi-meet/css/
COPY --from=builder /src/jitsi-meet/resources/*.sh /usr/share/jitsi-meet/scripts/
COPY --from=builder /src/jitsi-meet/*.html /usr/share/jitsi-meet/
COPY --from=builder /src/jitsi-meet/*.ico /usr/share/jitsi-meet/
COPY --from=builder /src/jitsi-meet/resources/robots.txt /usr/share/jitsi-meet/
ENV XMPP_BOSH_URL_BASE=https://meet.jit.si
ENV XMPP_DOMAIN=meet.jit.si
EXPOSE 8000
VOLUME ["/config"]

View File

@@ -0,0 +1,46 @@
server_name _;
client_max_body_size 0;
root /usr/share/jitsi-meet;
# ssi on with javascript for multidomain variables in config.js
ssi on;
ssi_types application/x-javascript application/javascript;
index index.html index.htm;
error_page 404 /static/404.html;
location = /config.js {
alias /config/config.js;
}
location = /interface_config.js {
alias /config/interface_config.js;
}
location = /external_api.js {
alias /usr/share/jitsi-meet/libs/external_api.min.js;
}
# ensure all static content can always be found first
location ~ ^/(libs|css|static|images|fonts|lang|sounds|connection_optimization|.well-known)/(.*)$
{
add_header 'Access-Control-Allow-Origin' '*';
alias /usr/share/jitsi-meet/$1/$2;
}
# BOSH
location = /http-bind {
proxy_pass {{ .Env.XMPP_BOSH_URL_BASE }}/http-bind;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host {{ .Env.XMPP_DOMAIN }};
}
location ~ ^/([^/?&:'"]+)$ {
try_files $uri @root_path;
}
location @root_path {
rewrite ^/(.*)$ / break;
}

View File

@@ -0,0 +1,60 @@
user www-data;
worker_processes 4;
pid /run/nginx.pid;
daemon off;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
client_max_body_size 0;
include /etc/nginx/mime.types;
types {
# add support for wasm MIME type, that is required by specification and it is not part of default mime.types file
application/wasm wasm;
}
default_type application/octet-stream;
##
# Logging Settings
##
access_log /dev/stdout;
error_log /dev/stderr;
##
# Gzip Settings
##
gzip on;
gzip_types text/plain text/css application/javascript application/json;
gzip_vary on;
gzip_min_length 860;
##
## The Sever
##
server {
listen 8000 default_server;
include /config/nginx/meet.conf;
}
}

View File

@@ -0,0 +1,12 @@
#!/usr/bin/with-contenv bash
# make our folders
mkdir -p \
/config/nginx \
/run \
/var/lib/nginx/tmp/client_body \
/var/tmp/nginx
# copy config files
cp /defaults/nginx.conf /config/nginx/nginx.conf
tpl /defaults/meet.conf > /config/nginx/meet.conf

View File

@@ -0,0 +1,3 @@
#!/usr/bin/with-contenv bash
exec nginx -c /config/nginx/nginx.conf

View File

@@ -1,9 +1,8 @@
/* eslint-disable no-unused-vars, no-var, max-len */
var interfaceConfig = {
// TO FIX: this needs to be handled from SASS variables. There are some
// methods allowing to use variables both in css and js.
DEFAULT_BACKGROUND: '#474747',
DEFAULT_LOGO_URL: '../images/watermark.png',
/**
* Whether or not the blurred video background for large video should be
@@ -48,10 +47,11 @@ var interfaceConfig = {
*/
TOOLBAR_BUTTONS: [
'microphone', 'camera', 'closedcaptions', 'desktop', 'fullscreen',
'fodeviceselection', 'hangup', 'profile', 'info', 'chat', 'recording',
'fodeviceselection', 'hangup', 'profile', 'chat', 'recording',
'livestreaming', 'etherpad', 'sharedvideo', 'settings', 'raisehand',
'videoquality', 'filmstrip', 'invite', 'feedback', 'stats', 'shortcuts',
'tileview', 'videobackgroundblur', 'download', 'help', 'mute-everyone'
'tileview', 'videobackgroundblur', 'download', 'help', 'mute-everyone',
'e2ee', 'security'
],
SETTINGS_SECTIONS: [ 'devices', 'language', 'moderator', 'profile', 'calendar' ],
@@ -175,7 +175,7 @@ var interfaceConfig = {
// has a suboptimal experience. Browsers which are not listed as optimal or
// unsupported are considered suboptimal. Valid values are:
// chrome, chromium, edge, electron, firefox, nwjs, opera, safari
OPTIMAL_BROWSERS: [ 'chrome', 'chromium', 'firefox', 'nwjs', 'electron' ],
OPTIMAL_BROWSERS: [ 'chrome', 'chromium', 'firefox', 'nwjs', 'electron', 'safari' ],
// Browsers, in addition to those which do not fully support WebRTC, that
// are not supported and should show the unsupported browser page.
@@ -206,12 +206,12 @@ var interfaceConfig = {
* If this is set to false, the banner will not be rendered at all. If set to true, the check for extension(s)
* being already installed is done before rendering.
*/
SHOW_CHROME_EXTENSION_BANNER: false
SHOW_CHROME_EXTENSION_BANNER: false,
/**
* When enabled, the kick participant button will not be presented for users without a JWT
*/
// HIDE_KICK_BUTTON_FOR_GUESTS: false
// HIDE_KICK_BUTTON_FOR_GUESTS: false,
/**
* How many columns the tile view can expand to. The respected range is
@@ -229,6 +229,17 @@ var interfaceConfig = {
*/
// MOBILE_DOWNLOAD_LINK_IOS: 'https://itunes.apple.com/us/app/jitsi-meet/id1165103905',
/**
* Specify Firebase dynamic link properties for the mobile apps.
*/
// MOBILE_DYNAMIC_LINK: {
// APN: 'org.jitsi.meet',
// APP_CODE: 'w2atb',
// CUSTOM_DOMAIN: undefined,
// IBI: 'com.atlassian.JitsiMeet.ios',
// ISI: '1165103905'
// },
/**
* Specify mobile app scheme for opening the app from the mobile browser.
*/
@@ -252,6 +263,12 @@ var interfaceConfig = {
MOBILE_DYNAMIC_LINK
PHONE_NUMBER_REGEX
*/
// Allow all above example options to include a trailing comma and
// prevent fear when commenting out the last value.
makeJsonParserHappy: 'even if last key had a trailing comma'
// no configuration value should follow this line.
};
/* eslint-enable no-unused-vars, no-var, max-len */

View File

@@ -66,6 +66,7 @@ target 'JitsiMeet' do
pod 'RNSound', :path => '../node_modules/react-native-sound'
pod 'RNSVG', :path => '../node_modules/react-native-svg'
pod 'RNWatch', :path => '../node_modules/react-native-watch-connectivity'
pod 'RNDefaultPreference', :path => '../node_modules/react-native-default-preference'
# Native pod dependencies
#

View File

@@ -287,7 +287,7 @@ PODS:
- React-jsinspector (0.61.5-jitsi.1)
- react-native-background-timer (2.1.1):
- React
- react-native-calendar-events (1.7.3):
- react-native-calendar-events (2.0.0):
- React
- react-native-keep-awake (4.0.0):
- React
@@ -353,6 +353,8 @@ PODS:
- ReactCommon/turbomodule/core (= 0.61.5-jitsi.1)
- RNCAsyncStorage (1.3.4):
- React
- RNDefaultPreference (1.4.2):
- React
- RNGoogleSignin (3.0.1):
- GoogleSignIn (~> 5.0.0)
- React
@@ -363,7 +365,7 @@ PODS:
- React
- RNSVG (9.7.1):
- React
- RNWatch (0.2.0):
- RNWatch (0.4.3):
- React
- Yoga (1.14.0)
@@ -409,6 +411,7 @@ DEPENDENCIES:
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
- ReactCommon/turbomodule (from `../node_modules/react-native/ReactCommon`)
- "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)"
- RNDefaultPreference (from `../node_modules/react-native-default-preference`)
- "RNGoogleSignin (from `../node_modules/@react-native-community/google-signin`)"
- RNSound (from `../node_modules/react-native-sound`)
- RNSVG (from `../node_modules/react-native-svg`)
@@ -416,13 +419,11 @@ DEPENDENCIES:
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
SPEC REPOS:
https://github.com/CocoaPods/Specs.git:
trunk:
- Amplitude-iOS
- AppAuth
- boost-for-react-native
- CocoaLumberjack
- ObjectiveDropboxOfficial
trunk:
- AppAuth
- Crashlytics
- Fabric
- Firebase
@@ -442,6 +443,7 @@ SPEC REPOS:
- GTMAppAuth
- GTMSessionFetcher
- nanopb
- ObjectiveDropboxOfficial
- PromisesObjC
EXTERNAL SOURCES:
@@ -509,6 +511,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon"
RNCAsyncStorage:
:path: "../node_modules/@react-native-community/async-storage"
RNDefaultPreference:
:path: "../node_modules/react-native-default-preference"
RNGoogleSignin:
:path: "../node_modules/@react-native-community/google-signin"
RNSound:
@@ -562,7 +566,7 @@ SPEC CHECKSUMS:
React-jsiexecutor: de1c37cf59ae9adcbf2be82eea0e090dc3f3205e
React-jsinspector: b76c4e84a7833bb4c90549d59ed53ec299ff912b
react-native-background-timer: 0d34748e53a972507c66963490c775321a88f6f2
react-native-calendar-events: 2fe35a9294af05de0ed819d3a1b5dac048d2c010
react-native-calendar-events: 1442fad71a00388f933cfa25512588fec300fcf8
react-native-keep-awake: eba3137546b10003361b37c761f6c429b59814ae
react-native-netinfo: 8d8db463bcc5db66a8ac5c48a7d86beb3b92f61a
react-native-webrtc: 86d841823e66d68cc1f86712db1c2956056bf0c2
@@ -578,12 +582,13 @@ SPEC CHECKSUMS:
React-RCTVibration: a1bcfcdc0b5a73a1b0829a34cee22bd0e95bacba
ReactCommon: 675681aba4fecff5acbc0e440530cc422103c610
RNCAsyncStorage: 8e31405a9f12fbf42c2bb330e4560bfd79c18323
RNDefaultPreference: 56a405ce61033ac77b95004dccd7ac54c2eb50d1
RNGoogleSignin: 39336070b35fc4cea6a98cf111e00480317be0ae
RNSound: c980916b596cc15c8dcd2f6ecd3b13c4881dbe20
RNSVG: aac12785382e8fd4f28d072fe640612e34914631
RNWatch: 09738b339eceb66e4d80a2371633ca5fb380fa42
RNWatch: a5320c959c75e72845c07985f3e935e58998f1d3
Yoga: 7b4209fda2441f99d54dd6cf4c82b094409bb68f
PODFILE CHECKSUM: f615794fb9184757b00cd16e534824ba6ee2fc98
PODFILE CHECKSUM: 082858daebbe170e7a490de433e7f2a99e0c3701
COCOAPODS: 1.8.4
COCOAPODS: 1.9.1

View File

@@ -1,206 +1,3 @@
# Jitsi Meet SDK for iOS
The Jitsi Meet iOS SDK provides the same user experience as the Jitsi Meet app,
in a customizable way which you can embed in your apps.
## Sample applications using the SDK
If you want to see how easy integrating the Jitsi Meet SDK into a native application is, take a look at the
[sample applications repository](https://github.com/jitsi/jitsi-meet-sdk-samples).
## Usage
There are 2 ways to integrate the SDK into your project:
- Using CocoaPods
- Building it yourself
### Using CocoaPods
Follow the instructions [here](https://github.com/jitsi/jitsi-meet-ios-sdk-releases/blob/master/README.md).
### Building it yourself
1. Install all required [dependencies](https://github.com/jitsi/jitsi-meet/blob/master/doc/mobile.md).
2. `xcodebuild -workspace ios/jitsi-meet.xcworkspace -scheme JitsiMeet -destination='generic/platform=iOS' -configuration Release archive`
After successfully building Jitsi Meet SDK for iOS, copy
`ios/sdk/JitsiMeet.framework` (if the path points to a symbolic link, follow the
symbolic link) and
`node_modules/react-native-webrtc/ios/WebRTC.framework` into your project.
## API
JitsiMeet is an iOS framework which embodies the whole Jitsi Meet experience and
makes it reusable by third-party apps.
To get started:
1. Add a `JitsiMeetView` to your app using a Storyboard or Interface Builder,
for example.
2. Then, once the view has loaded, set the delegate in your controller and load
the desired URL:
```objc
- (void)viewDidLoad {
[super viewDidLoad];
JitsiMeetView *jitsiMeetView = (JitsiMeetView *) self.view;
jitsiMeetView.delegate = self;
JitsiMeetConferenceOptions *options = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
builder.serverURL = [NSURL URLWithString:@"https://meet.jit.si"];
builder.room = @"test123";
builder.audioOnly = YES;
}];
[jitsiMeetView join:options];
}
```
### JitsiMeetView class
The `JitsiMeetView` class is the entry point to the SDK. It a subclass of
`UIView` which renders a full conference in the designated area.
#### delegate
Property to get/set the `JitsiMeetViewDelegate` on `JitsiMeetView`.
#### join:JitsiMeetConferenceOptions
Joins the conference specified by the given options.
```objc
JitsiMeetConferenceOptions *options = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
builder.serverURL = [NSURL URLWithString:@"https://meet.jit.si"];
builder.room = @"test123";
builder.audioOnly = NO;
builder.audioMuted = NO;
builder.videoMuted = NO;
builder.welcomePageEnabled = NO;
}];
[jitsiMeetView join:options];
```
#### leave
Leaves the currently active conference.
#### Universal / deep linking
In order to support Universal / deep linking, `JitsiMeet` offers 2 class
methods that you app's delegate should call in order for the app to follow those
links.
If these functions return NO it means the URL wasn't handled by the SDK. This
is useful when the host application uses other SDKs which also use linking.
```objc
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler
{
return [[JitsiMeet sharedInstance] application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}
```
And also one of the following:
```objc
// See https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623073-application?language=objc
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
return [[JitsiMeet sharedInstance] application:app
openURL:url
options: options];
}
```
### JitsiMeetViewDelegate
This delegate is optional, and can be set on the `JitsiMeetView` instance using
the `delegate` property.
It provides information about the conference state: was it joined, left, did it
fail?
All methods in this delegate are optional.
#### conferenceJoined
Called when a conference was joined.
The `data` dictionary contains a "url" key with the conference URL.
#### conferenceTerminated
Called when a conference was terminated either by user choice or due to a
failure.
The `data` dictionary contains an "error" key with the error and a "url" key
with the conference URL. If the conference finished gracefully no `error`
key will be present.
#### conferenceWillJoin
Called before a conference is joined.
The `data` dictionary contains a "url" key with the conference URL.
#### enterPictureInPicture
Called when entering Picture-in-Picture is requested by the user. The app should
now activate its Picture-in-Picture implementation (and resize the associated
`JitsiMeetView`. The latter will automatically detect its new size and adjust
its user interface to a variant appropriate for the small size ordinarily
associated with Picture-in-Picture.)
The `data` dictionary is empty.
### Picture-in-Picture
`JitsiMeetView` will automatically adjust its UI when presented in a
Picture-in-Picture style scenario, in a rectangle too small to accommodate its
"full" UI.
Jitsi Meet SDK does not currently implement native Picture-in-Picture on iOS. If
desired, apps need to implement non-native Picture-in-Picture themselves and
resize `JitsiMeetView`.
If `delegate` implements `enterPictureInPicture:`, the in-call toolbar will
render a button to afford the user to request entering Picture-in-Picture.
## Dropbox integration
To setup the Dropbox integration, follow these steps:
1. Add the following to the app's Info.plist and change `<APP_KEY>` to your
Dropbox app key:
```
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string></string>
<key>CFBundleURLSchemes</key>
<array>
<string>db-<APP_KEY></string>
</array>
</dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>dbapi-2</string>
<string>dbapi-8-emm</string>
</array>
```
2. Make sure your app calls the Jitsi Meet SDK universal / deep linking delegate
methods.
This document has been moved to [The Handbook](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-ios-sdk).

View File

@@ -18,25 +18,17 @@
#import "AppDelegate.h"
#import "FIRUtilities.h"
#import "Types.h"
#import "ViewController.h"
@import Crashlytics;
@import Fabric;
@import Firebase;
@import JitsiMeet;
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Initialize Crashlytics and Firebase if a valid GoogleService-Info.plist file was provided.
if ([FIRUtilities appContainsRealServiceInfoPlist]) {
NSLog(@"Enablign Crashlytics and Firebase");
[FIRApp configure];
[Fabric with:@[[Crashlytics class]]];
}
JitsiMeet *jitsiMeet = [JitsiMeet sharedInstance];
jitsiMeet.conferenceActivityType = JitsiMeetConferenceActivityType;
@@ -54,11 +46,25 @@
#endif
}];
// Initialize Crashlytics and Firebase if a valid GoogleService-Info.plist file was provided.
if ([FIRUtilities appContainsRealServiceInfoPlist] && ![jitsiMeet isCrashReportingDisabled]) {
NSLog(@"Enabling Crashlytics and Firebase");
[FIRApp configure];
[Fabric with:@[[Crashlytics class]]];
}
[jitsiMeet application:application didFinishLaunchingWithOptions:launchOptions];
return YES;
}
- (void) applicationWillTerminate:(UIApplication *)application {
NSLog(@"Application will terminate!");
// Try to leave the current meeting graceefully.
ViewController *rootController = (ViewController *)self.window.rootViewController;
[rootController terminate];
}
#pragma mark Linking delegate methods
- (BOOL)application:(UIApplication *)application

View File

@@ -16,12 +16,7 @@
#import "FIRUtilities.h"
// Plist file name.
NSString *const kGoogleServiceInfoFileName = @"GoogleService-Info";
// Plist file type.
NSString *const kGoogleServiceInfoFileType = @"plist";
NSString *const kGoogleAppIDPlistKey = @"GOOGLE_APP_ID";
@import JitsiMeet;
@implementation FIRUtilities
@@ -30,37 +25,11 @@ NSString *const kGoogleAppIDPlistKey = @"GOOGLE_APP_ID";
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSBundle *bundle = [NSBundle mainBundle];
containsRealServiceInfoPlist = [self containsRealServiceInfoPlistInBundle:bundle];
containsRealServiceInfoPlist = [InfoPlistUtil containsRealServiceInfoPlistInBundle:bundle];
});
return containsRealServiceInfoPlist;
}
+ (BOOL)containsRealServiceInfoPlistInBundle:(NSBundle *)bundle {
NSString *bundlePath = bundle.bundlePath;
if (!bundlePath.length) {
return NO;
}
NSString *plistFilePath = [bundle pathForResource:kGoogleServiceInfoFileName
ofType:kGoogleServiceInfoFileType];
if (!plistFilePath.length) {
return NO;
}
NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile:plistFilePath];
if (!plist) {
return NO;
}
// Perform a very naive validation by checking to see if the plist has the dummy google app id
NSString *googleAppID = plist[kGoogleAppIDPlistKey];
if (!googleAppID.length) {
return NO;
}
return YES;
}
+ (NSURL *)extractURL: (FIRDynamicLink*)dynamicLink {
NSURL *url = nil;
if (dynamicLink != nil) {

View File

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

View File

@@ -20,4 +20,6 @@
@interface ViewController : UIViewController<JitsiMeetViewDelegate>
- (void)terminate;
@end

View File

@@ -102,4 +102,11 @@
}
#endif
#pragma mark - Helpers
- (void)terminate {
JitsiMeetView *view = (JitsiMeetView *) self.view;
[view leave];
}
@end

View File

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

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