Compare commits

...

301 Commits

Author SHA1 Message Date
Jonathan Lennox
81cf79e643 In loadtest, make localAudio non-const. (#8829)
(Because we modify it.)
2021-03-18 09:39:13 -04:00
Mihai-Andrei Uscat
a22d054b10 feat(InviteMore): Relocate invite prompt for mobile friendliness. 2021-03-18 14:09:22 +02:00
Vlad Piersec
7fce181080 feat(config): Add config option to allow unsetting local video flip 2021-03-18 09:35:42 +02:00
Vlad Piersec
92735478d1 fix(toolbox): Fix overflow menu & button background 2021-03-18 09:16:43 +02:00
Mihai-Andrei Uscat
7dabfc21b4 feat(Chat): Revamp design.
* ensure keyboard stays open when sending messages on mobile web.
2021-03-18 09:08:34 +02:00
Saúl Ibarra Corretgé
1395f84550 fix(virtual-background) fix tainted canvas when using the CDN
When we use a CDN the images come from an origin different than the site so
unless we mark them for CORS the canvas where they are painted will be tainted.

Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image
2021-03-17 16:32:16 +01:00
Vlad Piersec
d080460f9b fix(toolbox): Fix mic disabled icon 2021-03-17 15:23:45 +02:00
tmoldovan8x8
61567f47c0 fix(android) changes the property name for the manifestOutputDirectory 2021-03-17 14:19:43 +01:00
Avram Tudor
4f3058eae2 Merge pull request #8823 from jitsi/tavram/hide-support
fix(jaas) hide support link in invite error for jaas users
2021-03-17 15:16:32 +02:00
Tudor-Ovidiu Avram
3a073d9af4 fix(jaas) hide support link in invite error for jaas users 2021-03-17 11:53:58 +02:00
Mihai-Andrei Uscat
aef0287605 feat(ToggleCamera): Implement for web. 2021-03-17 10:44:18 +02:00
Vlad Piersec
bb19567efa fix(prejoin): Use localFlipX on prejoin screen 2021-03-17 09:19:55 +01:00
Saúl Ibarra Corretgé
79ab973694 chore(deps) update react-native-webrtc
Fix script for downloading bitcode.
2021-03-16 22:09:21 +01:00
Saúl Ibarra Corretgé
7046785ca3 chore(deps) update react-native-webrtc to 1.89.1 2021-03-16 19:57:26 +01:00
Saúl Ibarra Corretgé
b817bd19d5 chore(deps) bump js-utils to 1.0.6
Fixes a harmless but confusing error in postis processing when using the
Bitwarden Chrome extension, for example.
2021-03-16 19:57:03 +01:00
luz paz
817d54b0b9 fix(misc) typos
Found via `codespell -q 3 -S ./lang`
2021-03-16 16:12:12 +01:00
Vlad Piersec
3f0bb6818c fix(toolbox): Fix always on top toolbar 2021-03-16 16:07:49 +01:00
Saúl Ibarra Corretgé
4fa47c8070 fix(virtual-background) use a DOM element for storing the image
THis will reuse the previously cached image and obey the base href.

Ref:
https://stackoverflow.com/questions/6241716/is-there-a-difference-between-new-image-and-document-createelementimg
2021-03-16 11:27:27 +01:00
Saúl Ibarra Corretgé
0dcb8a025b fix(rn,bottomsheet) limit width 2021-03-16 11:19:52 +01:00
tmoldovan8x8
8defaa9aec feat(android): adds timer to OngoingNotification 2021-03-16 12:13:37 +02:00
Vlad Piersec
d214079148 fix(toolbox): Constrain toolbox width on large mobile device 2021-03-16 09:50:49 +01:00
Vlad Piersec
096ee3cb53 fix(toolbox): Background of disabled settings button & tileview button 2021-03-16 09:20:02 +01:00
Vlad Piersec
fd606896b8 fix(toolbox): Fix buttons size in minified mode 2021-03-16 09:32:36 +02:00
Jonathan Lennox
226581a81a Add muteAudio function to load test JS. (#8802) 2021-03-15 15:37:58 -04:00
Avram Tudor
e1c5b1e626 Merge pull request #8799 from jitsi/tavram/billing-id
fix(vpaas) send jitsiMeetId instead of billingId
2021-03-15 15:54:57 +02:00
Tudor-Ovidiu Avram
831c5ba59d fix(vpaas) send jitsiMeetId instead of billingId 2021-03-15 13:22:17 +02:00
Andrei Gavrilescu
bad1bc91cf fix(screenshare): audio screen share muted state (#8785)
* AudioMixerEffect muted state

* update lib-jitsi-meet
2021-03-15 11:44:03 +02:00
Saúl Ibarra Corretgé
30d0aabaca feat(build,rnnoise) don't use an external bundle for the effect
The majority of the code is in the WASM file, the JS is just 9KB.
It's so little, in fact, that the performance hint for the main bundle didn't
have to be adjusted.
2021-03-12 23:00:50 +01:00
Saúl Ibarra Corretgé
22b6d32174 feat(build,virtual-background) don't use an external bundle for the effect
The majority of the code is in the WASM file and models, this is just a few KB.
It's so little, in fact, that the performance hint for the main bundle didn't
have to be adjusted.
2021-03-12 23:00:50 +01:00
Saúl Ibarra Corretgé
31ace267ce fix(virtual-background) use tighter edge smoothing 2021-03-12 15:05:20 +01:00
tudordan7
194d357005 feat(virtual-backgrounds) add virtual background support 2021-03-12 15:05:20 +01:00
Vlad Piersec
c2ad06c5e6 fix(toolbox): Restructure items order for desktop & mobile 2021-03-12 15:19:23 +02:00
Vlad Piersec
e40b02ab3c fix(icons): No hardcoded colors for some svgs 2021-03-12 11:29:20 +02:00
titus.moldovan
2587eefefc fix(chat) hides send private chat button when enable.chat flag is false. 2021-03-12 09:19:31 +01:00
Vlad Piersec
b87c433e99 fix(toolbar): Update overflow menu according to review 2021-03-11 15:49:00 +02:00
tmoldovan8x8
751644db16 makes disableAudioFocus flag generic, so it can be used also from iOS 2021-03-11 15:13:24 +02:00
Vlad Piersec
c508572cc5 feat(toolbox): Redesign mobile toolbox 2021-03-11 12:38:37 +01:00
Vlad Piersec
b86c271a80 fix(toolbar): Small changes according to design review 2021-03-11 11:57:17 +01:00
Hristo Terezov
5efbe5f0ec chore(deps) lib-jitsi-meet@latest
* fix(modificationQueue): error handling & logs
* feat(dominantSpeaker): Add previous speaker list.

e60f09b189...0ec072378c
2021-03-10 17:30:06 -06:00
Jaya Allamsetty
2784c43a1b fix(UI): Add playsinline attribute for remote video.
For the video to play on Safari mobile browser, the playsInline attribute needs to be set to true. Set the mute attribute as well which was accidentally removed in code refactor.
2021-03-10 18:05:41 -05:00
Hristo Terezov
f5a34183e9 fix(useVideoStream): error handling & add logs. 2021-03-10 17:02:29 -06:00
Hristo Terezov
29f5d87d77 fix(prejoin): Don't overwrite display name with '' 2021-03-10 15:10:41 -06:00
hmuresan
ab6790bdaa (external_api) Add command for overwriting config values. 2021-03-10 18:30:14 +02:00
damencho
2e308d67d8 feat: Fixes filtering not needed presences.
We were filtering only self presences, no it filters and the presences to the other participants.
2021-03-09 16:19:43 -06:00
Vlad Piersec
91ba835f78 feat(Toolbar): Redesign web toolbar 2021-03-09 16:29:44 +02:00
dependabot[bot]
2643029ac8 chore(deps): bump elliptic from 6.5.3 to 6.5.4
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.3 to 6.5.4.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.3...v6.5.4)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-09 14:19:38 +01:00
Saúl Ibarra Corretgé
e40e078a29 fix(ios,build) make sure the correct broadcast extension ID is set 2021-03-09 10:33:04 +01:00
Saúl Ibarra Corretgé
6df5a4cf31 fix(ios) make sure broadcast extension version matches
Fixes this Apple Store Connect warning:

~~~
ITMS-90473: CFBundleShortVersionString Mismatch - The CFBundleShortVersionString
value '1.0' of extension 'jitsi-meet.app/PlugIns/JitsiMeetBroadcast
Extension.appex' does not match the CFBundleShortVersionString value '21.0.0' of
its containing iOS application 'jitsi-meet.app'.
~~~
2021-03-09 10:33:04 +01:00
Saúl Ibarra Corretgé
c7c7d7a155 fix(ios) move extension to a path without spaces 2021-03-09 10:33:04 +01:00
Hristo Terezov
8f06866646 feat(config): Add useHostPageLocalStorage 2021-03-08 16:26:42 -06:00
damencho
b559cb8ec6 feat: Move checks for moderator in pre-join and filter extra presences.
We will filter the initial presence where participant is announced as `participant` and shortly after that we send a second presence with the new `moderator` role.
2021-03-08 16:01:32 -06:00
damencho
30a2e84da1 fix: Fixes filtering lobby presences. 2021-03-08 16:01:32 -06:00
Saúl Ibarra Corretgé
3122983000 fix(config) fix syntax error in commented code 2021-03-08 15:34:19 -06:00
Jean-François Alarie
407021e258 feat(rn,flags) add fullscreen.enabled flag 2021-03-08 22:11:39 +01:00
Jaya Allamsetty
1a62a7b1cc chore(deps) lib-jitsi-meet@latest
* feat(browser-support): Add support for WKWebview based browsers. Apple added getUserMedia support for WkWebview based browsers like chrome and Firefox on iOS 14.3. These browsers behave as Safari does on iOS. Therefore, extend the Safari checks to these webkit based browsers as well.

08ce96d881...e60f09b189
2021-03-08 12:12:31 -05:00
Jaya Allamsetty
0ee03f1538 feat(browser-support): Add support for WKWebview based browsers. 2021-03-08 11:16:02 -05:00
Jaya Allamsetty
572beb8382 chore(deps) lib-jitsi-meet@latest
* squash: Always get lastN value from JitsiConference instance.
* fix(lastN): Return the correct lastN value for the conference.
* Use unified plan for mobile browsers on iOS

d31b5a2d5e...08ce96d881
2021-03-08 10:26:14 -05:00
Mihai-Andrei Uscat
d0d32b8a19 fix(responsive): Fix tiles not recomputing when jumping between screen sizes 2021-03-05 12:35:09 -06:00
Saúl Ibarra Corretgé
82ff988c18 fix(ios) the broadcast extension'd bundle ID must match the app's 2021-03-05 18:02:48 +01:00
Jaya Allamsetty
8fa5d09612 chore(deps) lib-jitsi-meet@latest
* fix(conference): Do not signal muted tracks on join. Do not add the muted audio/video tracks to the peerconnection on join. The tracks will be added when the user unmutes for the first time. This reduces the number of remote sources that will be added when a participant joins a large call where everyone joins muted (startAudioMuted/startVideoMuted setting).

e83fb93d2d...d31b5a2d5e
2021-03-05 10:42:05 -05:00
Alex Bumbu
508f1e0da9 feat(iOS): screensharing support
The Jitsi team would like to thank @AliKarpuzoglu, @linuxpi and The Hopp Foundation for the initial effort and help throughout.
2021-03-05 16:33:53 +01:00
Jaya Allamsetty
dcda89012e fix(tracks): Do not signal muted audio tracks.
Do not add the muted audio tracks to peerconnection until the user unmutes the first time. This applies to startSilent, startWithAudioMuted and startAudioMuted/startVideoMuted config.js settings.
2021-03-05 10:18:34 -05:00
Saúl Ibarra Corretgé
d93a402cc2 fix(rn,tracks) fix not showing alert when permission is not granted
The error object changed its shape through time, adapt to the change.
2021-03-05 12:59:13 +01:00
Saúl Ibarra Corretgé
b7b260f4c9 feat(ci) fail CI if package-lock wasn't updated 2021-03-05 11:13:49 +01:00
Saúl Ibarra Corretgé
4db3f04c0c fix(deps) sync package-lock 2021-03-05 11:13:49 +01:00
Дамян Минков
126a2bd0d7 chore(deps): Checks presence editing and make sure we send only on change.
* fix: Checks presence editing and make sure we send only on change.

f1ec966780...e83fb93d2d
2021-03-04 16:52:24 -06:00
gpatel-fr
29bbcf8590 handles spaces around hostname
((users doubleclick a host name and paste result in the installer)
2021-03-04 11:39:05 -06:00
Saúl Ibarra Corretgé
5c46b03251 fix(copyText) use a helper library
It does a more elaborate way of textarea copying, hopefully it's more reliable.
2021-03-04 10:03:51 -06:00
るしふぁ
eeb5abbbe8 fix: date util localization (#8723)
* Update dateUtil.js

* version up moment

* exclude unnecessary languages in Moment.js from webpack

* add Occitan of Moment.js

* Fixed auto-formatting

* add require missing by mistake
2021-03-04 08:20:27 -06:00
roms2000
49583b611c Update main-fr.json
Add missing translation.
Improve French language / French styling.
Fix typos.
2021-03-03 21:22:52 -06:00
Hristo Terezov
9e29dd063f fix(live-stream-section): Use await for copyText 2021-03-03 16:26:36 -06:00
Hristo Terezov
a2e2d31dfd fix(copyText): in iframe for chrome<85 2021-03-03 16:12:59 -06:00
Óscar Carretero
62c06441b1 Normalize language format 2021-03-03 15:14:34 -06:00
Niklas
f718a3e050 lang: Update main-da.json (#8642)
* Update main-da.json

* Apply suggestions from code review

Co-authored-by: jokjr <69192941+jokjr@users.noreply.github.com>

* Update main-da.json

* Apply suggestions from code review

Co-authored-by: jokjr <69192941+jokjr@users.noreply.github.com>

Co-authored-by: jokjr <69192941+jokjr@users.noreply.github.com>
2021-03-03 14:44:31 -06:00
Steffen Kolmer
899968d3a9 feat: Only show more numbers link if multiple numbers are available (#8702)
* Only show more numbers link if multiple numbers are available

* Fixed some linter errors

* Try to make flow happy

* Fixed another linter error

* Another try to make eslint happy

* Silence eslint
2021-03-03 08:45:26 -06:00
Matthias Nagel
696f509f18 Corrected example config for Apache
- dropped uneccessary rewrite rule
 - corrected number of trailing slashs in proxy directive
 - corrected url for colibri websocket
2021-03-03 08:43:32 -06:00
Calinteodor
430591bd1e feat(shared-video) refactor dialog to use React
Also unify the mobile and web features into one, even though internally they still have separate ways to enable the functionality.
2021-03-03 15:37:38 +01:00
dimitardelchev93
8ee324b37f Add missing translation in main-de.json (#8664) 2021-03-03 08:16:16 -06:00
tmoldovan8x8
399d6b6a4b chore(version) bumps mobile sdkVersion to 3.2.0 2021-03-02 15:21:20 +01:00
Saúl Ibarra Corretgé
ffad21cb59 fix(ios) sync podfile 2021-03-02 10:31:47 +01:00
Steffen Kolmer
ce6debac45 Revert changes dial in numbers link 2021-02-26 23:30:57 -06:00
Steffen Kolmer
5d8bf0c1e7 feat: Add a new setting to remove individual sharing features from UI (#8660)
* Added new config to enable individual sharing features

* make config values url friendly

* Add new setting to whitelist

* Fixed some linter issues

* Fixed more linter issues

* Fixed merge error

* Check if interfaceConfig is defined

* Only show more numbers link if there is more than one number
2021-02-26 19:50:26 -06:00
Steffen Kolmer
7bbd06c9f4 Use logger instead of console 2021-02-26 19:50:02 -06:00
Hristo Terezov
79a67049a9 chore(deps) lib-jitsi-meet@latest
* fix(RTCUtils): Init availableDevices.

e6ef4e7ae9...f1ec966780
2021-02-26 17:59:11 -06:00
Hristo Terezov
b1a3c5cd7b feat(external_api): allow clipboard-write 2021-02-26 15:05:45 -06:00
Hristo Terezov
9573a615b1 chore(deps) lib-jitsi-meet@latest
* fix(RTC) fix device selection not being available
* fix(TPCUtils): undefined is not an object (evaluating 'this.tpcUtils.replaceTrack(e,t).then')

4c668023b3...e6ef4e7ae9
2021-02-26 12:48:23 -06:00
Jaya Allamsetty
5d09102e48 chore(deps) lib-jitsi-meet@latest
* fix(TPC): Remove the existing track instead of overwriting. When a second remote track of the same mediatype is received for an endpoint, remove the existing track before creating the new remote track.

9beb47fe5f...4c668023b3
2021-02-26 10:24:48 -05:00
Tudor D. Pop
cc0ecc1fdd fix(blur) disable blur button if camera is off 2021-02-26 16:03:51 +01:00
Saúl Ibarra Corretgé
cecf324023 fix(deps) bump lodash
Fixes: https://github.com/jitsi/jitsi-meet/issues/8683
2021-02-25 16:16:18 +01:00
Saúl Ibarra Corretgé
943d5dca35 chore(deps) remove Tensorflow
We use TFLite now so this is unused.
2021-02-25 14:14:28 +01:00
Tudor D. Pop
dd1f8339b1 fix(blur-effect) enable blur effect on all platforms supporting canvas filters
That means all browsers except Safari, for now.

In addition, use the 96p model (instead of the 144p one) on browsers without SIMD support.
2021-02-25 13:21:03 +01:00
tudordan7
159f59b665 fix(lint-run-command) 2021-02-25 11:24:03 +01:00
Steffen Kolmer
23bb824731 feat: Added mute video moderation feature (#8630)
* Added mute video feature

* Fixed export

* Fixed some issues

* Added remote video mute notification

* Fixed import

* Fixed conference event handling

* Fixed some linting issues

* Fixed more linter errors

* turn screenshare off on remote video mute

* Fix linter issue

* translations added for mute video feature

* Added video mute button to interface config

* Updated lib-jitsi-meet

* Fix copy paste error

Co-authored-by: nurjinn jafar <nurjin.jafar@nordeck.net>
2021-02-24 15:45:07 -06:00
Saúl Ibarra Corretgé
42d926eef3 chore(deps) lib-jitsi-meet@latest
* fix(e2ee) fix disabling E2EE
* fix(e2ee) fix key index after ratchetting
* fix: Drop caps handling (#1495)
* fix(SendVideoController): Apply the sender constraint only when it changes. There were cases where the bridge was sending the same constraint multiple times causing redundant calls to getParameters/setParameters on the RTCRtpSender.
* feat: Use the new bridge signaling format.
* fix(gum) update permissions prompt detection

c534f74884...6a7b16c33e
2021-02-24 18:17:09 +01:00
Calinteodor
87a110b9c3 fix: improved copy text helper function (#8677) 2021-02-24 09:12:41 -06:00
Mihai-Andrei Uscat
a7db7ecaff fix(LargeVideo): Fix large video not resizing when closing chat. 2021-02-24 14:26:00 +02:00
horymury
79bb98dab3 (feature) - Add support for custom DID numbers page url 2021-02-24 11:37:14 +02:00
Gabriel Imre
d22792c9e3 feat(sip): Added auto-knocking for sip gateway if lobby is enabled
Co-authored-by: Gabriel Imre <gabriel.lucaci@8x8.com>
2021-02-24 11:35:32 +02:00
Avram Tudor
41e6af3464 Merge pull request #8120 from jitsi/tavram/slowgum
fix(gum) add event handling for SLOW_GET_USER_MEDIA
2021-02-23 14:45:36 +02:00
Tudor-Ovidiu Avram
f50fd7b7bd fix(gum) add event handling for SLOW_GET_USER_MEDIA
Show an overlay with a spinner when slow gUM is fired
2021-02-23 13:51:24 +02:00
Mihai-Andrei Uscat
43761fc398 feat(Chat) Improve responsive behaviour further.
* Add buttons to send messages/set nickname.
* Redesign message/nickname inputs.
* Pin messages to the input.
* Add keyboard avoider for Safari.
* Make chat content scrollable on mobile.
2021-02-23 09:39:20 +02:00
damencho
4c39d83ff1 feat(load-test): Fixes audio senders. 2021-02-22 17:48:19 -06:00
Jaya Allamsetty
e525c2b2ec chore(deps) lib-jitsi-meet@latest
* fix(SendVideoController): Apply the sender constraint only when it changes. There were cases where the bridge was sending the same constraint multiple times causing redundant calls to getParameters/setParameters on the RTCRtpSender.
* fix(gum) update permissions prompt detection

beaff3dd02...7f919faacc
2021-02-19 12:04:25 -05:00
Tudor D. Pop
f69a31d9c6 fix(blur) check model response status and catch errors 2021-02-19 15:00:07 +01:00
tmoldovan8x8
67930edae2 chore(ios) remove warnings on JitsiMeetView 2021-02-19 10:40:45 +02:00
Jaya Allamsetty
c11a94f7d7 feat: Add 'useNewBandwidthAllocationStrategy' to config.js. 2021-02-18 14:30:39 -05:00
Jaya Allamsetty
bfd093b0ba chore(deps) lib-jitsi-meet@latest
* feat: Use the new bridge signaling format.

c534f74884...beaff3dd02
2021-02-18 14:30:39 -05:00
Saúl Ibarra Corretgé
861935c9d7 fix(blur) fix model paths 2021-02-18 15:57:01 +01:00
Дамян Минков
8fcaea9e3d feat(load-test): Load test startmuted (#8629)
* feat(load-test): Senders unmute themselves if muted by policy.

* feat(load-test): Adds option to skip creating local audio track.

We currently create local audio track even when starting audio muted. Adding the option to control that can load test that for clients or signalling.
2021-02-17 10:28:01 -06:00
Pawel Domas
e0aab11f98 fix: TypeError: Cannot read property 'isAudioTrack' of undefined
When there's no jitsiTrack set on the base/tracks entry it means
a track is being created (get user media is in progress).
2021-02-17 09:25:09 -06:00
Tudor D. Pop
946339a52e feat(blur) replace BodyPix with TFLite
Use the Google Meet model and SIMD optimized WASM.
2021-02-17 16:03:33 +01:00
tmoldovan8x8
f71e8a9982 feat(mobile) adds actions and events for the chat 2021-02-17 16:26:40 +02:00
chipechop
af6080f173 fix(lang) update Italian translation 2021-02-17 13:25:23 +01:00
Jaya Allamsetty
b1080340ec chore(deps) lib-jitsi-meet@latest
* ref(QualityController): Split send and receive video constraints handling.
* fix: Save guards _features to be always empty and nver undefined. (#1493)

d1f0ab4d5a...c534f74884
2021-02-16 11:16:08 -05:00
damencho
684d121159 fix(load-test): Fixes keepalive url when using load-test. 2021-02-12 13:03:29 -06:00
Saúl Ibarra Corretgé
6740b0861e fix(rn,lobby) make sure the enable dialog follows the theme color 2021-02-12 16:40:56 +01:00
tmoldovan8x8
65c56669c4 feat refactors the chat flow so it has open and close functions 2021-02-12 13:18:16 +02:00
Дамян Минков
2cd43ba2e4 fix(load-test): Always create local audio track. (#8612)
* fix(load-test): Always create local audio track.

When audio mutes will mute the track. Also fixes previous change where we do not add any of the tracks to the room.

* squash: Fix lint errors.
2021-02-11 17:25:46 -06:00
Hristo Terezov
fec2641730 fix(popups): covered by labels. 2021-02-11 16:18:56 -06:00
damencho
04ee423257 fix(load-test): Create local tracks and then join.
Behaves now as the main client, and skips few unnecessary presences.
2021-02-11 15:14:31 -06:00
Hristo Terezov
460e137ee4 chore(deps) lib-jitsi-meet@latest
* fix(GUM-permissions): cache permissions on init.
* feat: Reuse billingId from localstorage as jitsiMeetId.
* fix(example) simplify
* feat(docs) mvoe API documentatrion to the handbook

84357ce1a8...d1f0ab4d5a
2021-02-11 13:56:46 -06:00
hmuresan
1a789130a3 feat (external_api) add command for kick participant 2021-02-11 07:33:26 -06:00
Nando Thomassen
16b00dc2af feat(flags) add feature flag for help button
Introduces a new feature flag ('help.enabled') and uses that to
determine the visibility of the 'Help' button in a call.
2021-02-10 22:34:13 +01:00
Saúl Ibarra Corretgé
c3a41b8cf3 fix(avatar) refactor preloading to avoid CORS issues
Fixes: https://github.com/jitsi/jitsi-meet/issues/8510

This basically reverts
a3fb996ff0
while retaining the same properties that prompted it's original intent, namely
avoiding sending the Referrer header.
2021-02-10 14:32:56 +01:00
damencho
f4d0ec1bb4 fix(load-test): Uses websocket if available and adds room param to the connection url. 2021-02-09 15:48:06 -06:00
tmoldovan8x8
ef6b641802 bugfix(ios) changes the participantInfo completion handler reference to strong.
When the method was called from Swift they were collected before calling them.
2021-02-09 18:03:25 +02:00
Saúl Ibarra Corretgé
579acbc570 feat(embed-meeting) add autoplay permission to iframe sample 2021-02-09 08:01:51 -06:00
niteshletxsoft
bca9a12df1 feat(external_ap) add api call to get live stream url 2021-02-09 12:43:38 +01:00
Shoolpani Dubey
a57b967f2e fix(external_api) add autoplay capabilities to created iframe
Should fix https://github.com/jitsi/jitsi-meet/issues/7037
2021-02-09 11:22:42 +01:00
Hristo Terezov
299927fcad docs: Add comment for initial GUM timeout values. 2021-02-08 15:53:38 -06:00
Hristo Terezov
7dc899ace1 ref(DeviceSelectionPopup): remove. 2021-02-08 15:53:38 -06:00
Hristo Terezov
a6c6cd6c56 fix: Add GUM timeout & improve device permissions 2021-02-08 15:53:38 -06:00
Hristo Terezov
7dc45c28a2 fix(AudioSlider): removed when volume is 0 2021-02-08 15:25:17 -06:00
Hristo Terezov
a215f9706a chore(deps) lib-jitsi-meet@latest
* fix(GUM): improve permissions logic.
* feat(GUM): timeout.
* ref: Remove pinEndpoint. (#1440)

30c8795770...84357ce1a8
2021-02-08 14:52:25 -06:00
Jonathan Lennox
4beca0d5dd Set receiver video constraint in load-test script, as-if tile view. (#8567) 2021-02-08 13:35:03 -05:00
Vlad Piersec
bfc4b2ac6f feat(vpaas): Send billing id to prosody 2021-02-08 12:49:55 +02:00
kazan417
53bdaa7928 fix(lang) update Russian translation 2021-02-07 12:44:20 +01:00
Tobias Kneidl
ba18b12024 add module proxy_wstunnel 2021-02-06 22:49:12 -06:00
Tobias Kneidl
a1438f1f21 change websocket url from http:// to ws:// 2021-02-06 22:49:04 -06:00
Julian1203
c856c20513 Update main-de.json
Small improvements (again)
2021-02-06 07:27:55 -06:00
Julian1203
cf92c964b4 Update main-de.json
Small improvements (again)
2021-02-05 22:15:51 -06:00
Julian1203
e69529867e Update main-de.json
Small improvements for the gender-neutral version and other small improvements.
2021-02-05 16:15:39 -06:00
Jaya Allamsetty
fd313c1af7 fix(tests): Add more checks so that test don't error out. 2021-02-05 16:30:58 -05:00
Jonathan Lennox
73c3feb8fa Improve load-test script. (#8563)
* In load-test, merge URL params into config.

* Honor config.testing.noAutoPlayVideo in load-test.
2021-02-05 16:00:28 -05:00
Дамян Минков
67a01364d3 Move load-test to resources (#8560)
* fix: Move load-test to resources.

* squash: Updates load-test dependencies.

* squash: Fix load-test build.
2021-02-05 09:12:45 -06:00
Saúl Ibarra Corretgé
7a64bf006e misc(tools) add script for updating mobile apps versions 2021-02-05 11:56:44 +01:00
Saúl Ibarra Corretgé
e5ea96fd4c feat(rn) update SDK version to 3.1.0 2021-02-05 11:56:44 +01:00
Saúl Ibarra Corretgé
c8ad04d0ff misc(tools) add script for updating SDK version 2021-02-05 11:56:44 +01:00
Saúl Ibarra Corretgé
c56afde00c feat(dev) bind to 0.0.0.0 on the dev server by default 2021-02-05 11:15:20 +01:00
tmoldovan8x8
9ed1969f7e feat(android) adds ability to disable the requestFocus on Android 2021-02-05 09:05:55 +02:00
Jonathan Lennox
12680c35ca Add lightweight load-test webpage, disabled by default (#8514)
Co-authored-by: Hristo Terezov <hristo@jitsi.org>
Co-authored-by: damencho <damencho@jitsi.org>
2021-02-04 18:04:36 -05:00
Jaya Allamsetty
0138f23755 feat(conference): Enable forced reload of client on bridge failure.
* feat(conference): Enable forced reload of client on bridge failure.
Force the client to reload when the bridge that is handling the media goes down.
This mitigates issues seen on the bridge because of a client re-joining the call with the same endpointId, BWE issues, etc.
This behavior is configurable through 'enableForcedReload' setting in config.js.
The client skips the pre-join page when the page reloads.

* squash: refactor the restart logic.

* squash: fix description

* squash: dispatch conferenceWillLeave action before reload.
2021-02-04 12:33:18 -05:00
Marc Seitz
16d88a288f feat: add ipados to list of Platform.OS (#8205)
* feat: add ipados list of Platform.OS
2021-02-04 10:34:44 -05:00
Jaya Allamsetty
210c4857fd deps: Update latest@lib-jitsi-meet.
Add the ability to configure different max bitrates for VP8 and VP9.
Set max bitrate for presenter to 2500 Kbps irrespective of the configured max bitrates for video.
479dd98...77978f0.
2021-02-04 09:50:32 -05:00
tmoldovan8x8
dca96f25f3 feat(mobile) adds feature flags for audioMute, videoMute and overflow… (#8537) 2021-02-04 15:32:09 +02:00
Mihai-Andrei Uscat
b69e93a900 fix(Safari): Fix mobile double tapping for toolbar and overflow.
* Create generic tooltip wrapper for mobile usability.
* Change overflow menu icon/font/padding sizes.
* Change overflow drawer expand icon.
2021-02-04 15:24:25 +02:00
tmoldovan8x8
d2568b874b feat(mobile) adds ability to retrieve participantsInfo array 2021-02-04 14:26:35 +02:00
Juan Searle
20c6115c38 Fix suspicious URL on Persian localization file 2021-02-03 20:39:08 -06:00
OctopusET
68b8ee5961 fix(lang) update korean translation 2021-02-03 15:52:59 +01:00
Andrei Gavrilescu
9895a04609 feat(rtcstats): send meeting uuid to rtcstats (#8526)
* send meeting uuid to rtcstats

* change ret description

* fix flow error

* update lib-jitsi-meet version
2021-02-03 12:28:39 +02:00
Andrzej Moskal
87f688dc8f fix(android) add ability to localize notification actions strings 2021-02-03 10:58:05 +01:00
Jaya Allamsetty
c58657c759 fix(test): Make sure test doesn't error out. 2021-02-01 11:49:45 -05:00
Ali Kazemkhanloo
687106818a Add Persian to languages-fa.json 2021-02-01 07:49:58 -06:00
Ali Kazemkhanloo
f228b4ecc1 Add Persian language to the list of languages 2021-02-01 07:49:58 -06:00
kichinosukey
8582b25d28 typo fix 2021-02-01 07:46:32 -06:00
Vlad Piersec
9418dbc2b1 fix(recents-list): Order recents by last used 2021-02-01 13:30:34 +02:00
Jonas Rittershofer
19bf027b8b Include xmpp and colibri proxy for apache
Signed-off-by: Jonas Rittershofer <jotoeri@users.noreply.github.com>
2021-01-30 10:06:22 -06:00
Mihai-Andrei Uscat
c370c05701 fix(Filmstrip): Prevent Toolbox from being shown indefinitely when hovering filmstrip 2021-01-29 15:34:37 +02:00
Emil Ivov
f034f179ff Merge pull request #8507 from saghul/readme-jaas
fix(docs) add JaaS link to README
2021-01-29 06:57:51 -06:00
Saúl Ibarra Corretgé
b94b18770c fix(docs) add JaaS link to README 2021-01-29 13:54:27 +01:00
Mihai-Andrei Uscat
3f93726c41 fix(Safari): Fix zoomed in mobile interface and cropped tile 2021-01-29 12:55:24 +02:00
Titus-Andrei Moldovan
af8072d9d2 chore(mobile) changes the name for screenShares to remoteScreenShares to better reflect it's content 2021-01-29 12:45:53 +02:00
Titus-Andrei Moldovan
45f4643469 feat(mobile) adds ToggleScreenShare event and action. 2021-01-29 12:45:53 +02:00
Avram Tudor
745879c447 Merge pull request #8503 from jitsi/tavram/dropbox
feat(external_api) allow dropbox option to be overwritten
2021-01-29 12:30:03 +02:00
Mihai-Andrei Uscat
4aab5e2054 feat(Dialog): Make dialog close button more mobile friendly.
* Remove pointless custom headers, fall back to ModalHeader instead.
2021-01-29 12:22:43 +02:00
Tudor-Ovidiu Avram
69971a0e90 feat(external_api) allow dropbox option to be overwritten 2021-01-29 11:44:16 +02:00
Pawel Domas
7c90f75ec9 fix(conference.js): crash on undefined
While on the prejoin screen, the local tracks are managed by the redux store and not conference.js, so localAudio is undefined.
2021-01-28 21:59:44 -05:00
damencho
bf714c1c8b feat: Allow star for room in moderated tenants. 2021-01-28 16:28:39 -06:00
Avram Tudor
8414e9d99f Merge pull request #8495 from jitsi/tavram/chat-updated
feat(external_api) add event for chat updates (unread counter, open s…
2021-01-28 16:42:06 +02:00
Tudor-Ovidiu Avram
dcaad41e69 feat(external_api) add event for chat updates (unread counter, open state) 2021-01-28 11:41:27 +02:00
Jonathan Lennox
63f0166f75 Add mime type mapping for wasm to default Debian nginx config. 2021-01-27 13:42:37 -06:00
Дамян Минков
79f3756d33 feat: Adds option to set ws keepalive url through config. (#8487)
* feat: Adds option to set ws keepalive url through config.

* chore(deps) lib-jitsi-meet@latest

* feat: Adds option to set ws keepalive url through config.
* fix VADAudioAnalyser: catch error

be18ff34be...9fdde46694
2021-01-27 11:13:32 -06:00
damencho
5ac30262a5 fix(debian): Improves handling db_get. 2021-01-26 09:49:03 -06:00
damencho
09315fa653 fix: Adds luasec as dependency.
This is in Recommended but we need it.
2021-01-26 09:49:03 -06:00
damencho
5f0dd903f6 fix(debian): Fixes enforce_apache option. 2021-01-26 09:49:03 -06:00
Steffen Kolmer
ef7d425859 feat(ui) update AtlasKit components 2021-01-26 16:47:55 +01:00
bgrozev
a9bb8e5e81 fix: Use internal_hashed everywhere. (#8485) 2021-01-26 09:33:41 -06:00
Mihai-Andrei Uscat
8cf4e15b23 Add config flag for tile responsiveness 2021-01-26 13:42:57 +02:00
Mihai-Andrei Uscat
db84889143 feat(tiles): Add responsive behaviour.
* Enforce fixed column number at various width breakpoints.
* Bring back the filmstrip at small sizes but hide it.
* Change default maximum columns to 7.
2021-01-26 13:42:57 +02:00
Ali Karpuzoglu
6ca3c6e43a fix(misc) typo 2021-01-26 12:38:49 +01:00
DeBuXer
6fd280a960 fix(lang) update Dutch translation 2021-01-26 11:27:42 +01:00
Jonas Rittershofer
6f9e65d348 Allow to enforce Apache via debconf
Signed-off-by: Jonas Rittershofer <jotoeri@users.noreply.github.com>
2021-01-25 16:27:01 -06:00
damencho
f1e06bff7b fix: Lobby display name set when preJoin is disabled. Fixes #8415. 2021-01-25 16:03:54 -06:00
Jaya Allamsetty
1cf7a361e9 feat: Implement aggressive layer suspension on RN.
RN doesn't support RTCRtpSender yet. Therefore, media is suspended on RN by changing the media direction in the SDP whenever the client receives an ideal height of 0 for sender constraints on the bridge channel.
LJM update - 3570339360...be18ff34be.
2021-01-25 15:21:16 -05:00
okyanusoz
e7990baa7d Fixed Turkish translation issues 2021-01-25 13:36:32 -06:00
Cedric Roijakkers
d35708815d fix(lang) corrected Dutch translation of toggleCamera 2021-01-22 17:39:20 +01:00
Jaya Allamsetty
270e52e402 deps(ljm): Restore local connection status.
831716c160...3570339360.
2021-01-22 10:44:01 -05:00
Saúl Ibarra Corretgé
635d283d5a chore(deps) react-native-callstats@3.70.1
Support processing stats in the spec-compliant format.
2021-01-22 14:06:10 +01:00
Balu
4affc68b50 Update main-de.json
Added missing "user" dialog parameter translation. Tried to stay gender neutral.
2021-01-22 06:24:42 -06:00
chipechop
dca262620b Update languages-it.json 2021-01-22 06:24:11 -06:00
as0bit
12c8258f56 Update main-de.json
lang: add missing fields to German translation
2021-01-22 06:22:22 -06:00
tmoldovan8x8
6a6aeb1d95 feat(mobile) adds more feature flags (#8450)
Features flags added:  
-tile-view.enabled
-filmstrip.enabled
-notifications.enabled
-toolbox.enabled
2021-01-22 12:03:39 +02:00
Дамян Минков
01c55bdb15 feat: Uses mod_external_services supporting urn:xmpp:extdisco:2. (#8455)
* feat: Uses mod_external_services supporting urn:xmpp:extdisco:2.

The old mod_turncredentials.lua is left to continue working for those using old installs.
New install will start using the new module which will no longer be needed with prosody 0.12.

https://hg.prosody.im/prosody-modules/file/4841cf3fded5/mod_external_services/mod_external_services.lua

* squash: Updates ljm to support urn:xmpp:extdisco:2.
2021-01-21 16:14:00 -06:00
bgrozev
5f891fd060 debian: Do not read jicofosecret. (#8454) 2021-01-21 13:19:39 -06:00
chipechop
a39905883f Update main-it.json
Added 4 missing lines in italian translation
2021-01-20 12:01:54 -06:00
Saúl Ibarra Corretgé
fe78f104bc feat(android) set compile/target SDK versions to 30 2021-01-20 15:14:09 +01:00
Saúl Ibarra Corretgé
9c13603489 feat(android) update native dependencies 2021-01-20 15:14:09 +01:00
tmoldovan8x8
61037b982b feat(mobile) adds ability to send and receive text messages (#8425) 2021-01-20 14:06:45 +02:00
Jaya Allamsetty
df21ec6f04 chore(deps) lib-jitsi-meet@latest (#8437)
https://github.com/jitsi/lib-jitsi-meet/compare/...94ac35ae818093896e639e74f5fc389b488206a0
2021-01-19 12:45:33 -06:00
Vlad Piersec
23574e9edc fix(vpaas): Store billing id in parent lolcaStorage on Safari 2021-01-18 09:56:03 +02:00
Dennis Scheiba
ec3130af0e make translation gender neutral 2021-01-16 21:56:22 -06:00
Filipe dos Santos Gundim
3b692dc502 fix join label in pt-br 2021-01-16 21:36:00 -06:00
Дамян Минков
6689aa3700 feat: Detects shard changed when using websockets.
* feat: Detects shard changed when using websockets. (#1462)

1009693f2e...cb484cf48c
2021-01-15 09:51:43 -06:00
Avram Tudor
13bc9863cb Merge pull request #8426 from jitsi/tavram/gradient-condition
fix(subject) remove gradient if no info in topbar
2021-01-15 16:26:19 +02:00
Tudor-Ovidiu Avram
7ff332b2bb fix(subject) remove gradient if no info in topbar 2021-01-15 16:02:50 +02:00
Mihai-Andrei Uscat
8aae2065dc fix(Toolbox): Fix toolbox display when accessing it via keyboard 2021-01-15 13:43:09 +02:00
Jaya Allamsetty
b65e61f633 feat: Add new codec selection mechanism.
When an endpoint that doesn't support the preferred codec (VP9) joins a conference, all the other endpoints fallback to VP8 until the endpoint leaves the call.
2021-01-14 18:01:38 -05:00
Saúl Ibarra Corretgé
88f1c218eb fix(rn,stats) fix incorrect bitrate calculation on mobile
Stats timestamps were incorrectly formatted, fixed upstream.

Fixes: https://github.com/jitsi/jitsi-meet/issues/8367
2021-01-14 14:59:22 +01:00
Boris Grozev
f6df76ab10 fix: Fix broken postinst reported by @wsldankers. 2021-01-14 07:55:50 -06:00
Saúl Ibarra Corretgé
85f1701393 fix(tile-view) avoid covering the logo
Reverts a8b2e6ffb3
2021-01-13 20:29:20 +01:00
damencho
2f7ff37472 fix: Fixes #8396, wrong ssi includes in offline static page. 2021-01-13 09:11:10 -06:00
Mihai-Andrei Uscat
c752ea13f1 feat(overflow): Add responsive drawer at small screen width.
* Implement opening toolbar and participant overflows as drawers when below certain width.
* Fix dial-in copy button displaying incorrectly.
2021-01-13 16:07:22 +01:00
tmoldovan8x8
5ef60c3a7d [WIP] adds BroadcastService (#8336)
feat(external_api) exposes more events from JS to native and adds the ability to send actions from native to JS.
2021-01-13 15:48:29 +02:00
hmuresan
1196ede961 feat(external-api) set privateMessage flag on incoming-message 2021-01-13 13:33:55 +01:00
Saúl Ibarra Corretgé
12877c7fce fix(settings) remove legacy compatibility code 2021-01-13 13:32:54 +01:00
Avram Tudor
c6bb600d4c Merge pull request #8400 from jitsi/tavram/shortcuts
feat(external_api) allow shortcuts to be disabled
2021-01-13 12:39:27 +02:00
Avram Tudor
845e23a947 Merge pull request #8399 from jitsi/tavram/overflowmenu
fix(menu) do not display overflow menu button if no items
2021-01-13 12:39:11 +02:00
Tudor-Ovidiu Avram
55ebb60f85 feat(external_api) allow shortcuts to be disabled 2021-01-13 12:10:27 +02:00
Tudor-Ovidiu Avram
8d3d94f568 fix(menu) do not display overflow menu button if no items 2021-01-13 11:55:38 +02:00
Avram Tudor
be24772e57 Merge pull request #8397 from jitsi/tavram/disable-jaas-directory
fix(jaas) disable directory integration
2021-01-13 11:38:05 +02:00
Tudor-Ovidiu Avram
a807f804a9 fix(jaas) disable directory integration 2021-01-13 11:13:04 +02:00
Hristo Terezov
db48dc3ed3 fix(Thumbnail): volume & audioLevel default values 2021-01-12 13:42:31 -06:00
Hristo Terezov
9bae7099dd fix(filmstrip): Import from base/tracks. 2021-01-12 13:42:31 -06:00
Hristo Terezov
e990f6984a fix(Thumbnail): Improve naming. 2021-01-12 13:42:31 -06:00
Hristo Terezov
9f321c988e style(isVideoPlayable): improve readability. 2021-01-12 13:42:31 -06:00
Hristo Terezov
2e5e9a3f79 fix(AudioTrack):Add check for NaN value for volume 2021-01-12 13:42:31 -06:00
Hristo Terezov
fdb8f76b90 fix(Thumbnail): imports. 2021-01-12 13:42:31 -06:00
Hristo Terezov
3d97bef308 style(Thumbnail): improve readability
Co-authored-by: Saúl Ibarra Corretgé <saghul@jitsi.org>
2021-01-12 13:42:31 -06:00
Hristo Terezov
5a55c7b965 style(AudioTrack): improve readability
Co-authored-by: Saúl Ibarra Corretgé <saghul@jitsi.org>
2021-01-12 13:42:31 -06:00
Hristo Terezov
e161cbc4bd fix(SmallVideo): computeDisplayModeInput
Co-authored-by: Saúl Ibarra Corretgé <saghul@jitsi.org>
2021-01-12 13:42:31 -06:00
Hristo Terezov
51e381a0b1 ref(Thumbnail): Create React component. 2021-01-12 13:42:31 -06:00
bgrozev
d8dd644f38 make sure extra plugin paths are enabled (#8390)
* fix: Make sure extra plugin_paths are not commented out.

* fix: Do not use "-e" as backup suffix.
2021-01-12 13:25:20 -06:00
Saúl Ibarra Corretgé
e30b2e14a5 fix(rn) stop room name generator when field is focused
Fixes: https://github.com/jitsi/jitsi-meet/issues/8307
2021-01-12 17:36:09 +01:00
Avram Tudor
7f1894dd57 Merge pull request #8379 from horymury/hmuresan/broadcast-screenshare
feat(external_api) add command and event listener for CS
2021-01-12 17:49:06 +02:00
hmuresan
4dda508708 feat(external_api) add command and event listener for CS 2021-01-12 17:23:40 +02:00
damencho
69c6463476 chore(deps) lib-jitsi-meet@latest
* fix: Disabling lobby when using tenant.

87c6e37475...7896fc8b92
2021-01-12 08:22:14 -06:00
Saúl Ibarra Corretgé
2763c2f5c9 fix(twa) update template
Set version to 1.0.0 with a very large version code so it's automatically kept
around when pushing new versions.

Additionally drop some no longer needed icon assets (bubblewrap did this).
2021-01-12 14:56:04 +01:00
Saúl Ibarra Corretgé
1ec8f70d55 fix(libre-build) skip spurious Firebase and GCM dependencies
Fixes: https://github.com/jitsi/jitsi-meet/issues/8353
2021-01-12 14:55:47 +01:00
Saúl Ibarra Corretgé
916208a5ff fix(libre-build) update react-native-device-info to 8.0.0
Will now work even if installreferrer or GCM are missing.
2021-01-12 14:55:47 +01:00
Mihai-Andrei Uscat
43e655b619 feat(chat): Improve responsiveness.
* Fix toolbox buttons not displaying properly when chat is open.
* Open chat in fullscreen dialog past custom thresholds when mobile/desktop toolbox would become unusable due to chat
* Remove mobile chat check when displaying toolbox
2021-01-12 15:24:55 +02:00
Avram Tudor
1ab0f1993a Merge pull request #8377 from jitsi/tavram/notifications
feat(external_api) allow notifications to be configured
2021-01-12 14:52:31 +02:00
Tudor-Ovidiu Avram
4cb7ebce70 feat(external_api) allow initial gUM requests to be disabled 2021-01-12 06:02:44 -06:00
hmuresan
0a5910f0b3 feat(external_api) set and cancel private chat through external API
- allow managing chat through API when chat button is not present on UI
2021-01-12 06:01:10 -06:00
Tudor-Ovidiu Avram
d91c546a1e feat(external_api) allow notifications to be configured 2021-01-12 11:22:53 +02:00
bgrozev
b6f7f8fba7 Remove the "focus" external component, use client_proxy instead. (#8381)
* feat: Add mod_client_proxy and mod_roster_command.

Taken from prosody-modules 4317:456b9f608fcf with the
mod_roster_command patch applied.

* feat: Use mod_client_proxy to proxy to jicofo.
2021-01-11 15:45:00 -06:00
Pawel Domas
6ebe2c2809 audio output selection in safari blocks the UI
It appears that at the time of this writing, creating audio tracks blocks
the browser's main thread for a long time on safari. Wasn't able to confirm
which part of track creation does the blocking exactly, but not creating
the tracks seems to help and makes the UI much more responsive.
2021-01-11 14:17:29 -05:00
Saygun ICYUZ
067610b3fd feat(recording) - Show recording started notification to the initiator (#8359)
* Show recording started notification to the initiator

* Translate 'recording.on' language key for English and Turkish
Translate 'liveStreaming.on' language key for English and Turkish
2021-01-11 08:21:33 -06:00
Avram Tudor
6f5534fcb6 Merge pull request #8352 from jitsi/tavram/allow-tileview-disabling
feat(jaas) allow tile view to be disabled
2021-01-08 16:03:21 +02:00
Tudor-Ovidiu Avram
dd8b220ff9 feat(jaas) allow tile view to be disabled 2021-01-08 12:00:13 +02:00
Avram Tudor
80d789879c Merge pull request #8356 from jitsi/tavram/top
feat(jaas) add config for displaying participants stats and conferenc…
2021-01-08 11:57:23 +02:00
Tudor-Ovidiu Avram
d49c5a6d8c feat(jaas) add config for displaying participants stats and conference subject 2021-01-08 10:21:07 +02:00
Mejans
9268255ca8 i18n: update Occitan language (#8346)
* Update main-oc.json

* Update languages-oc.json
2021-01-07 14:51:21 -06:00
Pawel Domas
a0806716ae fix(JitsiStreamPresenterEffect): frozen on Safari
Canvas rendering does not work as expected on Safari - the image stays
still on the first frame. Calling play() on the video tags seems to help.
2021-01-07 15:10:27 -05:00
Дамян Минков
3677a2f769 feat: Skip p2p when the participant is jigasi.
* feat: Skip p2p when the participant is jigasi.

1fd7256553...87c6e37475
2021-01-07 09:08:36 -06:00
Avram Tudor
3881da5db9 Merge pull request #8354 from jitsi/tavram/fix-filmstrip
fix(filmstrip) fix button not considering interface config settings
2021-01-07 15:20:22 +02:00
Tudor-Ovidiu Avram
35a586df3c fix(filmstrip) fix button not considering interface config settings 2021-01-07 14:53:11 +02:00
Saúl Ibarra Corretgé
dc5a776123 fix(ios) fix drag handle not rendering with latest react-native-svg
Fill must be properly specified.
2021-01-07 12:02:41 +01:00
Saúl Ibarra Corretgé
a3c6e690dd chore(deps) update react-native-svg to latest
Fixes icons not rendering on iOS 11.
2021-01-07 12:02:41 +01:00
Saúl Ibarra Corretgé
a1c197c73c fix(ios) fix crash on startup on iOS 11 2021-01-07 12:02:41 +01:00
damencho
e8c0c03e49 chore(deps) lib-jitsi-meet@latest
*  feat: Skips using disco-info for features. (#1450)
* sdp: improve sdp matching for simulcast lines (#1452)
* sdp: add missing colon to findLines calls (#1447)

310983c5b0...1fd7256553
2021-01-06 09:32:26 -06:00
Saúl Ibarra Corretgé
4798e0271b chore(android,ios) raise versions 2021-01-06 16:21:44 +01:00
Asif
cd29f10fa8 feat: emit raise hand event to external API (#8312)
* Expose raise hand event to external application

* Fix linting issues

* fix the app non existing issue
2021-01-06 08:49:10 -06:00
Pawel Domas
97dc07810c fix(setAudioOutputDeviceId): check if supported 2021-01-06 08:31:53 -06:00
damencho
28fa1f5dbe fix: Process pre-existing participants properties.
We were not processing properties which are set (fire properties updated) before the conference joined event is fired.
2021-01-05 14:29:34 -06:00
damencho
2ba6100e36 fix: Fixes showing phone icon for jigasi participants. 2021-01-05 14:29:34 -06:00
Shawn
060a8628ce fixed admin check for token verification 2021-01-05 12:56:33 -06:00
Christopher Engelhard
32fb08c56f Consistent formatting/indentation of files in ./doc (#8178)
* unify indentations (debian)

* unify indentations in example-config-files
2021-01-04 08:22:40 -06:00
Jakob Pfeiffer
4a3ff8ce2c fix(jitsi-meet-web-config.postinst) allow cert and key pre-selection (#8319)
* fix(jitsi-meet-web-config.postinst) allow cert and key pre-selection

* fix(jitsi-meet-web-config.postinst) jvb-hostname gets value from db_go instead of db_get

Co-authored-by: Jakob Pfeiffer <pgp-jkp@pfeiffer.ws>
2021-01-04 08:22:27 -06:00
yanglishuan
f32482539a fix(lang) update zhCN translation 2021-01-04 08:22:09 -06:00
53845714nF
f82088fb8f add systemd to letsencrypt installer (#8289)
* add systemd to letsencrypt

* Better readability of systemd change

Co-authored-by: Sebastian Feustel <sebastian.feustel@aei.mpg.de>
2021-01-04 08:21:47 -06:00
Vahid Zafari
76b4899c39 full support persian language (#8300) Fixes #8299 2020-12-23 08:29:07 -06:00
Marc Seitz
9b638a4052 fix(lang) update German translation 2020-12-23 11:07:10 +01:00
Saúl Ibarra Corretgé
a8b2e6ffb3 fix(tile-view) allow watermark to be covered 2020-12-23 11:05:30 +01:00
Saúl Ibarra Corretgé
aefd13ab1b fix(tile-view) reduce margins, take 2
Due to how the filmstrip size if computed I don't think there is a good way to
animate the change in size, so just ignore the toolbar, it will be hidden soon
enough.
2020-12-23 11:05:30 +01:00
Saúl Ibarra Corretgé
5e891caf94 fix(ios,fastlane) adjust scheme name after rename 2020-12-22 14:07:10 +01:00
Saúl Ibarra Corretgé
a01e3e9d8a fix(android) avoid crashes if view is null
This may happen due to API misuse, but also in complex applications where
activity lifetimes are not straightforward.
2020-12-22 13:53:39 +01:00
Saúl Ibarra Corretgé
687a6c31ee feat(analytics) unify Amplitude handlers across web and mobile
The amplitude-js library gained React Native support so there is no need to keep
separate implementations.
2020-12-22 10:36:10 +01:00
tmoldovan8x8
5ecb5717c7 feat(stats) add stats for mobile 2020-12-22 10:12:52 +01:00
Avram Tudor
8d813a499c Merge pull request #8293 from jitsi/tavram/update-jaas-rec
fix(jaas) update recording label and hide option for jaas users
2020-12-21 13:00:59 +02:00
Tudor-Ovidiu Avram
22384d9094 fix(jaas) update recording label and hide option for jaas users 2020-12-21 12:19:10 +02:00
eppesuig
b3f1f7f46e lang: Updating and uniforming italian translation (#8288)
* Updating and uniforming italian translation

- translate uniformly «meeting» to «conferenza», «chat» to «conversazione», ellipsys to «...», verbs in -ing with «in corso»
- correct a few typos
- update a message with old and unused placeholder
- translate some English messages

* typo

- add missing double quotes

* Fixed translation for "meeting" to "riunione"
2020-12-20 21:17:49 -06:00
xosecalvo
17350be16c Updated Galician translation
Updated original Weblate translation by https://github.com/meixome
2020-12-20 09:22:49 -06:00
Hristo Terezov
d4596889df feat(analytics): Adds metric for SS issues. 2020-12-18 15:27:43 -06:00
Mihai-Andrei Uscat
a5fe26bfdb fix(password): Fix add password button on Safari 2020-12-18 14:47:00 +02:00
Vlad Piersec
33e4324f6d fix(branding): Use config url for dynamic branding 2020-12-18 13:00:52 +01:00
Saúl Ibarra Corretgé
27d41604df fix(script) add commits list to update LJM message 2020-12-18 09:45:09 +01:00
Saúl Ibarra Corretgé
99ac60ed74 feat(ios) rename SDK target to JitsiMeetSDK
Swift has a longstanding bug where a framework and a type cannot be named the
same. We have somehow managed to not run into this, but it now seems to be
hitting us.

Since this is a breaking change, this starts the road for SDK 3.0.
2020-12-17 23:02:48 +01:00
Дамян Минков
4f52fd5e01 fix: Skip sending multiple times disco-info to jicofo.
* fix: Skip sending multiple times disco-info to jicofo.
* build(deps): bump ini from 1.3.5 to 1.3.7

9f65e8fab3...8bb653f1d6
2020-12-17 13:02:28 -06:00
bhlee
edf415a7da fix(welcome-page) fix .insecure-room-name-warning margin 2020-12-17 09:28:24 +01:00
bhlee
5637b37fd2 fix(main-ko) add keyboardShortcuts videoQuality (#8264)
* fix(main-ko.json) Update overall korean spelling & words

* fix(_welcome_page.css) update .insecure-room-name-warning_margin-top from 5px to 15px

* fix(_welcome_page.css) initialize .insecure-room-name-warning_margin-top from 15px to 5px

* fix(main-ko.json) add keyboardShortcuts videoQuality
2020-12-16 23:17:44 -06:00
bhlee
dc0c1f0d93 fix(main-ko.json) Update some korean spelling & words (#8253)
* fix(main-ko.json) Update overall korean spelling & words

* fix(_welcome_page.css) update .insecure-room-name-warning_margin-top from 5px to 15px

* fix(_welcome_page.css) initialize .insecure-room-name-warning_margin-top from 15px to 5px
2020-12-16 19:45:24 -06:00
597 changed files with 23954 additions and 9544 deletions

View File

@@ -5,6 +5,9 @@ build/*
# modify as little as possible.
flow-typed/*
libs/*
resources/*
react/features/stream-effects/virtual-background/vendor/*
load-test/*
# ESLint will by default ignore its own configuration file. However, there does
# not seem to be a reason why we will want to risk being inconsistent with our

View File

@@ -12,5 +12,6 @@ jobs:
with:
node-version: '12.x'
- run: npm install
- run: git status -s --untracked-files=no
- run: npm run lint
- run: make

View File

@@ -5,6 +5,8 @@ LIBJITSIMEET_DIR = node_modules/lib-jitsi-meet/
LIBFLAC_DIR = node_modules/libflacjs/dist/min/
OLM_DIR = node_modules/olm
RNNOISE_WASM_DIR = node_modules/rnnoise-wasm/dist/
TFLITE_WASM = react/features/stream-effects/virtual-background/vendor/tflite
MEET_MODELS_DIR = react/features/stream-effects/virtual-background/vendor/models/
NODE_SASS = ./node_modules/.bin/sass
NPM = npm
OUTPUT_DIR = .
@@ -16,14 +18,17 @@ WEBPACK_DEV_SERVER = ./node_modules/.bin/webpack-dev-server
all: compile deploy clean
compile:
compile: compile-load-test
$(WEBPACK) -p
compile-load-test:
${NPM} install --prefix resources/load-test && ${NPM} run build --prefix resources/load-test
clean:
rm -fr $(BUILD_DIR)
.NOTPARALLEL:
deploy: deploy-init deploy-appbundle deploy-rnnoise-binary deploy-lib-jitsi-meet deploy-libflac deploy-olm deploy-css deploy-local
deploy: deploy-init deploy-appbundle deploy-rnnoise-binary deploy-tflite deploy-meet-models deploy-lib-jitsi-meet deploy-libflac deploy-olm deploy-css deploy-local
deploy-init:
rm -fr $(DEPLOY_DIR)
@@ -39,8 +44,6 @@ deploy-appbundle:
$(BUILD_DIR)/external_api.min.map \
$(BUILD_DIR)/flacEncodeWorker.min.js \
$(BUILD_DIR)/flacEncodeWorker.min.map \
$(BUILD_DIR)/device_selection_popup_bundle.min.js \
$(BUILD_DIR)/device_selection_popup_bundle.min.map \
$(BUILD_DIR)/dial_in_info_bundle.min.js \
$(BUILD_DIR)/dial_in_info_bundle.min.map \
$(BUILD_DIR)/alwaysontop.min.js \
@@ -48,10 +51,6 @@ deploy-appbundle:
$(OUTPUT_DIR)/analytics-ga.js \
$(BUILD_DIR)/analytics-ga.min.js \
$(BUILD_DIR)/analytics-ga.min.map \
$(BUILD_DIR)/video-blur-effect.min.js \
$(BUILD_DIR)/video-blur-effect.min.map \
$(BUILD_DIR)/rnnoise-processor.min.js \
$(BUILD_DIR)/rnnoise-processor.min.map \
$(BUILD_DIR)/close3.min.js \
$(BUILD_DIR)/close3.min.map \
$(DEPLOY_DIR)
@@ -81,6 +80,16 @@ deploy-rnnoise-binary:
$(RNNOISE_WASM_DIR)/rnnoise.wasm \
$(DEPLOY_DIR)
deploy-tflite:
cp \
$(TFLITE_WASM)/*.wasm \
$(DEPLOY_DIR)
deploy-meet-models:
cp \
$(MEET_MODELS_DIR)/*.tflite \
$(DEPLOY_DIR)
deploy-css:
$(NODE_SASS) $(STYLES_MAIN) $(STYLES_BUNDLE) && \
$(CLEANCSS) --skip-rebase $(STYLES_BUNDLE) > $(STYLES_DESTINATION) ; \
@@ -90,7 +99,7 @@ deploy-local:
([ ! -x deploy-local.sh ] || ./deploy-local.sh)
.NOTPARALLEL:
dev: deploy-init deploy-css deploy-rnnoise-binary deploy-lib-jitsi-meet deploy-libflac deploy-olm
dev: deploy-init deploy-css deploy-rnnoise-binary deploy-tflite deploy-meet-models deploy-lib-jitsi-meet deploy-libflac deploy-olm
$(WEBPACK_DEV_SERVER) --detect-circular-deps
source-package:

View File

@@ -6,6 +6,8 @@ The Jitsi Meet client runs in your browser, without installing anything else on
Jitsi Meet allows very efficient collaboration. Users can stream their desktop or only some windows. It also supports shared document editing with Etherpad.
**NOTE:** If you are looking for Jitsi as a Service (JaaS) please start [here](https://jaas.8x8.vc).
## Installation
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.

View File

@@ -122,7 +122,7 @@ gradle.projectsEvaluated {
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
output.getProcessManifestProvider().get().doLast {
def outputDir = manifestOutputDirectory.get().asFile
def outputDir = multiApkManifestOutputDirectory.get().asFile
def manifestPath = new File(outputDir, 'AndroidManifest.xml')
def charset = 'UTF-8'
def text

View File

@@ -38,7 +38,7 @@ import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.Map;
import java.util.HashMap;
/**
* The one and only Activity that the Jitsi Meet app needs. The
@@ -183,8 +183,8 @@ public class MainActivity extends JitsiMeetActivity {
}
@Override
public void onConferenceTerminated(Map<String, Object> data) {
Log.d(TAG, "Conference terminated: " + data);
protected void onConferenceTerminated(HashMap<String, Object> extraData) {
Log.d(TAG, "Conference terminated: " + extraData);
}
// Activity lifecycle method overrides

View File

@@ -10,17 +10,17 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.2'
classpath 'com.google.gms:google-services:4.3.3'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.3.0'
classpath 'com.android.tools.build:gradle:4.1.2'
classpath 'com.google.gms:google-services:4.3.4'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.4.1'
}
}
ext {
buildToolsVersion = "29.0.3"
compileSdkVersion = 29
buildToolsVersion = "30.0.3"
compileSdkVersion = 30
minSdkVersion = 23
targetSdkVersion = 29
targetSdkVersion = 30
supportLibVersion = "28.0.0"
// The Maven artifact groupdId of the third-party react-native modules which

View File

@@ -25,5 +25,5 @@ android.enableDexingArtifactTransform.desugaring=false
android.useAndroidX=true
android.enableJetifier=true
appVersion=20.6.0
sdkVersion=2.12.0
appVersion=21.0.0
sdkVersion=3.2.0

View File

@@ -25,10 +25,6 @@ android {
sourceSets {
main {
java {
if (rootProject.ext.libreBuild) {
srcDir "src"
exclude "**/AmplitudeModule.java"
}
exclude "test/"
}
}
@@ -40,6 +36,7 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.fragment:fragment:1.2.5'
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
//noinspection GradleDynamicVersion
@@ -50,18 +47,25 @@ dependencies {
implementation 'com.dropbox.core:dropbox-core-sdk:3.0.8'
implementation 'com.jakewharton.timber:timber:4.7.1'
implementation 'com.squareup.duktape:duktape-android:1.3.0'
implementation 'com.google.code.gson:gson:2.8.6'
if (!rootProject.ext.libreBuild) {
implementation 'com.amplitude:android-sdk:2.14.1'
if (rootProject.ext.libreBuild) {
implementation(project(':react-native-device-info')) {
exclude group: 'com.google.firebase'
exclude group: 'com.google.android.gms'
exclude group: 'com.android.installreferrer'
}
} else {
implementation project(':react-native-device-info')
implementation(project(":react-native-google-signin")) {
exclude group: 'com.google.android.gms'
exclude group: 'androidx'
}
}
implementation project(':react-native-async-storage')
implementation project(':react-native-background-timer')
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')

View File

@@ -1,122 +0,0 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jitsi.meet.sdk;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.provider.Settings;
import android.text.TextUtils;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.amplitude.api.Amplitude;
import com.facebook.react.module.annotations.ReactModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Implements the react-native module for the Amplitude integration.
*/
@ReactModule(name = AmplitudeModule.NAME)
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);
}
/**
* Initializes the Amplitude SDK.
*
* @param instanceName The name of the Amplitude instance. Should
* be used only for multi-project logging.
* @param apiKey The API_KEY of the Amplitude project.
*/
@ReactMethod
@SuppressLint("HardwareIds")
public void init(String instanceName, String apiKey) {
Amplitude.getInstance(instanceName).initialize(getCurrentActivity(), apiKey);
// Set the device ID to something consistent.
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();
}
}
/**
* Sets the user ID for an Amplitude instance.
*
* @param instanceName The name of the Amplitude instance.
* @param userId The new value for the user ID.
*/
@ReactMethod
public void setUserId(String instanceName, String userId) {
Amplitude.getInstance(instanceName).setUserId(userId);
}
/**
* Sets the user properties for an Amplitude instance.
*
* @param instanceName The name of the Amplitude instance.
* @param userProps JSON string with user properties to be set.
*/
@ReactMethod
public void setUserProperties(String instanceName, ReadableMap userProps) {
if (userProps != null) {
Amplitude.getInstance(instanceName).setUserProperties(
new JSONObject(userProps.toHashMap()));
}
}
/**
* Log an analytics event.
*
* @param instanceName The name of the Amplitude instance.
* @param eventType The event type.
* @param eventPropsString JSON string with the event properties.
*/
@ReactMethod
public void logEvent(String instanceName, String eventType, String eventPropsString) {
try {
JSONObject eventProps = new JSONObject(eventPropsString);
Amplitude.getInstance(instanceName).logEvent(eventType, eventProps);
} catch (JSONException e) {
JitsiMeetLogger.e(e, "Error logging event");
}
}
@Override
public String getName() {
return NAME;
}
}

View File

@@ -99,6 +99,7 @@ public abstract class BaseReactView<ListenerT>
* The listener (e.g. {@link JitsiMeetViewListener}) instance for reporting
* events occurring in Jitsi Meet.
*/
@Deprecated
private ListenerT listener;
/**
@@ -167,6 +168,7 @@ public abstract class BaseReactView<ListenerT>
*
* @return The listener set on this {@code BaseReactView}.
*/
@Deprecated
public ListenerT getListener() {
return listener;
}
@@ -179,8 +181,10 @@ public abstract class BaseReactView<ListenerT>
* @param data - The details of the event associated with/specific to the
* specified {@code name}.
*/
@Deprecated
protected abstract void onExternalAPIEvent(String name, ReadableMap data);
@Deprecated
protected void onExternalAPIEvent(
Map<String, Method> listenerMethods,
String name, ReadableMap data) {
@@ -215,6 +219,7 @@ public abstract class BaseReactView<ListenerT>
*
* @param listener The listener to set on this {@code BaseReactView}.
*/
@Deprecated
public void setListener(ListenerT listener) {
this.listener = listener;
}

View File

@@ -0,0 +1,90 @@
package org.jitsi.meet.sdk;
import android.content.Intent;
import android.os.Bundle;
import com.facebook.react.bridge.WritableNativeMap;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.HashMap;
/**
* Wraps the name and extra data for events that were broadcasted locally.
*/
public class BroadcastAction {
private static final String TAG = BroadcastAction.class.getSimpleName();
private final Type type;
private final HashMap<String, Object> data;
public BroadcastAction(Intent intent) {
this.type = Type.buildTypeFromAction(intent.getAction());
this.data = buildDataFromBundle(intent.getExtras());
}
public Type getType() {
return this.type;
}
public HashMap<String, Object> getData() {
return this.data;
}
public WritableNativeMap getDataAsWritableNativeMap() {
WritableNativeMap nativeMap = new WritableNativeMap();
for (String key : this.data.keySet()) {
try {
// TODO add support for different types of objects
nativeMap.putString(key, this.data.get(key).toString());
} catch (Exception e) {
JitsiMeetLogger.w(TAG + " invalid extra data in event", e);
}
}
return nativeMap;
}
private static HashMap<String, Object> buildDataFromBundle(Bundle bundle) {
HashMap<String, Object> map = new HashMap<>();
if (bundle != null) {
for (String key : bundle.keySet()) {
map.put(key, bundle.get(key));
}
}
return map;
}
enum Type {
SET_AUDIO_MUTED("org.jitsi.meet.SET_AUDIO_MUTED"),
HANG_UP("org.jitsi.meet.HANG_UP"),
SEND_ENDPOINT_TEXT_MESSAGE("org.jitsi.meet.SEND_ENDPOINT_TEXT_MESSAGE"),
TOGGLE_SCREEN_SHARE("org.jitsi.meet.TOGGLE_SCREEN_SHARE"),
RETRIEVE_PARTICIPANTS_INFO("org.jitsi.meet.RETRIEVE_PARTICIPANTS_INFO"),
OPEN_CHAT("org.jitsi.meet.OPEN_CHAT"),
CLOSE_CHAT("org.jitsi.meet.CLOSE_CHAT"),
SEND_CHAT_MESSAGE("org.jitsi.meet.SEND_CHAT_MESSAGE");
private final String action;
Type(String action) {
this.action = action;
}
public String getAction() {
return action;
}
private static Type buildTypeFromAction(String action) {
for (Type type : Type.values()) {
if (type.action.equalsIgnoreCase(action)) {
return type;
}
}
return null;
}
}
}

View File

@@ -0,0 +1,30 @@
package org.jitsi.meet.sdk;
import android.content.Context;
import android.content.Intent;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.facebook.react.bridge.ReadableMap;
/**
* Class used to emit events through the LocalBroadcastManager, called when events
* from JS occurred. Takes an action name from JS, builds and broadcasts the {@link BroadcastEvent}
*/
public class BroadcastEmitter {
private final LocalBroadcastManager localBroadcastManager;
public BroadcastEmitter(Context context) {
localBroadcastManager = LocalBroadcastManager.getInstance(context);
}
public void sendBroadcast(String name, ReadableMap data) {
BroadcastEvent event = new BroadcastEvent(name, data);
Intent intent = event.buildIntent();
if (intent != null) {
localBroadcastManager.sendBroadcast(intent);
}
}
}

View File

@@ -0,0 +1,150 @@
package org.jitsi.meet.sdk;
import android.content.Intent;
import android.os.Bundle;
import com.facebook.react.bridge.ReadableMap;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.HashMap;
/**
* Wraps the name and extra data for the events that occur on the JS side and are
* to be broadcasted.
*/
public class BroadcastEvent {
private static final String TAG = BroadcastEvent.class.getSimpleName();
private final Type type;
private final HashMap<String, Object> data;
public BroadcastEvent(String name, ReadableMap data) {
this.type = Type.buildTypeFromName(name);
this.data = data.toHashMap();
}
public BroadcastEvent(Intent intent) {
this.type = Type.buildTypeFromAction(intent.getAction());
this.data = buildDataFromBundle(intent.getExtras());
}
public Type getType() {
return this.type;
}
public HashMap<String, Object> getData() {
return this.data;
}
public Intent buildIntent() {
if (type != null && type.action != null) {
Intent intent = new Intent(type.action);
for (String key : this.data.keySet()) {
try {
intent.putExtra(key, this.data.get(key).toString());
} catch (Exception e) {
JitsiMeetLogger.w(TAG + " invalid extra data in event", e);
}
}
return intent;
}
return null;
}
private static HashMap<String, Object> buildDataFromBundle(Bundle bundle) {
if (bundle != null) {
try {
HashMap<String, Object> map = new HashMap<>();
for (String key : bundle.keySet()) {
map.put(key, bundle.get(key));
}
return map;
} catch (Exception e) {
JitsiMeetLogger.w(TAG + " invalid extra data", e);
}
}
return null;
}
public enum Type {
CONFERENCE_JOINED("org.jitsi.meet.CONFERENCE_JOINED"),
CONFERENCE_TERMINATED("org.jitsi.meet.CONFERENCE_TERMINATED"),
CONFERENCE_WILL_JOIN("org.jitsi.meet.CONFERENCE_WILL_JOIN"),
AUDIO_MUTED_CHANGED("org.jitsi.meet.AUDIO_MUTED_CHANGED"),
PARTICIPANT_JOINED("org.jitsi.meet.PARTICIPANT_JOINED"),
PARTICIPANT_LEFT("org.jitsi.meet.PARTICIPANT_LEFT"),
ENDPOINT_TEXT_MESSAGE_RECEIVED("org.jitsi.meet.ENDPOINT_TEXT_MESSAGE_RECEIVED"),
SCREEN_SHARE_TOGGLED("org.jitsi.meet.SCREEN_SHARE_TOGGLED"),
PARTICIPANTS_INFO_RETRIEVED("org.jitsi.meet.PARTICIPANTS_INFO_RETRIEVED"),
CHAT_MESSAGE_RECEIVED("org.jitsi.meet.CHAT_MESSAGE_RECEIVED"),
CHAT_TOGGLED("org.jitsi.meet.CHAT_TOGGLED");
private static final String CONFERENCE_WILL_JOIN_NAME = "CONFERENCE_WILL_JOIN";
private static final String CONFERENCE_JOINED_NAME = "CONFERENCE_JOINED";
private static final String CONFERENCE_TERMINATED_NAME = "CONFERENCE_TERMINATED";
private static final String AUDIO_MUTED_CHANGED_NAME = "AUDIO_MUTED_CHANGED";
private static final String PARTICIPANT_JOINED_NAME = "PARTICIPANT_JOINED";
private static final String PARTICIPANT_LEFT_NAME = "PARTICIPANT_LEFT";
private static final String ENDPOINT_TEXT_MESSAGE_RECEIVED_NAME = "ENDPOINT_TEXT_MESSAGE_RECEIVED";
private static final String SCREEN_SHARE_TOGGLED_NAME = "SCREEN_SHARE_TOGGLED";
private static final String PARTICIPANTS_INFO_RETRIEVED_NAME = "PARTICIPANTS_INFO_RETRIEVED";
private static final String CHAT_MESSAGE_RECEIVED_NAME = "CHAT_MESSAGE_RECEIVED";
private static final String CHAT_TOGGLED_NAME = "CHAT_TOGGLED";
private final String action;
Type(String action) {
this.action = action;
}
public String getAction() {
return action;
}
private static Type buildTypeFromAction(String action) {
for (Type type : Type.values()) {
if (type.action.equalsIgnoreCase(action)) {
return type;
}
}
return null;
}
private static Type buildTypeFromName(String name) {
switch (name) {
case CONFERENCE_WILL_JOIN_NAME:
return CONFERENCE_WILL_JOIN;
case CONFERENCE_JOINED_NAME:
return CONFERENCE_JOINED;
case CONFERENCE_TERMINATED_NAME:
return CONFERENCE_TERMINATED;
case AUDIO_MUTED_CHANGED_NAME:
return AUDIO_MUTED_CHANGED;
case PARTICIPANT_JOINED_NAME:
return PARTICIPANT_JOINED;
case PARTICIPANT_LEFT_NAME:
return PARTICIPANT_LEFT;
case ENDPOINT_TEXT_MESSAGE_RECEIVED_NAME:
return ENDPOINT_TEXT_MESSAGE_RECEIVED;
case SCREEN_SHARE_TOGGLED_NAME:
return SCREEN_SHARE_TOGGLED;
case PARTICIPANTS_INFO_RETRIEVED_NAME:
return PARTICIPANTS_INFO_RETRIEVED;
case CHAT_MESSAGE_RECEIVED_NAME:
return CHAT_MESSAGE_RECEIVED;
case CHAT_TOGGLED_NAME:
return CHAT_TOGGLED;
}
return null;
}
}
}

View File

@@ -0,0 +1,43 @@
package org.jitsi.meet.sdk;
import android.content.Intent;
public class BroadcastIntentHelper {
public static Intent buildSetAudioMutedIntent(boolean muted) {
Intent intent = new Intent(BroadcastAction.Type.SET_AUDIO_MUTED.getAction());
intent.putExtra("muted", muted);
return intent;
}
public static Intent buildHangUpIntent() {
return new Intent(BroadcastAction.Type.HANG_UP.getAction());
}
public static Intent buildSendEndpointTextMessageIntent(String to, String message) {
Intent intent = new Intent(BroadcastAction.Type.SEND_ENDPOINT_TEXT_MESSAGE.getAction());
intent.putExtra("to", to);
intent.putExtra("message", message);
return intent;
}
public static Intent buildToggleScreenShareIntent() {
return new Intent(BroadcastAction.Type.TOGGLE_SCREEN_SHARE.getAction());
}
public static Intent buildOpenChatIntent(String participantId) {
Intent intent = new Intent(BroadcastAction.Type.OPEN_CHAT.getAction());
intent.putExtra("to", participantId);
return intent;
}
public static Intent buildCloseChatIntent() {
return new Intent(BroadcastAction.Type.CLOSE_CHAT.getAction());
}
public static Intent buildSendChatMessageIntent(String participantId, String message) {
Intent intent = new Intent(BroadcastAction.Type.SEND_CHAT_MESSAGE.getAction());
intent.putExtra("to", participantId);
intent.putExtra("message", message);
return intent;
}
}

View File

@@ -0,0 +1,34 @@
package org.jitsi.meet.sdk;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
/**
* Listens for {@link BroadcastAction}s on LocalBroadcastManager. When one occurs,
* it emits it to JS.
*/
public class BroadcastReceiver extends android.content.BroadcastReceiver {
public BroadcastReceiver(Context context) {
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context);
IntentFilter intentFilter = new IntentFilter();
for (BroadcastAction.Type type : BroadcastAction.Type.values()) {
intentFilter.addAction(type.getAction());
}
localBroadcastManager.registerReceiver(this, intentFilter);
}
@Override
public void onReceive(Context context, Intent intent) {
BroadcastAction action = new BroadcastAction(intent);
String actionName = action.getType().getAction();
ReactInstanceManagerHolder.emitEvent(actionName, action.getDataAsWritableNativeMap());
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright @ 2017-present Atlassian Pty Ltd
* Copyright @ 2017-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +24,9 @@ import com.facebook.react.module.annotations.ReactModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.HashMap;
import java.util.Map;
/**
* Module implementing an API for sending events from JavaScript to native code.
*/
@@ -35,6 +38,9 @@ class ExternalAPIModule
private static final String TAG = NAME;
private final BroadcastEmitter broadcastEmitter;
private final BroadcastReceiver broadcastReceiver;
/**
* Initializes a new module instance. There shall be a single instance of
* this module throughout the lifetime of the app.
@@ -44,6 +50,11 @@ class ExternalAPIModule
*/
public ExternalAPIModule(ReactApplicationContext reactContext) {
super(reactContext);
broadcastEmitter = new BroadcastEmitter(reactContext);
broadcastReceiver = new BroadcastReceiver(reactContext);
ParticipantsService.init(reactContext);
}
/**
@@ -56,6 +67,28 @@ class ExternalAPIModule
return NAME;
}
/**
* Gets a mapping with the constants this module is exporting.
*
* @return a {@link Map} mapping the constants to be exported with their
* values.
*/
@Override
public Map<String, Object> getConstants() {
Map<String, Object> constants = new HashMap<>();
constants.put("SET_AUDIO_MUTED", BroadcastAction.Type.SET_AUDIO_MUTED.getAction());
constants.put("HANG_UP", BroadcastAction.Type.HANG_UP.getAction());
constants.put("SEND_ENDPOINT_TEXT_MESSAGE", BroadcastAction.Type.SEND_ENDPOINT_TEXT_MESSAGE.getAction());
constants.put("TOGGLE_SCREEN_SHARE", BroadcastAction.Type.TOGGLE_SCREEN_SHARE.getAction());
constants.put("RETRIEVE_PARTICIPANTS_INFO", BroadcastAction.Type.RETRIEVE_PARTICIPANTS_INFO.getAction());
constants.put("OPEN_CHAT", BroadcastAction.Type.OPEN_CHAT.getAction());
constants.put("CLOSE_CHAT", BroadcastAction.Type.CLOSE_CHAT.getAction());
constants.put("SEND_CHAT_MESSAGE", BroadcastAction.Type.SEND_CHAT_MESSAGE.getAction());
return constants;
}
/**
* Dispatches an event that occurred on the JavaScript side of the SDK to
* the specified {@link BaseReactView}'s listener.
@@ -79,7 +112,8 @@ class ExternalAPIModule
JitsiMeetLogger.d(TAG + " Sending event: " + name + " with data: " + data);
try {
view.onExternalAPIEvent(name, data);
} catch(Exception e) {
broadcastEmitter.sendBroadcast(name, data);
} catch (Exception e) {
JitsiMeetLogger.e(e, TAG + " onExternalAPIEvent: error sending event");
}
}

View File

@@ -16,33 +16,41 @@
package org.jitsi.meet.sdk;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.facebook.react.modules.core.PermissionListener;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.Map;
import java.util.HashMap;
/**
* A base activity for SDK users to embed. It uses {@link JitsiMeetFragment} to do the heavy
* lifting and wires the remaining Activity lifecycle methods so it works out of the box.
*/
public class JitsiMeetActivity extends FragmentActivity
implements JitsiMeetActivityInterface, JitsiMeetViewListener {
implements JitsiMeetActivityInterface {
protected static final String TAG = JitsiMeetActivity.class.getSimpleName();
private static final String ACTION_JITSI_MEET_CONFERENCE = "org.jitsi.meet.CONFERENCE";
private static final String JITSI_MEET_CONFERENCE_OPTIONS = "JitsiMeetConferenceOptions";
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
onBroadcastReceived(intent);
}
};
// Helpers for starting the activity
//
@@ -68,8 +76,7 @@ public class JitsiMeetActivity extends FragmentActivity
setContentView(R.layout.activity_jitsi_meet);
// Listen for conference events.
getJitsiView().setListener(this);
registerForBroadcastMessages();
if (!extraInitialize()) {
initialize();
@@ -91,6 +98,8 @@ public class JitsiMeetActivity extends FragmentActivity
}
JitsiMeetOngoingConferenceService.abort(this);
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
super.onDestroy();
}
@@ -107,26 +116,39 @@ public class JitsiMeetActivity extends FragmentActivity
protected JitsiMeetView getJitsiView() {
JitsiMeetFragment fragment
= (JitsiMeetFragment) getSupportFragmentManager().findFragmentById(R.id.jitsiFragment);
return fragment.getJitsiView();
return fragment != null ? fragment.getJitsiView() : null;
}
public void join(@Nullable String url) {
JitsiMeetConferenceOptions options
= new JitsiMeetConferenceOptions.Builder()
.setRoom(url)
.build();
.setRoom(url)
.build();
join(options);
}
public void join(JitsiMeetConferenceOptions options) {
getJitsiView().join(options);
JitsiMeetView view = getJitsiView();
if (view != null) {
view.join(options);
} else {
JitsiMeetLogger.w("Cannot join, view is null");
}
}
public void leave() {
getJitsiView().leave();
JitsiMeetView view = getJitsiView();
if (view != null) {
view.leave();
} else {
JitsiMeetLogger.w("Cannot leave, view is null");
}
}
private @Nullable JitsiMeetConferenceOptions getConferenceOptions(Intent intent) {
private @Nullable
JitsiMeetConferenceOptions getConferenceOptions(Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_VIEW.equals(action)) {
@@ -145,7 +167,7 @@ public class JitsiMeetActivity extends FragmentActivity
* Helper function called during activity initialization. If {@code true} is returned, the
* initialization is delayed and the {@link JitsiMeetActivity#initialize()} method is not
* called. In this case, it's up to the subclass to call the initialize method when ready.
*
* <p>
* This is mainly required so we do some extra initialization in the Jitsi Meet app.
*
* @return {@code true} if the initialization will be delayed, {@code false} otherwise.
@@ -160,6 +182,37 @@ public class JitsiMeetActivity extends FragmentActivity
join(getConferenceOptions(getIntent()));
}
protected void onConferenceJoined(HashMap<String, Object> extraData) {
JitsiMeetLogger.i("Conference joined: " + extraData);
// Launch the service for the ongoing notification.
JitsiMeetOngoingConferenceService.launch(this);
}
protected void onConferenceTerminated(HashMap<String, Object> extraData) {
JitsiMeetLogger.i("Conference terminated: " + extraData);
finish();
}
protected void onConferenceWillJoin(HashMap<String, Object> extraData) {
JitsiMeetLogger.i("Conference will join: " + extraData);
}
protected void onParticipantJoined(HashMap<String, Object> extraData) {
try {
JitsiMeetLogger.i("Participant joined: ", extraData);
} catch (Exception e) {
JitsiMeetLogger.w("Invalid participant joined extraData", e);
}
}
protected void onParticipantLeft(HashMap<String, Object> extraData) {
try {
JitsiMeetLogger.i("Participant left: ", extraData);
} catch (Exception e) {
JitsiMeetLogger.w("Invalid participant left extraData", e);
}
}
// Activity lifecycle methods
//
@@ -191,7 +244,11 @@ public class JitsiMeetActivity extends FragmentActivity
@Override
protected void onUserLeaveHint() {
getJitsiView().enterPictureInPicture();
JitsiMeetView view = getJitsiView();
if (view != null) {
view.enterPictureInPicture();
}
}
// JitsiMeetActivityInterface
@@ -207,24 +264,37 @@ public class JitsiMeetActivity extends FragmentActivity
JitsiMeetActivityDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
// JitsiMeetViewListener
//
private void registerForBroadcastMessages() {
IntentFilter intentFilter = new IntentFilter();
@Override
public void onConferenceJoined(Map<String, Object> data) {
JitsiMeetLogger.i("Conference joined: " + data);
// Launch the service for the ongoing notification.
JitsiMeetOngoingConferenceService.launch(this);
for (BroadcastEvent.Type type : BroadcastEvent.Type.values()) {
intentFilter.addAction(type.getAction());
}
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, intentFilter);
}
@Override
public void onConferenceTerminated(Map<String, Object> data) {
JitsiMeetLogger.i("Conference terminated: " + data);
finish();
}
private void onBroadcastReceived(Intent intent) {
if (intent != null) {
BroadcastEvent event = new BroadcastEvent(intent);
@Override
public void onConferenceWillJoin(Map<String, Object> data) {
JitsiMeetLogger.i("Conference will join: " + data);
switch (event.getType()) {
case CONFERENCE_JOINED:
onConferenceJoined(event.getData());
break;
case CONFERENCE_WILL_JOIN:
onConferenceWillJoin(event.getData());
break;
case CONFERENCE_TERMINATED:
onConferenceTerminated(event.getData());
break;
case PARTICIPANT_JOINED:
onParticipantJoined(event.getData());
break;
case PARTICIPANT_LEFT:
onParticipantLeft(event.getData());
break;
}
}
}
}

View File

@@ -21,11 +21,13 @@ import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.IBinder;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
/**
* This class implements an Android {@link Service}, a foreground one specifically, and it's
@@ -35,19 +37,18 @@ import org.jitsi.meet.sdk.log.JitsiMeetLogger;
* See: https://developer.android.com/guide/components/services
*/
public class JitsiMeetOngoingConferenceService extends Service
implements OngoingConferenceTracker.OngoingConferenceListener {
implements OngoingConferenceTracker.OngoingConferenceListener {
private static final String TAG = JitsiMeetOngoingConferenceService.class.getSimpleName();
static final class Actions {
static final String START = TAG + ":START";
static final String HANGUP = TAG + ":HANGUP";
}
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver();
private boolean isAudioMuted;
static void launch(Context context) {
OngoingNotification.createOngoingConferenceNotificationChannel();
Intent intent = new Intent(context, JitsiMeetOngoingConferenceService.class);
intent.setAction(Actions.START);
intent.setAction(Action.START.getName());
ComponentName componentName;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
@@ -70,11 +71,16 @@ public class JitsiMeetOngoingConferenceService extends Service
super.onCreate();
OngoingConferenceTracker.getInstance().addListener(this);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BroadcastEvent.Type.AUDIO_MUTED_CHANGED.getAction());
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(broadcastReceiver, intentFilter);
}
@Override
public void onDestroy() {
OngoingConferenceTracker.getInstance().removeListener(this);
LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(broadcastReceiver);
super.onDestroy();
}
@@ -86,26 +92,37 @@ public class JitsiMeetOngoingConferenceService extends Service
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
final String action = intent.getAction();
if (Actions.START.equals(action)) {
Notification notification = OngoingNotification.buildOngoingConferenceNotification();
if (notification == null) {
final String actionName = intent.getAction();
final Action action = Action.fromName(actionName);
switch (action) {
case UNMUTE:
case MUTE:
Intent muteBroadcastIntent = BroadcastIntentHelper.buildSetAudioMutedIntent(action == Action.MUTE);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(muteBroadcastIntent);
break;
case START:
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted);
if (notification == null) {
stopSelf();
JitsiMeetLogger.w(TAG + " Couldn't start service, notification is null");
} else {
startForeground(OngoingNotification.NOTIFICATION_ID, notification);
JitsiMeetLogger.i(TAG + " Service started");
}
break;
case HANGUP:
JitsiMeetLogger.i(TAG + " Hangup requested");
Intent hangupBroadcastIntent = BroadcastIntentHelper.buildHangUpIntent();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(hangupBroadcastIntent);
stopSelf();
JitsiMeetLogger.w(TAG + " Couldn't start service, notification is null");
} else {
startForeground(OngoingNotification.NOTIFICATION_ID, notification);
JitsiMeetLogger.i(TAG + " Service started");
}
} else if (Actions.HANGUP.equals(action)) {
JitsiMeetLogger.i(TAG + " Hangup requested");
// Abort all ongoing calls
if (AudioModeModule.useConnectionService()) {
ConnectionService.abortConnections();
}
stopSelf();
} else {
JitsiMeetLogger.w(TAG + " Unknown action received: " + action);
stopSelf();
break;
default:
JitsiMeetLogger.w(TAG + " Unknown action received: " + action);
stopSelf();
break;
}
return START_NOT_STICKY;
@@ -115,7 +132,50 @@ public class JitsiMeetOngoingConferenceService extends Service
public void onCurrentConferenceChanged(String conferenceUrl) {
if (conferenceUrl == null) {
stopSelf();
OngoingNotification.resetStartingtime();
JitsiMeetLogger.i(TAG + "Service stopped");
}
}
public enum Action {
START(TAG + ":START"),
HANGUP(TAG + ":HANGUP"),
MUTE(TAG + ":MUTE"),
UNMUTE(TAG + ":UNMUTE");
private final String name;
Action(String name) {
this.name = name;
}
public static Action fromName(String name) {
for (Action action : Action.values()) {
if (action.name.equalsIgnoreCase(name)) {
return action;
}
}
return null;
}
public String getName() {
return name;
}
}
private class BroadcastReceiver extends android.content.BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
isAudioMuted = Boolean.parseBoolean(intent.getStringExtra("muted"));
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted);
if (notification == null) {
stopSelf();
JitsiMeetLogger.w(TAG + " Couldn't start service, notification is null");
} else {
startForeground(OngoingNotification.NOTIFICATION_ID, notification);
JitsiMeetLogger.i(TAG + " Service started");
}
}
}
}

View File

@@ -197,6 +197,7 @@ public class JitsiMeetView extends BaseReactView<JitsiMeetViewListener>
* by/associated with the specified {@code name}.
*/
@Override
@Deprecated
protected void onExternalAPIEvent(String name, ReadableMap data) {
onExternalAPIEvent(LISTENER_METHODS, name, data);
}

View File

@@ -21,6 +21,7 @@ import java.util.Map;
/**
* Interface for listening to events coming from Jitsi Meet.
*/
@Deprecated
public interface JitsiMeetViewListener {
/**
* Called when a conference was joined.

View File

@@ -32,6 +32,7 @@ import java.util.regex.Pattern;
* Utility methods for helping with transforming {@link ExternalAPIModule}
* events into listener methods. Used with descendants of {@link BaseReactView}.
*/
@Deprecated
public final class ListenerUtils {
/**
* Extracts the methods defined in a listener and creates a mapping of this

View File

@@ -23,13 +23,14 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import androidx.annotation.StringRes;
import androidx.core.app.NotificationCompat;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.Random;
/**
* Helper class for creating the ongoing notification which is used with
* {@link JitsiMeetOngoingConferenceService}. It allows the user to easily get back to the app
@@ -42,7 +43,7 @@ class OngoingNotification {
private static final String CHANNEL_NAME = "Ongoing Conference Notifications";
static final int NOTIFICATION_ID = new Random().nextInt(99999) + 10000;
private static long startingTime = 0;
static void createOngoingConferenceNotificationChannel() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
@@ -56,7 +57,7 @@ class OngoingNotification {
}
NotificationManager notificationManager
= (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
= (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel
= notificationManager.getNotificationChannel(CHANNEL_ID);
@@ -73,7 +74,7 @@ class OngoingNotification {
notificationManager.createNotificationChannel(channel);
}
static Notification buildOngoingConferenceNotification() {
static Notification buildOngoingConferenceNotification(boolean isMuted) {
Context context = ReactInstanceManagerHolder.getCurrentActivity();
if (context == null) {
JitsiMeetLogger.w(TAG + " Cannot create notification: no current context");
@@ -83,11 +84,10 @@ class OngoingNotification {
Intent notificationIntent = new Intent(context, context.getClass());
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
NotificationCompat.Builder builder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder = new NotificationCompat.Builder(context, CHANNEL_ID);
} else {
builder = new NotificationCompat.Builder(context);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID);
if (startingTime == 0) {
startingTime = System.currentTimeMillis();
}
builder
@@ -97,23 +97,36 @@ class OngoingNotification {
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setOngoing(true)
.setWhen(startingTime)
.setUsesChronometer(true)
.setAutoCancel(false)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setUsesChronometer(true)
.setOnlyAlertOnce(true)
.setSmallIcon(context.getResources().getIdentifier("ic_notification", "drawable", context.getPackageName()));
// Add a "hang-up" action only if we are using ConnectionService.
if (AudioModeModule.useConnectionService()) {
Intent hangupIntent = new Intent(context, JitsiMeetOngoingConferenceService.class);
hangupIntent.setAction(JitsiMeetOngoingConferenceService.Actions.HANGUP);
PendingIntent hangupPendingIntent
= PendingIntent.getService(context, 0, hangupIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action hangupAction = new NotificationCompat.Action(0, "Hang up", hangupPendingIntent);
NotificationCompat.Action hangupAction = createAction(context, JitsiMeetOngoingConferenceService.Action.HANGUP, R.string.ongoing_notification_action_hang_up);
builder.addAction(hangupAction);
}
JitsiMeetOngoingConferenceService.Action toggleAudioAction = isMuted
? JitsiMeetOngoingConferenceService.Action.UNMUTE : JitsiMeetOngoingConferenceService.Action.MUTE;
int toggleAudioTitle = isMuted ? R.string.ongoing_notification_action_unmute : R.string.ongoing_notification_action_mute;
NotificationCompat.Action audioAction = createAction(context, toggleAudioAction, toggleAudioTitle);
builder.addAction(hangupAction);
builder.addAction(audioAction);
return builder.build();
}
static void resetStartingtime() {
startingTime = 0;
}
private static NotificationCompat.Action createAction(Context context, JitsiMeetOngoingConferenceService.Action action, @StringRes int titleId) {
Intent intent = new Intent(context, JitsiMeetOngoingConferenceService.class);
intent.setAction(action.getName());
PendingIntent pendingIntent
= PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
String title = context.getString(titleId);
return new NotificationCompat.Action(0, title, pendingIntent);
}
}

View File

@@ -0,0 +1,27 @@
package org.jitsi.meet.sdk;
import com.google.gson.annotations.SerializedName;
public class ParticipantInfo {
@SerializedName("participantId")
public String id;
@SerializedName("displayName")
public String displayName;
@SerializedName("avatarUrl")
public String avatarUrl;
@SerializedName("email")
public String email;
@SerializedName("name")
public String name;
@SerializedName("isLocal")
public boolean isLocal;
@SerializedName("role")
public String role;
}

View File

@@ -0,0 +1,90 @@
package org.jitsi.meet.sdk;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.annotation.Nullable;
public class ParticipantsService extends android.content.BroadcastReceiver {
private static final String TAG = ParticipantsService.class.getSimpleName();
private static final String REQUEST_ID = "requestId";
private final Map<String, WeakReference<ParticipantsInfoCallback>> participantsInfoCallbackMap = new HashMap<>();
private static ParticipantsService instance;
@Nullable
public static ParticipantsService getInstance() {
return instance;
}
private ParticipantsService(Context context) {
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BroadcastEvent.Type.PARTICIPANTS_INFO_RETRIEVED.getAction());
localBroadcastManager.registerReceiver(this, intentFilter);
}
static void init(Context context) {
instance = new ParticipantsService(context);
}
public void retrieveParticipantsInfo(ParticipantsInfoCallback participantsInfoCallback) {
String callbackKey = UUID.randomUUID().toString();
this.participantsInfoCallbackMap.put(callbackKey, new WeakReference<>(participantsInfoCallback));
String actionName = BroadcastAction.Type.RETRIEVE_PARTICIPANTS_INFO.getAction();
WritableMap data = Arguments.createMap();
data.putString(REQUEST_ID, callbackKey);
ReactInstanceManagerHolder.emitEvent(actionName, data);
}
@Override
public void onReceive(Context context, Intent intent) {
BroadcastEvent event = new BroadcastEvent(intent);
switch (event.getType()) {
case PARTICIPANTS_INFO_RETRIEVED:
try {
List<ParticipantInfo> participantInfoList = new Gson().fromJson(
event.getData().get("participantsInfo").toString(),
new TypeToken<ArrayList<ParticipantInfo>>() {
}.getType());
ParticipantsInfoCallback participantsInfoCallback = this.participantsInfoCallbackMap.get(event.getData().get(REQUEST_ID).toString()).get();
if (participantsInfoCallback != null) {
participantsInfoCallback.onReceived(participantInfoList);
this.participantsInfoCallbackMap.remove(participantsInfoCallback);
}
} catch (Exception e) {
JitsiMeetLogger.w(TAG + "error parsing participantsList", e);
}
break;
}
}
public interface ParticipantsInfoCallback {
void onReceived(List<ParticipantInfo> participantInfoList);
}
}

View File

@@ -91,14 +91,6 @@ class ReactInstanceManagerHolder {
nativeModules.add(new WebRTCModule(reactContext, options));
try {
Class<?> amplitudeModuleClass = Class.forName("org.jitsi.meet.sdk.AmplitudeModule");
Constructor constructor = amplitudeModuleClass.getConstructor(ReactApplicationContext.class);
nativeModules.add((NativeModule)constructor.newInstance(reactContext));
} catch (Exception e) {
// Ignore any error, the module is not compiled when LIBRE_BUILD is enabled.
}
return nativeModules;
}
@@ -192,6 +184,7 @@ class ReactInstanceManagerHolder {
new com.facebook.react.shell.MainReactPackage(),
new com.horcrux.svg.SvgPackage(),
new com.kevinresol.react_native_default_preference.RNDefaultPreferencePackage(),
new com.learnium.RNDeviceInfo.RNDeviceInfo(),
new com.ocetnik.timer.BackgroundTimerPackage(),
new com.reactnativecommunity.asyncstorage.AsyncStoragePackage(),
new com.reactnativecommunity.netinfo.NetInfoPackage(),

View File

@@ -3,4 +3,7 @@
<string name="dropbox_app_key"></string>
<string name="ongoing_notification_title">Ongoing meeting</string>
<string name="ongoing_notification_text">You are currently in a meeting. Tap to return to it.</string>
<string name="ongoing_notification_action_hang_up">Hang up</string>
<string name="ongoing_notification_action_mute">Mute</string>
<string name="ongoing_notification_action_unmute">Unmute</string>
</resources>

View File

@@ -1,16 +1,18 @@
rootProject.name = 'jitsi-meet'
include ':app', ':sdk'
include ':react-native-async-storage'
project(':react-native-async-storage').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-async-storage/async-storage/android')
include ':react-native-background-timer'
project(':react-native-background-timer').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-background-timer/android')
include ':react-native-calendar-events'
project(':react-native-calendar-events').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-calendar-events/android')
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-device-info'
project(':react-native-device-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-device-info/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'

View File

@@ -33,6 +33,7 @@ import {
conferenceLeft,
conferenceSubjectChanged,
conferenceTimestampChanged,
conferenceUniqueIdSet,
conferenceWillJoin,
conferenceWillLeave,
dataChannelOpened,
@@ -98,6 +99,7 @@ import {
destroyLocalTracks,
getLocalJitsiAudioTrack,
getLocalJitsiVideoTrack,
getLocalTracks,
isLocalCameraTrackMuted,
isLocalTrackMuted,
isUserInteractionRequiredForUnmute,
@@ -114,7 +116,7 @@ import {
submitFeedback
} from './react/features/feedback';
import { showNotification } from './react/features/notifications';
import { mediaPermissionPromptVisibilityChanged } from './react/features/overlay';
import { mediaPermissionPromptVisibilityChanged, toggleSlowGUMOverlay } from './react/features/overlay';
import { suspendDetected } from './react/features/power-monitor';
import {
initPrejoin,
@@ -124,7 +126,7 @@ import {
} from './react/features/prejoin';
import { disableReceiver, stopReceiver } from './react/features/remote-control';
import { toggleScreenshotCaptureEffect } from './react/features/screenshot-capture';
import { setSharedVideoStatus } from './react/features/shared-video';
import { setSharedVideoStatus } from './react/features/shared-video/actions';
import { AudioMixerEffect } from './react/features/stream-effects/audio-mixer/AudioMixerEffect';
import { createPresenterEffect } from './react/features/stream-effects/presenter';
import { endpointMessageReceived } from './react/features/subtitles';
@@ -472,34 +474,42 @@ export default {
*/
createInitialLocalTracks(options = {}) {
const errors = {};
const initialDevices = [ 'audio' ];
const requestedAudio = true;
// Always get a handle on the audio input device so that we have statistics (such as "No audio input" or
// "Are you trying to speak?" ) even if the user joins the conference muted.
const initialDevices = config.disableInitialGUM ? [] : [ 'audio' ];
const requestedAudio = !config.disableInitialGUM;
let requestedVideo = false;
// Always get a handle on the audio input device so that we have statistics even if the user joins the
// conference muted. Previous implementation would only acquire the handle when the user first unmuted,
// which would results in statistics ( such as "No audio input" or "Are you trying to speak?") being available
// only after that point.
if (options.startWithAudioMuted) {
this.muteAudio(true, true);
}
if (!options.startWithVideoMuted
if (!config.disableInitialGUM
&& !options.startWithVideoMuted
&& !options.startAudioOnly
&& !options.startScreenSharing) {
initialDevices.push('video');
requestedVideo = true;
}
if (!config.disableInitialGUM) {
JitsiMeetJS.mediaDevices.addEventListener(
JitsiMediaDevicesEvents.PERMISSION_PROMPT_IS_SHOWN,
browserName =>
APP.store.dispatch(
mediaPermissionPromptVisibilityChanged(true, browserName))
);
}
JitsiMeetJS.mediaDevices.addEventListener(
JitsiMediaDevicesEvents.PERMISSION_PROMPT_IS_SHOWN,
browserName =>
APP.store.dispatch(
mediaPermissionPromptVisibilityChanged(true, browserName))
JitsiMediaDevicesEvents.SLOW_GET_USER_MEDIA,
() => APP.store.dispatch(toggleSlowGUMOverlay(true))
);
let tryCreateLocalTracks;
// On Electron there is no permission prompt for granting permissions. That's why we don't need to
// spend much time displaying the overlay screen. If GUM is not resolved withing 15 seconds it will
// probably never resolve.
const timeout = browser.isElectron() ? 15000 : 60000;
// FIXME is there any simpler way to rewrite this spaghetti below ?
if (options.startScreenSharing) {
tryCreateLocalTracks = this._createDesktopTrack()
@@ -508,7 +518,12 @@ export default {
return [ desktopStream ];
}
return createLocalTracksF({ devices: [ 'audio' ] }, true)
return createLocalTracksF({
devices: [ 'audio' ],
timeout,
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
})
.then(([ audioStream ]) =>
[ desktopStream, audioStream ])
.catch(error => {
@@ -522,7 +537,12 @@ export default {
errors.screenSharingError = error;
return requestedAudio
? createLocalTracksF({ devices: [ 'audio' ] }, true)
? createLocalTracksF({
devices: [ 'audio' ],
timeout,
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
})
: [];
})
.catch(error => {
@@ -534,15 +554,37 @@ export default {
// Resolve with no tracks
tryCreateLocalTracks = Promise.resolve([]);
} else {
tryCreateLocalTracks = createLocalTracksF({ devices: initialDevices }, true)
tryCreateLocalTracks = createLocalTracksF({
devices: initialDevices,
timeout,
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
})
.catch(err => {
if (requestedAudio && requestedVideo) {
// Try audio only...
errors.audioAndVideoError = err;
if (err.name === JitsiTrackErrors.TIMEOUT && !browser.isElectron()) {
// In this case we expect that the permission prompt is still visible. There is no point of
// executing GUM with different source. Also at the time of writting the following
// inconsistency have been noticed in some browsers - if the permissions prompt is visible
// and another GUM is executed the prompt does not change its content but if the user
// clicks allow the user action isassociated with the latest GUM call.
errors.audioOnlyError = err;
errors.videoOnlyError = err;
return [];
}
return (
createLocalTracksF({ devices: [ 'audio' ] }, true));
createLocalTracksF({
devices: [ 'audio' ],
timeout,
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
}));
} else if (requestedAudio && !requestedVideo) {
errors.audioOnlyError = err;
@@ -563,7 +605,11 @@ export default {
// Try video only...
return requestedVideo
? createLocalTracksF({ devices: [ 'video' ] }, true)
? createLocalTracksF({
devices: [ 'video' ],
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
})
: [];
})
.catch(err => {
@@ -583,6 +629,7 @@ export default {
// the user inputs their credentials, but the dialog would be
// overshadowed by the overlay.
tryCreateLocalTracks.then(tracks => {
APP.store.dispatch(toggleSlowGUMOverlay(false));
APP.store.dispatch(mediaPermissionPromptVisibilityChanged(false));
return tracks;
@@ -773,12 +820,16 @@ export default {
return this._setLocalAudioVideoStreams(tracks);
}
const [ tracks, con ] = await this.createInitialLocalTracksAndConnect(
roomName, initialOptions);
const [ tracks, con ] = await this.createInitialLocalTracksAndConnect(roomName, initialOptions);
let localTracks = tracks;
this._initDeviceList(true);
return this.startConference(con, tracks);
if (initialOptions.startWithAudioMuted) {
localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.AUDIO);
}
return this.startConference(con, localTracks);
},
/**
@@ -846,7 +897,7 @@ export default {
showUI && APP.store.dispatch(notifyMicError(error));
};
createLocalTracksF({ devices: [ 'audio' ] }, false)
createLocalTracksF({ devices: [ 'audio' ] })
.then(([ audioTrack ]) => audioTrack)
.catch(error => {
maybeShowErrorDialog(error);
@@ -960,7 +1011,7 @@ export default {
//
// FIXME when local track creation is moved to react/redux
// it should take care of the use case described above
createLocalTracksF({ devices: [ 'video' ] }, false)
createLocalTracksF({ devices: [ 'video' ] })
.then(([ videoTrack ]) => videoTrack)
.catch(error => {
// FIXME should send some feedback to the API on error ?
@@ -969,7 +1020,11 @@ export default {
// Rollback the video muted status by using null track
return null;
})
.then(videoTrack => this.useVideoStream(videoTrack));
.then(videoTrack => {
logger.debug(`muteVideo: calling useVideoStream for track: ${videoTrack}`);
return this.useVideoStream(videoTrack);
});
} else {
// FIXME show error dialog if it fails (should be handled by react)
muteLocalVideo(mute);
@@ -1269,7 +1324,11 @@ export default {
this._getConferenceOptions());
APP.store.dispatch(conferenceWillJoin(room));
this._setLocalAudioVideoStreams(localTracks);
// Filter out the tracks that are muted.
const tracks = localTracks.filter(track => !track.isMuted());
this._setLocalAudioVideoStreams(tracks);
this._room = room; // FIXME do not use this
sendLocalParticipant(APP.store, room);
@@ -1288,8 +1347,11 @@ export default {
if (track.isAudioTrack()) {
return this.useAudioStream(track);
} else if (track.isVideoTrack()) {
logger.debug(`_setLocalAudioVideoStreams is calling useVideoStream with track: ${track}`);
return this.useVideoStream(track);
}
logger.error(
'Ignored not an audio nor a video track: ', track);
@@ -1309,6 +1371,8 @@ export default {
* @returns {Promise}
*/
useVideoStream(newTrack) {
logger.debug(`useVideoStream: ${newTrack}`);
return new Promise((resolve, reject) => {
_replaceLocalVideoTrackQueue.enqueue(onFinish => {
const state = APP.store.getState();
@@ -1318,14 +1382,20 @@ export default {
if (isPrejoinPageVisible(state)) {
const oldTrack = getLocalJitsiVideoTrack(state);
logger.debug(`useVideoStream on the prejoin screen: Replacing ${oldTrack} with ${newTrack}`);
return APP.store.dispatch(replaceLocalTrack(oldTrack, newTrack))
.then(resolve)
.catch(reject)
.catch(error => {
logger.error(`useVideoStream failed on the prejoin screen: ${error}`);
reject(error);
})
.then(onFinish);
}
logger.debug(`useVideoStream: Replacing ${this.localVideo} with ${newTrack}`);
APP.store.dispatch(
replaceLocalTrack(this.localVideo, newTrack, room))
replaceLocalTrack(this.localVideo, newTrack, room))
.then(() => {
this.localVideo = newTrack;
this._setSharingScreen(newTrack);
@@ -1335,7 +1405,10 @@ export default {
this.setVideoMuteStatus(this.isLocalVideoMuted());
})
.then(resolve)
.catch(reject)
.catch(error => {
logger.error(`useVideoStream failed: ${error}`);
reject(error);
})
.then(onFinish);
});
});
@@ -1482,7 +1555,11 @@ export default {
if (didHaveVideo) {
promise = promise.then(() => createLocalTracksF({ devices: [ 'video' ] }))
.then(([ stream ]) => this.useVideoStream(stream))
.then(([ stream ]) => {
logger.debug(`_turnScreenSharingOff using ${stream} for useVideoStream`);
return this.useVideoStream(stream);
})
.catch(error => {
logger.error('failed to switch back to local video', error);
@@ -1493,7 +1570,11 @@ export default {
);
});
} else {
promise = promise.then(() => this.useVideoStream(null));
promise = promise.then(() => {
logger.debug('_turnScreenSharingOff using null for useVideoStream');
return this.useVideoStream(null);
});
}
return promise.then(
@@ -1504,6 +1585,8 @@ export default {
},
error => {
this.videoSwitchInProgress = false;
logger.error(`_turnScreenSharingOff failed: ${error}`);
throw error;
});
},
@@ -1524,6 +1607,7 @@ export default {
* @return {Promise.<T>}
*/
async toggleScreenSharing(toggle = !this._untoggleScreenSharing, options = {}) {
logger.debug(`toggleScreenSharing: ${toggle}`);
if (this.videoSwitchInProgress) {
return Promise.reject('Switch in progress.');
}
@@ -1590,6 +1674,8 @@ export default {
desktopVideoStream.on(
JitsiTrackEvents.LOCAL_TRACK_STOPPED,
() => {
logger.debug(`Local screensharing track stopped. ${this.isSharingScreen}`);
// If the stream was stopped during screen sharing
// session then we should switch back to video.
this.isSharingScreen
@@ -1754,6 +1840,7 @@ export default {
const desktopVideoStream = streams.find(stream => stream.getType() === MEDIA_TYPE.VIDEO);
if (desktopVideoStream) {
logger.debug(`_switchToScreenSharing is using ${desktopVideoStream} for useVideoStream`);
await this.useVideoStream(desktopVideoStream);
}
@@ -1862,6 +1949,10 @@ export default {
APP.store.dispatch(conferenceLeft(room, ...args));
});
room.on(
JitsiConferenceEvents.CONFERENCE_UNIQUE_ID_SET,
(...args) => APP.store.dispatch(conferenceUniqueIdSet(room, ...args)));
room.on(
JitsiConferenceEvents.AUTH_STATUS_CHANGED,
(authEnabled, authLogin) =>
@@ -1953,7 +2044,11 @@ export default {
room.on(JitsiConferenceEvents.TRACK_MUTE_CHANGED, (track, participantThatMutedUs) => {
if (participantThatMutedUs) {
APP.store.dispatch(participantMutedUs(participantThatMutedUs));
APP.store.dispatch(participantMutedUs(participantThatMutedUs, track));
if (this.isSharingScreen && track.isVideoTrack()) {
logger.debug('TRACK_MUTE_CHANGED while screen sharing');
this._turnScreenSharingOff(false);
}
}
});
@@ -2011,7 +2106,6 @@ export default {
formattedDisplayName
|| interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME)
});
APP.UI.changeDisplayName(id, formattedDisplayName);
}
);
room.on(
@@ -2050,10 +2144,7 @@ export default {
(...args) => APP.store.dispatch(lockStateChanged(room, ...args)));
room.on(JitsiConferenceEvents.KICKED, participant => {
APP.UI.hideStats();
APP.store.dispatch(kickedOut(room, participant));
// FIXME close
});
room.on(JitsiConferenceEvents.PARTICIPANT_KICKED, (kicker, kicked) => {
@@ -2109,8 +2200,26 @@ export default {
}
);
room.on(JitsiConferenceEvents.STARTED_MUTED, () => {
(room.isStartAudioMuted() || room.isStartVideoMuted())
&& APP.UI.notifyInitiallyMuted();
const audioMuted = room.isStartAudioMuted();
const videoMuted = room.isStartVideoMuted();
const localTracks = getLocalTracks(APP.store.getState()['features/base/tracks']);
const promises = [];
APP.store.dispatch(setAudioMuted(audioMuted));
APP.store.dispatch(setVideoMuted(videoMuted));
// Remove the tracks from the peerconnection.
for (const track of localTracks) {
if (audioMuted && track.jitsiTrack?.getType() === MEDIA_TYPE.AUDIO) {
promises.push(this.useAudioStream(null));
}
if (videoMuted && track.jitsiTrack?.getType() === MEDIA_TYPE.VIDEO) {
promises.push(this.useVideoStream(null));
}
}
Promise.allSettled(promises)
.then(() => APP.UI.notifyInitiallyMuted());
});
room.on(
@@ -2161,7 +2270,7 @@ export default {
.then(effect => this.localVideo.setEffect(effect))
.then(() => {
this.setVideoMuteStatus(false);
logger.log('switched local video device');
logger.log('Switched local video device while screen sharing and the video is unmuted');
this._updateVideoDeviceId();
})
.catch(err => APP.store.dispatch(notifyCameraError(err)));
@@ -2170,7 +2279,7 @@ export default {
// id for video, dispose the existing presenter track and create a new effect
// that can be applied on un-mute.
} else if (this.isSharingScreen && videoWasMuted) {
logger.log('switched local video device');
logger.log('Switched local video device: while screen sharing and the video is muted');
const { height } = this.localVideo.track.getSettings();
this._updateVideoDeviceId();
@@ -2197,12 +2306,20 @@ export default {
return stream;
})
.then(stream => this.useVideoStream(stream))
.then(stream => {
logger.log('Switching the local video device.');
return this.useVideoStream(stream);
})
.then(() => {
logger.log('switched local video device');
logger.log('Switched local video device.');
this._updateVideoDeviceId();
})
.catch(err => APP.store.dispatch(notifyCameraError(err)));
.catch(error => {
logger.error(`Switching the local video device failed: ${error}`);
return APP.store.dispatch(notifyCameraError(error));
});
}
}
);
@@ -2249,7 +2366,7 @@ export default {
return this.useAudioStream(stream);
})
.then(() => {
if (hasDefaultMicChanged) {
if (this.localAudio && 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.
@@ -2383,14 +2500,11 @@ export default {
_onConferenceJoined() {
APP.UI.initConference();
APP.keyboardshortcut.init();
if (!config.disableShortcuts) {
APP.keyboardshortcut.init();
}
APP.store.dispatch(conferenceJoined(room));
const displayName
= APP.store.getState()['features/base/settings'].displayName;
APP.UI.changeDisplayName('localVideoContainer', displayName);
},
/**
@@ -2557,6 +2671,7 @@ export default {
delete newDevices.videoinput;
// Removing the current video track in order to force the unmute to select the preferred device.
logger.debug('_onDeviceListChanged: Removing the current video track.');
this.useVideoStream(null);
}
@@ -2592,7 +2707,7 @@ 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) {
if (this.localAudio && 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.
@@ -2868,10 +2983,6 @@ export default {
APP.store.dispatch(updateSettings({
displayName: formattedNickname
}));
if (room) {
APP.UI.changeDisplayName(id, formattedNickname);
}
},
/**

137
config.js
View File

@@ -240,6 +240,12 @@ var config = {
// 90: 2
// },
// Provides a way to translate the legacy bridge signaling messages, 'LastNChangedEvent',
// 'SelectedEndpointsChangedEvent' and 'ReceiverVideoConstraint' into the new 'ReceiverVideoConstraints' message
// that invokes the new bandwidth allocation algorithm in the bridge which is described here
// - https://github.com/jitsi/jitsi-videobridge/blob/master/doc/allocation.md.
// useNewBandwidthAllocationStrategy: false,
// Specify the settings for video quality optimizations on the client.
// videoQuality: {
// // Provides a way to prevent a video codec from being negotiated on the JVB connection. The codec specified
@@ -261,9 +267,16 @@ var config = {
// // the available bandwidth calculated by the browser, but it will be capped by the values specified here.
// // This is currently not implemented on app based clients on mobile.
// maxBitratesVideo: {
// low: 200000,
// standard: 500000,
// high: 1500000
// VP8 : {
// low: 200000,
// standard: 500000,
// high: 1500000
// },
// VP9: {
// low: 100000,
// standard: 300000,
// high: 1200000
// }
// },
//
// // The options can be used to override default thresholds of video thumbnail heights corresponding to
@@ -318,6 +331,11 @@ var config = {
// TCC sequence numbers starting from 0.
// enableIceRestart: false,
// Enables forced reload of the client when the call is migrated as a result of
// the bridge going down. Currently enabled by default as call migration through
// session-terminate is causing siganling issues when Octo is enabled.
// enableForcedReload: true,
// Use TURN/UDP servers for the jitsi-videobridge connection (by default
// we filter out TURN/UDP because it is usually not needed since the
// bridge itself is reachable via UDP)
@@ -326,6 +344,9 @@ var config = {
// UI
//
// Disables responsive tiles.
// disableResponsiveTiles: false,
// Hides lobby button
// hideLobbyButton: false,
@@ -336,6 +357,13 @@ var config = {
// will be joined when no room is specified.
enableWelcomePage: true,
// Disable app shortcuts that are registered upon joining a conference
// disableShortcuts: false,
// Disable initial browser getUserMedia requests.
// This is useful for scenarios where users might want to start a conference for screensharing only
// disableInitialGUM: false,
// Enabling the close page will ignore the welcome page redirection when
// a call is hangup.
// enableClosePage: false,
@@ -384,7 +412,26 @@ var config = {
// enableAutomaticUrlCopy: false,
// Base URL for a Gravatar-compatible service. Defaults to libravatar.
// gravatarBaseURL: 'https://seccdn.libravatar.org/avatar/';
// gravatarBaseURL: 'https://seccdn.libravatar.org/avatar/',
// Moved from interfaceConfig(TOOLBAR_BUTTONS).
// The name of the toolbar buttons to display in the toolbar, including the
// "More actions" menu. If present, the button will display. Exceptions are
// "livestreaming" and "recording" which also require being a moderator and
// some other values in config.js to be enabled. Also, the "profile" button will
// not display for users with a JWT.
// Notes:
// - it's impossible to choose which buttons go in the "More actions" menu
// - it's impossible to control the placement of buttons
// - 'desktop' controls the "Share your screen" button
// - if `toolbarButtons` is undefined, we fallback to enabling all buttons on the UI
// toolbarButtons: [
// 'microphone', 'camera', 'closedcaptions', 'desktop', 'embedmeeting', 'fullscreen',
// 'fodeviceselection', 'hangup', 'profile', 'chat', 'recording',
// 'livestreaming', 'etherpad', 'sharedvideo', 'settings', 'raisehand',
// 'videoquality', 'filmstrip', 'invite', 'feedback', 'stats', 'shortcuts',
// 'tileview', 'select-background', 'download', 'help', 'mute-everyone', 'mute-video-everyone', 'security'
// ],
// Stats
//
@@ -571,6 +618,10 @@ var config = {
// the menu has option to flip the locally seen video for local presentations
// disableLocalVideoFlip: false,
// A property used to unset the default flip state of the local video.
// When it is set to 'true', the local(self) video will not be mirrored anymore.
// doNotFlipLocalVideo: false,
// Mainly privacy related settings
// Disables all invite functions from the app (share, invite, dial out...etc)
@@ -616,19 +667,33 @@ var config = {
logoImageUrl: 'https://example.com/logo-img.png'
}
*/
// brandingDataUrl: '',
// dynamicBrandingUrl: '',
// The URL of the moderated rooms microservice, if available. If it
// is present, a link to the service will be rendered on the welcome page,
// otherwise the app doesn't render it.
// moderatedRoomServiceUrl: 'https://moderated.jitsi-meet.example.com',
// If true, tile view will not be enabled automatically when the participants count threshold is reached.
// disableTileView: true,
// Hides the conference subject
// hideConferenceSubject: true
// Hides the conference timer.
// hideConferenceTimer: true,
// Hides the participants stats
// hideParticipantsStats: true
// Sets the conference subject
// subject: 'Conference Subject',
// This property is related to the use case when jitsi-meet is used via the IFrame API. When the property is true
// jitsi-meet will use the local storage of the host page instead of its own. This option is useful if the browser
// is not persisting the local storage inside the iframe.
// useHostPageLocalStorage: true,
// List of undocumented settings used in jitsi-meet
/**
_immediateReloadThreshold
@@ -680,8 +745,70 @@ var config = {
forceTurnRelay
hiddenDomain
ignoreStartMuted
websocketKeepAlive
websocketKeepAliveUrl
*/
/**
Use this array to configure which notifications will be shown to the user
The items correspond to the title or description key of that notification
Some of these notifications also depend on some other internal logic to be displayed or not,
so adding them here will not ensure they will always be displayed
A falsy value for this prop will result in having all notifications enabled (e.g null, undefined, false)
*/
// notifications: [
// 'connection.CONNFAIL', // shown when the connection fails,
// 'dialog.cameraNotSendingData', // shown when there's no feed from user's camera
// 'dialog.kickTitle', // shown when user has been kicked
// 'dialog.liveStreaming', // livestreaming notifications (pending, on, off, limits)
// 'dialog.lockTitle', // shown when setting conference password fails
// 'dialog.maxUsersLimitReached', // shown when maximmum users limit has been reached
// 'dialog.micNotSendingData', // shown when user's mic is not sending any audio
// 'dialog.passwordNotSupportedTitle', // shown when setting conference password fails due to password format
// 'dialog.recording', // recording notifications (pending, on, off, limits)
// 'dialog.remoteControlTitle', // remote control notifications (allowed, denied, start, stop, error)
// 'dialog.reservationError',
// 'dialog.serviceUnavailable', // shown when server is not reachable
// 'dialog.sessTerminated', // shown when there is a failed conference session
// 'dialog.sessionRestarted', // show when a client reload is initiated because of bridge migration
// 'dialog.tokenAuthFailed', // show when an invalid jwt is used
// 'dialog.transcribing', // transcribing notifications (pending, off)
// 'dialOut.statusMessage', // shown when dial out status is updated.
// 'liveStreaming.busy', // shown when livestreaming service is busy
// 'liveStreaming.failedToStart', // shown when livestreaming fails to start
// 'liveStreaming.unavailableTitle', // shown when livestreaming service is not reachable
// 'lobby.joinRejectedMessage', // shown when while in a lobby, user's request to join is rejected
// 'lobby.notificationTitle', // shown when lobby is toggled and when join requests are allowed / denied
// 'localRecording.localRecording', // shown when a local recording is started
// 'notify.disconnected', // shown when a participant has left
// 'notify.grantedTo', // shown when moderator rights were granted to a participant
// 'notify.invitedOneMember', // shown when 1 participant has been invited
// 'notify.invitedThreePlusMembers', // shown when 3+ participants have been invited
// 'notify.invitedTwoMembers', // shown when 2 participants have been invited
// 'notify.kickParticipant', // shown when a participant is kicked
// 'notify.mutedRemotelyTitle', // shown when user is muted by a remote party
// 'notify.mutedTitle', // shown when user has been muted upon joining,
// 'notify.newDeviceAudioTitle', // prompts the user to use a newly detected audio device
// 'notify.newDeviceCameraTitle', // prompts the user to use a newly detected camera
// 'notify.passwordRemovedRemotely', // shown when a password has been removed remotely
// 'notify.passwordSetRemotely', // shown when a password has been set remotely
// 'notify.raisedHand', // shown when a partcipant used raise hand,
// 'notify.startSilentTitle', // shown when user joined with no audio
// 'prejoin.errorDialOut',
// 'prejoin.errorDialOutDisconnected',
// 'prejoin.errorDialOutFailed',
// 'prejoin.errorDialOutStatus',
// 'prejoin.errorStatusCode',
// 'prejoin.errorValidation',
// 'recording.busy', // shown when recording service is busy
// 'recording.failedToStart', // shown when recording fails to start
// 'recording.unavailableTitle', // shown when recording service is not reachable
// 'toolbar.noAudioSignalTitle', // shown when a broken mic is detected
// 'toolbar.noisyAudioInputTitle', // shown when noise is detected for the current microphone
// 'toolbar.talkWhileMutedPopup', // shown when user tries to speak while muted
// 'transcribing.failedToStart' // shown when transcribing fails to start
// ]
// Allow all above example options to include a trailing comma and
// prevent fear when commenting out the last value.

View File

@@ -94,6 +94,10 @@ function connect(id, password, roomName) {
// in future). It's included for the time being for Jitsi Meet and lib-jitsi-meet versions interoperability.
connectionConfig.serviceUrl = connectionConfig.bosh = serviceUrl;
if (connectionConfig.websocketKeepAliveUrl) {
connectionConfig.websocketKeepAliveUrl += `?room=${roomName}`;
}
const connection = new JitsiMeetJS.JitsiConnection(null, jwt, connectionConfig);
if (config.iAmRecorder) {

View File

@@ -1,50 +1,144 @@
/**
* Mixins that mimic the way Atlaskit fills the screen with modals at low screen widths.
*/
@mixin full-size-modal-positioner() {
height: 100%;
left: 0;
position: fixed;
top: 0;
max-width: 100%;
width: 100%;
}
@mixin full-size-modal-dialog() {
height: 100%;
max-height: 100%;
border-radius: 0;
}
/**
* Move the @atlaskit/flag container up a little bit so it does not cover the
* toolbar with the first notification.
*/
.jIMojv{
.atlaskit-portal > #notifications-container {
bottom: calc(#{$newToolbarSizeWithPadding}) !important;
}
/**
* Disable the slide-in animation for @atlaskit/flag due to the animation
* repeating for each queued flag once it becomes the top flag.
*/
.mIBKA:first-child {
animation: cbfRuT 0s !important;
-webkit-animation: cbfRuT 0s !important;
}
.modal-dialog-form {
/**
* Update the @atlaskit/dropdown-menu trigger wrapper to make sure it looks
* click-able.
*/
.cjJUnw {
cursor: pointer;
}
/**
* Override @atlaskit/dropdown-menu styling when in a modal because the
* dropdown backgrounds clash with the modal backgrounds.
*/
.cksvax[data-role=droplistContent] {
border: 1px solid #455166;
.dropdown-menu div[style*="transform"] {
outline: 1px solid #455166;
}
}
/**
* Override @atlaskit/modal-dialog header styling
*/
.atlaskit-portal [role="dialog"] header {
.jitsi-icon {
cursor: pointer;
}
.jitsi-icon svg {
fill: #B8C7E0;
}
}
/**
* Make header close button more easily tappable on mobile.
*/
.mobile-browser .atlaskit-portal [role="dialog"] header .jitsi-icon {
display: grid;
place-items: center;
height: 48px;
width: 48px;
background: #2a3a4b;
border-radius: 3px;
}
/**
* Override @atlaskit/theme styling for the top toolbar so it displays over
* the video thumbnail while obscuring as little as possible.
*/
.videocontainer .tOoji {
.videocontainer__toptoolbar > div > div {
background: none;
}
/**
* Override @atlaskit/InlineDialog styling for the overflowmenu so it displays
* with the correct height.
* Keep overflow menu within screen vertical bounds and make it scrollable.
*/
.toolbox-button-wth-dialog .eYJELv {
max-height: initial;
.toolbox-button-wth-dialog > div:nth-child(2) {
background: $menuBG;
max-height: calc(100vh - #{$newToolbarSizeWithPadding} - 46px);
margin-bottom: 4px;
padding: 0;
overflow-y: auto;
}
.audio-preview > div:nth-child(2),
.video-preview > div:nth-child(2) {
margin-bottom: 4px;
outline: none;
padding: 0;
}
/**
* The following selectors keep the chat modal full-size anywhere between 100px
* and 580px for desktop or 680px for mobile.
*/
@media (min-width: 100px) and (max-width: 320px) {
.smiley-input {
display: none;
}
.shift-right .focus-lock > div > div {
@include full-size-modal-positioner();
}
.shift-right .focus-lock [role="dialog"] {
@include full-size-modal-dialog();
}
}
@media (min-width: 480px) and (max-width: 580px) {
.shift-right .focus-lock > div > div {
@include full-size-modal-positioner();
}
.shift-right .focus-lock [role="dialog"] {
@include full-size-modal-dialog();
}
}
@media (min-width: 580px) and (max-width: 680px) {
.mobile-browser {
&.shift-right .focus-lock > div > div {
@include full-size-modal-positioner();
}
&.shift-right .focus-lock [role="dialog"] {
@include full-size-modal-dialog();
}
}
}
// Override Atlaskit inline style for the modal background.
// Important is unfortunately needed for that.
.shift-right .focus-lock [role="dialog"][style] {
background-color: $chatBackgroundColor !important;
}
// Remove Atlaskit padding from the chat dialog.
.shift-right .focus-lock [role="dialog"] > div:first-child > div:nth-child(2) {
padding: 0;
}
div.Tooltip {
color: #fff;
font-size: 12px;
line-height: 14px;
padding: 8px;
}

View File

@@ -1,26 +1,37 @@
.audio-preview {
display: inline-block;
&-content {
background: #2A3A4B;
font-size: 15px;
background: $menuBG;
border-radius: 3px;
font-size: 14px;
line-height: 24px;
max-height: 456px;
overflow: auto;
width: 328px;
width: 300px;
}
&-header {
color: #fff;
align-items: center;
display: flex;
padding: 16px;
margin-top: 8px;
padding: 8px 16px;
&-icon {
color: #A4B8D1;
display: inline-block;
svg {
fill: #fff;
}
}
&--bordered {
border-bottom: 1px solid #4C4D50;
}
&-text {
font-weight: bold;
margin-left: 8px;
margin-left: 12px;
}
}
@@ -29,19 +40,18 @@
color: #fff;
cursor: pointer;
display: flex;
padding: 12px 0;
padding: 8px 0;
margin-left: 48px;
&--selected {
background: #1C2025;
background: #131519;
cursor: initial;
margin-left: 0;
padding-left: 21px;
padding-left: 18px;
}
&-text {
color: #fff;
font-size: 15px;
display: inline-block;
line-height: 24px;
text-overflow: ellipsis;
@@ -56,12 +66,13 @@
&:hover {
.audio-preview-entry {
background: #3F4E5E;
background: #36383C;
margin-left: 0;
padding-left: 48px;
&--selected {
padding-left: 21px;
padding-left: 18px;
background: $newToolbarBackgroundColor;
}
}
@@ -74,6 +85,10 @@
}
}
&:last-child {
padding-bottom: 8px;
}
.audio-preview-entry-text {
max-width: 256px;
}
@@ -84,18 +99,19 @@
&:hover {
.audio-preview-entry {
background: #3F4E5E;
background: #36383C;
margin-left: 0;
padding-left: 48px;
&--selected {
padding-left: 21px;
background: $newToolbarBackgroundColor;
padding-left: 18px;
}
}
}
.audio-preview-entry-text {
max-width: 196px;
max-width: 178px;
}
}
@@ -110,7 +126,7 @@
&--check {
background: #31B76A;
margin-right: 13px;
margin-right: 16px;
}
&--exclamation {
@@ -121,6 +137,11 @@
}
}
&-hr {
border-top: 1px solid #4C4D50;
border-bottom: 0;
}
&-test-button {
display: none;
background: #FFF;
@@ -129,23 +150,16 @@
color: #1C2025;
cursor: pointer;
font-weight: 600;
font-size: 15px;
line-height: 24px;
padding: 4px 16px;
padding: 2px 16px;
position: absolute;
right: 16px;
top: 8px;
top: 5px;
}
&-meter-mic {
position: absolute;
right: 16px;
top: 18px;
}
// Override @atlaskit/InlineDialog container which is made with styled components
& > div > div:nth-child(2) > div > div {
outline: none;
padding: 0;
top: 14px;
}
}

View File

@@ -17,6 +17,7 @@ textarea {
html {
height: 100%;
width: 100%;
overflow: hidden;
}
body {
@@ -44,20 +45,12 @@ body {
* pad the modal container in order for the modals to be centered
* while also taking the chat size into consideration.
*/
@media (min-width: 480px + $sidebarWidth) {
.shift-right [class^="Modal__FillScreen"] {
@media (min-width: 581px) {
.shift-right .atlaskit-portal > div:not(.Tooltip) {
padding-left: $sidebarWidth;
}
}
/**
* Similarly, we offset the notifications when the chat is open by
* padding the container.
*/
.shift-right [class^="styledFlagGroup-"] {
padding-left: $sidebarWidth;
}
.jitsi-icon svg {
fill: white;
}
@@ -201,74 +194,3 @@ form {
background: rgba(0, 0, 0, .5);
border-radius: 4px;
}
.desktop-browser {
@media only screen and (max-width: $smallScreen) {
.watermark {
width: 20%;
height: 20%;
}
.new-toolbox {
.toolbox-content {
.button-group-center, .button-group-left, .button-group-right {
.toolbox-button {
.toolbox-icon {
width: 28px;
height: 28px;
svg {
width: 18px;
height: 18px;
}
}
&:nth-child(2) {
.toolbox-icon {
width: 30px;
height: 30px;
}
}
}
}
}
}
}
@media only screen and (max-width: $verySmallScreen) {
#videoResolutionLabel {
display: none;
}
.vertical-filmstrip .filmstrip {
display: none;
}
.new-toolbox {
.toolbox-content {
.button-group-center, .button-group-left, .button-group-right {
.settings-button-small-icon {
display: none;
}
.toolbox-button {
.toolbox-icon {
width: 18px;
height: 18px;
svg {
width: 12px;
height: 12px;
}
}
&:nth-child(2) {
.toolbox-icon {
width: 20px;
height: 20px;
}
}
}
}
}
}
.chrome-extension-banner {
display: none;
}
}
}

View File

@@ -1,5 +1,5 @@
#sideToolbarContainer {
background-color: $newToolbarBackgroundColor;
background-color: $chatBackgroundColor;
box-sizing: border-box;
color: #FFF;
display: flex;
@@ -32,6 +32,13 @@
width: $sidebarWidth;
word-wrap: break-word;
display: flex;
flex-direction: column;
& > :first-child {
margin-top: auto;
}
a {
display: block;
}
@@ -98,43 +105,102 @@
}
.chat-header {
background-color: $chatHeaderBackgroundColor;
height: 70px;
position: relative;
width: 100%;
z-index: 1;
display: flex;
justify-content: flex-end;
padding: 16px;
align-items: center;
box-sizing: border-box;
color: #fff;
font-weight: 600;
font-size: 24px;
line-height: 32px;
.chat-close {
align-items: center;
bottom: 8px;
color: white;
.jitsi-icon {
cursor: pointer;
display: flex;
font-size: 18px;
height: 40px;
justify-content: center;
line-height: 15px;
padding: 4px;
position: absolute;
right: 5px;
width: 40px;
}
}
&:hover {
color: rgba(255, 255, 255, 0.8);
.chat-input-container {
padding: 0 16px 16px;
&.populated {
#chat-input {
&:focus-within {
border: 1px solid #619CF4;
}
.send-button {
background: #1B67EC;
cursor: pointer;
@media (hover: hover) and (pointer: fine) {
&:hover {
background: #3D82FB;
}
}
&:active {
background: #0852D4;
}
path {
fill: #fff;
}
}
}
}
}
#chat-input {
border-top: 1px solid $chatInputSeparatorColor;
border: 1px solid $chatInputSeparatorColor;
display: flex;
padding: 5px 10px;
padding: 4px;
border-radius: 3px;
* {
background-color: transparent;
}
}
.send-button-container {
display: flex;
align-items: center;
}
.send-button {
display: flex;
align-items: center;
justify-content: center;
height: 40px;
width: 40px;
border-radius: 3px;
path {
fill: $chatInputSeparatorColor;
}
}
.smiley-button {
display: flex;
align-items: center;
justify-content: center;
height: 40px;
width: 40px;
border-radius: 3px;
}
#chat-input .smiley-button {
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: #484A4F;
}
}
}
.remoteuser {
color: #B8C7E0;
}
@@ -164,10 +230,47 @@
#nickname {
text-align: center;
color: #9d9d9d;
font-size: 18px;
margin-top: 30px;
left: 5px;
right: 5px;
font-size: 16px;
margin: auto 0;
padding: 0 16px;
input {
height: 40px;
}
label {
line-height: 24px;
}
.enter-chat {
display: flex;
align-items: center;
justify-content: center;
margin-top: 16px;
height: 40px;
background: #1B67EC;
border-radius: 3px;
color: #fff;
cursor: pointer;
&.disabled {
color: #757575;
background: #11336E;
pointer-events: none;
}
}
}
.mobile-browser {
#nickname {
input {
height: 48px;
}
.enter-chat {
height: 48px;
}
}
}
.sideToolbarContainer {
@@ -177,13 +280,17 @@
}
.display-name {
font-size: 13px;
font-weight: bold;
font-size: 12px;
font-weight: 600;
margin-bottom: 5px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
@media (max-width: 580px) {
display: none !important;
}
}
.chatmessage {
@@ -224,12 +331,16 @@
}
.messagecontent {
margin: 5px 10px;
margin: 8px;
max-width: 100%;
overflow: hidden;
}
}
.timestamp {
color: #757575;
}
.smiley {
font-size: 14pt;
}
@@ -265,7 +376,9 @@
max-height: 0;
overflow: hidden;
position: absolute;
width: $sidebarWidth;
width: calc(#{$sidebarWidth} - 32px);
margin-bottom: 5px;
margin-left: -5px;
/**
* CSS transitions do not apply for auto dimensions. So to produce the css
@@ -280,9 +393,8 @@
}
#smileysContainer {
background-color: $newToolbarBackgroundColor;
border-bottom: 1px solid;
border-top: 1px solid;
background-color: $chatBackgroundColor;
border-top: 1px solid $chatInputSeparatorColor;
}
}
@@ -379,3 +491,49 @@
}
}
}
.chat-dialog {
display: flex;
flex-direction: column;
height: 100%;
margin-top: -5px; // Margin set by atlaskit.
&-header {
display: flex;
justify-content: flex-end;
align-items: center;
margin: 16px;
width: calc(100% - 32px);
box-sizing: border-box;
color: #fff;
font-weight: 600;
font-size: 24px;
line-height: 32px;
.jitsi-icon {
cursor: pointer;
}
}
#chatconversation {
width: 100%;
}
}
.touchmove-hack {
display: flex;
flex: 1;
overflow: auto;
}
/**
* Make header close button more easily tappable on mobile.
*/
.mobile-browser .chat-dialog-header .jitsi-icon {
display: grid;
place-items: center;
height: 48px;
width: 48px;
background: #36383C;
border-radius: 3px;
}

View File

@@ -69,7 +69,7 @@
}
// Override @Atlaskit/inline-dialog styles
.cpick-container > div > div:nth-child(2) > div > div {
.cpick-container > div:nth-child(2) {
outline: none;
padding: 8px 0 0 0;
}

84
css/_drawer.scss Normal file
View File

@@ -0,0 +1,84 @@
.drawer-portal {
position: absolute;
left: 0;
right: 0;
bottom: 0;
z-index: $drawerZ;
}
.drawer-menu {
max-height: 50vh;
background: #242528;
border-radius: 16px 16px 0 0;
overflow-y: auto;
&.expanded {
max-height: 80vh;
}
.drawer-toggle {
display: flex;
justify-content: center;
align-items: center;
height: 44px;
cursor: pointer;
svg {
fill: none;
}
}
.popupmenu {
margin: auto;
width: 100%;
}
.popupmenu__item {
height: 48px;
}
&#{&} .overflow-menu {
margin: auto;
font-size: 1.2em;
list-style-type: none;
padding: 0;
.overflow-menu-item {
box-sizing: border-box;
height: 48px;
padding: 12px 16px;
align-items: center;
color: $overflowMenuItemColor;
cursor: pointer;
display: flex;
font-size: 16px;
div {
display: flex;
flex-direction: row;
align-items: center;
}
&.unclickable {
cursor: default;
}
@media (hover: hover) and (pointer: fine) {
&.unclickable:hover {
background: inherit;
}
}
&.disabled {
cursor: initial;
color: #3b475c;
}
}
.profile-text {
max-width: 100%;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
}

View File

@@ -4,7 +4,7 @@
top: 30px;
right: 30px;
transition: right 0.5s;
z-index: $filmstripVideosZ + 1;
z-index: $labelsZ;
.circular-label {
align-items: center;

View File

@@ -23,44 +23,10 @@
flex-direction: row;
left: 50%;
position: absolute;
top: 10px;
bottom: 10px;
transform: translateX(-50%);
.toolbox-button {
&:first-child {
.toolbox-icon {
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}
}
&:nth-child(2) {
svg {
fill: $hangupColor;
}
}
&:last-child {
.toolbox-icon {
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
}
}
}
.filmstrip-toolbox {
flex-direction: column;
.toolbox-button {
&:nth-child(1) {
svg {
fill: $hangupColor;
}
}
.toolbox-icon {
border-radius: 3px;
}
}
}
}

View File

@@ -47,4 +47,5 @@
border-radius: 3px;
margin: -16px -24px;
padding: 16px 24px;
z-index: $popoverZ;
}

View File

@@ -6,7 +6,6 @@
min-width: 75px;
text-align: left;
padding: 0px;
width: 180px;
white-space: nowrap;
&__item {

View File

@@ -129,7 +129,7 @@
}
&-dropdown-container {
& > div > div:nth-child(2) > div > div {
& > div:nth-child(2) {
background: #fff;
padding: 0;
}

View File

@@ -25,7 +25,7 @@
text {
fill: black;
font-size: 26px;
font-weight: 400;
font-weight: 400;
}
}
@@ -197,14 +197,6 @@
&> div {
margin: 0 12px;
}
.settings-button-small-icon {
right: -8px;
&--hovered {
right: -10px;
}
}
}
}

View File

@@ -65,3 +65,21 @@
}
}
}
.desktop-browser {
&.shift-right {
@media only screen and (max-width: $verySmallScreen + $sidebarWidth) {
#videoResolutionLabel {
display: none;
}
.vertical-filmstrip .filmstrip {
display: none;
}
.chrome-extension-banner {
display: none;
}
}
}
}

View File

@@ -1,84 +1,62 @@
.settings-button {
&-container {
position: relative;
.settings-button-container {
position: relative;
.toolbox-icon {
align-items: center;
cursor: pointer;
display: flex;
background-color: #fff;
border-radius: 50%;
border: 1px solid #d1dbe8;
justify-content: center;
width: 38px;
height: 38px;
.toolbox-icon {
align-items: center;
border-radius: 3px;
cursor: pointer;
display: flex;
justify-content: center;
&.disabled, .disabled & {
cursor: initial;
color: #929292;
background-color: #36383c;
&:hover {
background-color: #daebfa;
border: 1px solid #daebfa;
}
&.toggled {
background: #2a3a4b;
border: 1px solid #5e6d7a;
svg {
fill: #fff;
}
&:hover {
background-color: #5e6d7a;
}
}
&.disabled, .disabled & {
cursor: initial;
color: #fff;
background-color: #a4b8d1;
&:hover {
background-color: #a4b8d1;
}
}
svg {
fill: #5e6d7a;
}
}
}
&-small-icon {
background: #FFF;
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 50%;
bottom: 0;
box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.25);
cursor: pointer;
height: 16px;
position: absolute;
text-align: center;
right: 4px;
width: 16px;
&> svg {
fill: #5e6d7a;
margin-top: 5px;
}
&--disabled {
background-color: #a4b8d1;
cursor: default;
}
&--hovered {
bottom: -1px;
height: 20px;
right: 2px;
width: 20px;
&> svg {
margin-top: 6px;
background-color: #36383c;
}
}
}
}
.settings-button-small-icon {
background: #36383C;
box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25), 0px 0px 0px 1px rgba(0, 0, 0, 0.1);
border-radius: 3px;
cursor: pointer;
padding: 4px;
position: absolute;
right: -4px;
top: -3px;
&:hover {
background: #F2F3F4;
box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25), 0px 0px 0px 1px rgba(0, 0, 0, 0.1);
&> svg {
fill: #000;
}
&.settings-button-small-icon--disabled {
background: #36383C;
&> svg {
fill: #929292;
}
}
}
&> svg {
fill: #fff;
}
&--disabled {
background-color: #36383c;
cursor: default;
&> svg {
fill: #929292;
}
}
}

View File

@@ -14,12 +14,15 @@
text-overflow: ellipsis;
box-sizing: border-box;
white-space: nowrap;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
&.visible {
top: 0px;
}
&.gradient {
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
}
&-text {
vertical-align: middle;
}

View File

@@ -33,245 +33,240 @@
&.visible {
bottom: 0;
.toolbox-background {
bottom: 0px;
}
}
&.no-buttons {
display: none;
}
&.shift-right {
margin-left: $sidebarWidth;
width: calc(100% - #{$sidebarWidth});
@media (min-width: 581px) {
&.shift-right {
margin-left: $sidebarWidth;
width: calc(100% - #{$sidebarWidth});
}
}
}
.toolbox-content {
align-items: center;
box-sizing: border-box;
display: flex;
margin-bottom: 16px;
position: relative;
z-index: $toolbarZ;
.button-group-center,
.button-group-left,
.button-group-right {
display: flex;
width: 33%;
}
.toolbox-background {
background-image: linear-gradient(to top, rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0));
transition: bottom .3s ease-in;
height: 160px;
width: 100%;
bottom: -160px;
.button-group-center {
justify-content: center;
}
.button-group-right {
justify-content: flex-end;
}
.toolbox-button-wth-dialog {
display: inline-block;
}
}
.toolbox-button {
color: $toolbarButtonColor;
cursor: pointer;
display: inline-block;
line-height: $newToolbarSize;
text-align: center;
}
.toolbar-button-with-badge {
display: inline-block;
position: relative;
.badge-round {
bottom: -5px;
font-size: 12px;
line-height: 20px;
min-width: 20px;
pointer-events: none;
position: absolute;
z-index: $toolbarBackgroundZ;
right: -5px;
}
}
.toolbox-content-wrapper {
display: flex;
flex-direction: column;
margin: 0 auto;
max-width: 100%;
}
.toolbox-content-items {
background: $newToolbarBackgroundColor;
box-shadow: 0px 2px 8px 4px rgba(0, 0, 0, 0.25), 0px 0px 0px 1px rgba(0, 0, 0, 0.15);
border-radius: 6px;
margin: 0 auto;
padding: 6px;
text-align: center;
>div {
margin-left: 8px;
&:first-child {
margin-left: 0;
}
}
}
.overflow-menu {
font-size: 14px;
list-style-type: none;
padding: 8px 0;
background-color: $menuBG;
.profile-text {
max-width: 150px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
.overflow-menu-item {
align-items: center;
color: $overflowMenuItemColor;
cursor: pointer;
display: flex;
font-size: 14px;
font-weight: 400;
height: 40px;
line-height: 24px;
padding: 8px 16px;
box-sizing: border-box;
@media (hover: hover) and (pointer: fine) {
&:hover {
background: $overflowMenuItemBackground;
}
}
.toolbox-content {
box-sizing: border-box;
div {
display: flex;
justify-content: space-between;
margin-left: auto;
margin-right: auto;
padding: 20px 16px;
position: relative;
width: 100%;
z-index: $toolbarZ;
flex-direction: row;
align-items: center;
}
.button-group-center,
.button-group-left,
.button-group-right {
display: flex;
width: 33%;
&.unclickable {
cursor: default;
}
&.disabled {
cursor: initial;
color: #929292;
svg {
fill: #929292;
}
}
.button-group-center {
justify-content: center;
.toolbox-button {
.toolbox-icon {
background-color: #fff;
border-radius: 50%;
border: 1px solid #d1dbe8;
margin: 0px 4px;
width: 38px;
height: 38px;
&:hover {
background-color: #daebfa;
border: 1px solid #daebfa;
}
&.toggled {
background: #2a3a4b;
border: 1px solid #5e6d7a;
svg {
fill: #fff;
}
&:hover {
background-color: #5e6d7a;
}
}
&.disabled, .disabled & {
cursor: initial;
color: #fff;
background-color: #a4b8d1;
}
svg {
fill: #5e6d7a;
}
}
&:nth-child(2) {
.toolbox-icon {
background-color: $hangupColor;
border: 1px solid $hangupColor;
width: 40px;
height: 40px;
&:hover {
background-color: $hangupColor;
}
svg {
fill: #fff;
}
}
}
}
@media (hover: hover) and (pointer: fine) {
&.unclickable:hover {
background: inherit;
}
}
}
.button-group-right {
justify-content: flex-end;
.beta-tag {
background: #36383C;
border-radius: 3px;
color: #fff;
font-size: 12px;
margin-left: 8px;
padding: 0 4px;
text-transform: uppercase;
}
.overflow-menu-item-icon {
margin-right: 16px;
i {
display: inline;
font-size: 24px;
}
@media (hover: hover) and (pointer: fine) {
i:hover {
background-color: initial;
}
}
.overflow-menu {
font-size: 1.2em;
list-style-type: none;
background-color: $overflowMenuBG;
/**
* Undo atlaskit padding by reducing margins.
*/
margin: -16px -24px;
padding: 4px 0;
img {
max-width: 24px;
max-height: 24px;
}
.overflow-menu-item {
align-items: center;
color: $overflowMenuItemColor;
cursor: pointer;
display: flex;
font-size: 14px;
height: 22px;
padding: 5px 12px;
svg {
fill: #fff;
height: 20px;
width: 20px;
}
}
div {
display: flex;
flex-direction: row;
align-items: center;
}
&:hover {
background-color: $overflowMenuItemHoverBG;
color: $overflowMenuItemHoverColor;
}
.overflow-menu-hr {
border-top: 1px solid #4C4D50;
border-bottom: 0;
margin: 8px 0;
}
&.unclickable {
cursor: default;
}
&.unclickable:hover {
background: inherit;
}
&.disabled {
cursor: initial;
color: #3b475c;
}
}
.toolbox-icon {
display: flex;
border-radius: 3px;
flex-direction: column;
font-size: 24px;
height: $newToolbarSize;
justify-content: center;
width: $newToolbarSize;
.beta-tag {
background: $overflowMenuItemColor;
border-radius: 2px;
color: $overflowMenuBG;
font-size: 11px;
font-weight: bold;
margin-left: 8px;
padding: 0 6px;
}
.overflow-menu-item-icon {
margin-right: 10px;
i {
display: inline;
font-size: 24px;
}
i:hover {
background-color: initial;
}
img {
max-width: 24px;
max-height: 24px;
}
svg {
fill: #B8C7E0 !important;
}
}
.profile-text {
max-width: 150px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
@media (hover: hover) and (pointer: fine) {
&:hover {
background: $newToolbarButtonHoverColor;
}
}
.toolbox-button {
color: $toolbarButtonColor;
cursor: pointer;
display: inline-block;
line-height: $newToolbarSize;
margin: 0 8px;
text-align: center;
@media (max-width: 320px) {
height: 36px;
width: 36px;
}
&.toggled {
background: $newToolbarButtonToggleColor;
}
&.disabled {
cursor: initial !important;
background-color: #36383c !important;
svg {
fill: #929292 !important;
}
}
}
.toolbar-button-with-badge {
position: relative;
.hangup-button {
background-color: $hangupColor;
.badge-round {
bottom: -5px;
font-size: 12px;
line-height: 20px;
min-width: 20px;
pointer-events: none;
position: absolute;
right: -5px;
}
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: $hangupHoverColor;
}
}
.toolbox-button-wth-dialog {
display: inline-block;
}
.toolbox-icon {
display: flex;
border-radius: 5px;
flex-direction: column;
font-size: 24px;
height: $newToolbarSize;
justify-content: center;
width: $newToolbarSize;
&:hover, &.toggled {
background: $newToolbarButtonHoverColor;
}
&.disabled {
cursor: initial !important;
background-color: #a4b8d1 !important;
svg {
fill: #fff !important;
}
}
}
svg {
fill: #fff;
}
}
@@ -289,3 +284,47 @@
@include transition(all .3s ease-out);
}
/**
* Audio and video buttons do not have toggled state.
*/
.audio-preview,
.video-preview {
.toolbox-icon.toggled {
background: none;
&:hover {
background: $newToolbarButtonHoverColor;
}
}
}
/**
* On small mobile devices make the toolbar full width and pad the invite prompt.
*/
.toolbox-content-mobile {
@media (max-width: 500px) {
margin-bottom: 0;
.toolbox-content-wrapper {
width: 100%;
}
.toolbox-content-items {
border-radius: 0;
display: flex;
justify-content: space-evenly;
padding: 6px 0;
width: 100%;
}
.invite-more-container {
margin: 0 16px 8px;
}
.invite-more-container.elevated {
margin-bottom: 52px;
}
}
}

View File

@@ -12,7 +12,7 @@
1px 0px 1px rgba(0,0,0,0.3),
0px 0px 1px rgba(0,0,0,0.3);
transform: translateX(-50%);
z-index: $filmstripVideosZ + 1;
z-index: $subtitlesZ;
span {
background: black;

View File

@@ -4,7 +4,8 @@
* Style variables
*/
$baseFontFamily: -apple-system, BlinkMacSystemFont, 'open_sanslight', 'Helvetica Neue', Helvetica, Arial, sans-serif;
$hangupColor: #bf2117;
$hangupColor:#DD3849;
$hangupHoverColor: #F25363;
$hangupFontSize: 2em;
/**
@@ -37,20 +38,20 @@ $presence-idle: rgb(172, 172, 172);
/**
* Toolbar
*/
$newToolbarBackgroundColor: rgba(22, 38, 55, 0.8);
$newToolbarButtonHoverColor: rgba(255, 255, 255, 0.15);
$newToolbarButtonToggleColor: rgba(255, 255, 255, 0.2);
$newToolbarBackgroundColor: #131519;
$newToolbarButtonHoverColor: rgba(255, 255, 255, 0.2);
$newToolbarButtonToggleColor: rgba(255, 255, 255, 0.15);
$AOTToolbarButtonHoverColor: rgba(14, 20, 35, 0.6);
$AOTToolbarButtonToggleColor: rgba(14, 20, 35, 1);
$menuBG:#242528;
$newToolbarFontSize: 24px;
$newToolbarHangupFontSize: 32px;
$newToolbarSize: 40px;
$newToolbarSize: 48px;
$newToolbarSizeWithPadding: calc(#{$newToolbarSize} + 24px);
$toolbarTitleFontSize: 19px;
$overflowMenuBG: initial;
$overflowMenuItemHoverBG: #313D52;
$overflowMenuItemHoverColor: #B8C7E0;
$overflowMenuItemColor: #B8C7E0;
$overflowMenuItemColor: #fff;
$overflowMenuItemBackground: #36383C;
/**
* Video layout
@@ -90,12 +91,12 @@ $modalTextColor: #333;
* Chat
*/
$chatActionsSeparatorColor: rgb(173, 105, 112);
$chatHeaderBackgroundColor: rgba(42, 58, 75, 0.9);
$chatBackgroundColor: #131519;
$chatInputSeparatorColor: #A4B8D1;
$chatLocalMessageBackgroundColor: rgb(4, 98, 178);
$chatLocalMessageBackgroundColor: #484A4F;
$chatPrivateMessageBackgroundColor: rgb(153, 69, 77);
$chatRemoteMessageBackgroundColor: rgb(86, 101, 114);
$sidebarWidth: 375px;
$chatRemoteMessageBackgroundColor: #242528;
$sidebarWidth: 315px;
/**
* Misc.
@@ -114,18 +115,21 @@ $zindex1: 1;
$zindex2: 2;
$zindex3: 3;
$toolbarBackgroundZ: 4;
$filmstripVideosZ: 5;
$labelsZ: 5;
$filmstripVideosZ: 6;
$subtitlesZ: 7;
$popoverZ: 8;
$zindex10: 10;
$reloadZ: 20;
$poweredByZ: 100;
$ringingZ: 300;
$sideToolbarContainerZ: 300;
$toolbarZ: 350;
$sideToolbarContainerZ: 200;
$toolbarZ: 250;
$drawerZ: 351;
$tooltipsZ: 401;
$dropdownMaskZ: 900;
$dropdownZ: 901;
$centeredVideoLabelZ: 1010;
$popoverZ: 1015;
$overlayZ: 1016;

View File

@@ -1,18 +1,21 @@
.video-preview {
background: none;
max-height: 290px;
display: inline-block;
max-height: 344px;
&-container {
background: $menuBG;
border-radius: 3px;
overflow: auto;
padding: 16px;
padding: 8px;
}
&-entry {
cursor: pointer;
height: 135px;
margin-bottom: 16px;
height: 168px;
margin-bottom: 8px;
position: relative;
width: 240px;
width: 284px;
&:last-child {
margin-bottom: 0;
@@ -20,13 +23,15 @@
&--selected {
border: 3px solid #31B76A;
border-radius: 3px;
cursor: default;
height: 129px;
width: 234px;
height: 162px;
width: 278px;
}
}
&-video {
border-radius: 3px;
height: 100%;
object-fit: cover;
width: 100%;
@@ -50,21 +55,28 @@
}
&-label {
bottom: 8px;
color: #fff;
font-size: 13px;
line-height: 20px;
overflow: hidden;
padding: 8px;
position: absolute;
text-align: center;
text-overflow: ellipsis;
width: 220px;
width: 100%;
z-index: 2;
}
// Override @atlaskit/InlineDialog container which is made with styled components
& > div > div:nth-child(2) > div > div {
outline: none;
padding: 0;
&-container {
margin: 0 16px;
}
&-text {
background-color: #131519;
border-radius: 3px;
padding: 2px 8px;
font-size: 13px;
line-height: 20px;
margin: 0 auto;
max-width: calc(100% - 16px);
overflow: hidden;
text-overflow: ellipsis;
width: fit-content;
white-space: nowrap;
}
}
}

View File

@@ -182,10 +182,12 @@
z-index: $zindex2;
}
&.shift-right {
&#largeVideoContainer {
margin-left: $sidebarWidth;
width: calc(100% - #{$sidebarWidth});
@media (min-width: 581px) {
&.shift-right {
&#largeVideoContainer {
margin-left: $sidebarWidth;
width: calc(100% - #{$sidebarWidth});
}
}
}
}
@@ -478,14 +480,6 @@
z-index: $reloadZ; /*The reload button should appear on top of the header!*/
}
.audiolevel {
display: inline-block;
position: absolute;
z-index: $zindex0;
border-radius:1px;
pointer-events: none;
}
#dominantSpeaker {
visibility: hidden;
width: 300px;

View File

@@ -90,7 +90,7 @@ body.welcome-page {
color: $defaultWarningColor;
display: flex;
flex-direction: row;
margin-top: 5px;
margin-top: 15px;
.jitsi-icon {
margin-right: 15px;
@@ -208,6 +208,11 @@ body.welcome-page {
cursor: pointer;
font-size: 32px;
}
.toolbox-icon {
height: 24px;
width: 24px;
}
}
.welcome-watermark {

View File

@@ -6,7 +6,6 @@
}
.horizontal-filmstrip .filmstrip {
position: absolute;
bottom: 0;
right: 0;
padding: 10px 5px;

View File

@@ -15,7 +15,7 @@
box-sizing: border-box;
display: flex;
flex-direction: column;
height: 100vh;
height: 100%;
width: 100vw;
}
@@ -42,17 +42,18 @@
height: 100%;
justify-content: center;
left: 0;
position: fixed;
position: absolute;
top: 0;
width: 100%;
z-index: $filmstripVideosZ;
&.shift-right {
margin-left: $sidebarWidth;
width: calc(100% - #{$sidebarWidth});
@media (min-width: 581px) {
&.shift-right {
margin-left: $sidebarWidth;
width: calc(100% - #{$sidebarWidth});
#filmstripRemoteVideos {
width: calc(100vw - #{$sidebarWidth});
#filmstripRemoteVideos {
width: calc(100vw - #{$sidebarWidth});
}
}
}
}
@@ -86,6 +87,7 @@
box-sizing: border-box;
display: flex;
flex-wrap: wrap;
flex-shrink: 0;
margin-top: auto;
margin-bottom: auto;
justify-content: center;
@@ -100,6 +102,15 @@
video {
object-fit: contain;
}
/**
* Max-width corresponding to the ASPECT_RATIO_BREAKPOINT from features/filmstrip/constants.
*/
@media only screen and (max-width: 500px) {
video {
object-fit: cover;
}
}
}
.has-overflow#filmstripRemoteVideosContainer {
@@ -109,14 +120,4 @@
.has-overflow .videocontainer {
align-self: baseline;
}
/**
* Firefox flex acts a little differently. To make sure the bottom row of
* thumbnails is not overlapped by the horizontal toolbar, margin is added
* to the local thumbnail to keep it from the bottom of the screen. It is
* assumed the local thumbnail will always be on the bottom row.
*/
.has-overflow #localVideoContainer {
margin-bottom: 100px !important;
}
}

View File

@@ -22,11 +22,6 @@
display: none;
}
#remoteConnectionMessage,
.watermark {
z-index: $filmstripVideosZ + 1;
}
/**
* The follow styling uses !important to override inline styles set with
* javascript.

View File

@@ -43,6 +43,7 @@ $flagsImagePath: "../images/";
@import 'modals/settings/settings';
@import 'modals/speaker_stats/speaker_stats';
@import 'modals/video-quality/video-quality';
@import 'modals/virtual-background/virtual-background';
@import 'modals/local-recording/local-recording';
@import 'videolayout_default';
@import 'notice';
@@ -103,5 +104,6 @@ $flagsImagePath: "../images/";
@import 'e2ee';
@import 'responsive';
@import 'connection-status';
@import 'drawer';
/* Modules END */

View File

@@ -39,7 +39,7 @@
.device-selector-trigger-text {
overflow: hidden;
margin-left: 8px;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
width: 100%;

View File

@@ -2,22 +2,6 @@
&-dialog {
display: flex;
flex-direction: column;
&-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 {

View File

@@ -50,6 +50,12 @@
}
}
.dial-in-number {
display: flex;
justify-content: space-between;
padding-right: 8px;
}
.dial-in-numbers-list {
margin-top: 20px;
font-size: 12px;

View File

@@ -1,45 +1,55 @@
.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));
margin-bottom: 8px;
transition: margin-bottom 0.3s;
&.elevated {
z-index: $filmstripVideosZ + 1;
margin-bottom: 36px;
}
}
&-content {
display: flex;
flex-direction: column;
align-items: center;
padding: 16px;
background: rgba(0, 0, 0, 0.7);
border-radius: 8px;
color: #fff;
font-size: 16px;
line-height: 24px;
font-weight: 600;
}
&-header {
font-size: 19px;
line-height: 28px;
margin: 24px 0 16px 0;
max-width: 100%;
margin-bottom: 16px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
&-button {
display: flex;
margin: auto;
padding: 8px 16px;
width: fit-content;
width: -moz-fit-content;
height: 24px;
max-width: 100%;
height: 48px;
box-sizing: border-box;
padding: 12px 16px;
background: #0376DA;
border-radius: 3px;
font-size: 14px;
line-height: 24px;
cursor: pointer;
&:hover {
background: #278ADF;
@media (hover: hover) and (pointer: fine) {
&:hover {
background: #278ADF;
}
}
&-text {
margin-left: 8px;
font-size: 15px;
line-height: 24px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
&-dialog {
@@ -47,22 +57,6 @@
font-size: 15px;
line-height: 24px;
&.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;
}
}
&.separator {
margin: 24px 0 24px -20px;
padding: 0 20px;
@@ -112,11 +106,11 @@
border-radius: 4px;
cursor: pointer;
}
&:hover > div:hover {
background-color: rgba(255, 255, 255, 0.2);
}
& > :not(:last-child) {
margin-right: 16px;
}
@@ -135,7 +129,6 @@
.dial-in-copy {
display: inline-block;
vertical-align: middle;
margin-left: 21px;
cursor: pointer;
}
}

View File

@@ -23,6 +23,10 @@
padding: 20px 0px 4px 0px;
}
input[type="checkbox"] + svg + span {
color: #9FB0CC;
}
.calendar-tab,
.more-tab,
.profile-edit {

View File

@@ -111,7 +111,3 @@
display: none;
}
}
#videoResolutionLabel {
z-index: $zindex3 + 1;
}

View File

@@ -0,0 +1,44 @@
.virtual-background-dialog{
display: inline-flex;
cursor: pointer;
.thumbnail{
object-fit: cover;
padding: 5px;
height: 40px;
width: 40px;
}
.thumbnail-selected{
object-fit: cover;
padding: 5px;
height: 40px;
width: 40px;
border: 2px solid #a4b8d1;
}
.blur-selected{
border: 2px solid #a4b8d1;
}
.virtual-background-none{
font-weight: bold;
padding: 5px;
height: 35px;
width: 35px;
border-radius: 10px;
border: 1px solid #a4b8d1;
text-align: center;
vertical-align: middle;
line-height: 35px;
margin-right: 5px;
}
.none-selected{
font-weight: bold;
padding: 5px;
height: 35px;
width: 35px;
border-radius: 10px;
border: 2px solid #a4b8d1;
text-align: center;
vertical-align: middle;
line-height: 35px;
margin-right: 5px;
}
}

View File

@@ -33,4 +33,12 @@
bottom: 24px;
width: 100%;
}
&__spinner-container {
display: flex;
width: 100%;
height: 100%;
justify-content: center;
align-items: center;
}
}

2
debian/control vendored
View File

@@ -33,7 +33,7 @@ Description: Configuration for web serving of Jitsi Meet
Package: jitsi-meet-prosody
Architecture: all
Depends: openssl, prosody | prosody-trunk | prosody-0.11
Depends: openssl, prosody | prosody-trunk | prosody-0.11, lua-sec
Replaces: jitsi-meet-tokens
Description: Prosody configuration for Jitsi Meet
Jitsi Meet is a WebRTC JavaScript application that uses Jitsi

View File

@@ -35,7 +35,7 @@ case "$1" in
db_input critical jitsi-videobridge/jvb-hostname || true
db_go
fi
JVB_HOSTNAME="$RET"
JVB_HOSTNAME=$(echo "$RET" | xargs echo -n)
db_get jitsi-videobridge/jvbsecret
if [ -z "$RET" ] ; then
@@ -60,20 +60,11 @@ case "$1" in
JICOFO_AUTH_PASSWORD="$RET"
fi
db_get jicofo/jicofosecret
if [ -z "$RET" ] ; then
# if secret is missing generate it, and store it
JICOFO_SECRET=`generateRandomPassword`
db_set jicofo/jicofosecret "$JICOFO_SECRET"
else
JICOFO_SECRET="$RET"
fi
JICOFO_AUTH_DOMAIN="auth.$JVB_HOSTNAME"
# detect dpkg-reconfigure, just delete old links
db_get jitsi-meet-prosody/jvb-hostname
JVB_HOSTNAME_OLD=$RET
JVB_HOSTNAME_OLD=$(echo "$RET" | xargs echo -n)
if [ -n "$RET" ] && [ ! "$JVB_HOSTNAME_OLD" = "$JVB_HOSTNAME" ] ; then
rm -f /etc/prosody/conf.d/$JVB_HOSTNAME_OLD.cfg.lua
rm -f /etc/prosody/certs/$JVB_HOSTNAME_OLD.key
@@ -107,7 +98,6 @@ case "$1" in
mkdir -p /etc/prosody/conf.d/
cp /usr/share/jitsi-meet-prosody/prosody.cfg.lua-jvb.example $PROSODY_HOST_CONFIG
sed -i "s/jitmeet.example.com/$JVB_HOSTNAME/g" $PROSODY_HOST_CONFIG
sed -i "s/focusSecret/$JICOFO_SECRET/g" $PROSODY_HOST_CONFIG
sed -i "s/focusUser/$JICOFO_AUTH_USER/g" $PROSODY_HOST_CONFIG
sed -i "s/__turnSecret__/$TURN_SECRET/g" $PROSODY_HOST_CONFIG
if [ ! -f /etc/prosody/conf.d/$JVB_HOSTNAME.cfg.lua ]; then
@@ -142,6 +132,28 @@ case "$1" in
echo -e " admins = { \"$JICOFO_AUTH_USER@auth.$JVB_HOSTNAME\", \"jvb@auth.$JVB_HOSTNAME\" }" >> $PROSODY_HOST_CONFIG
fi
# Convert the old focus component config to the new one.
# Old:
# Component "focus.jitmeet.example.com"
# component_secret = "focusSecret"
# New:
# Component "focus.jitmeet.example.com" "client_proxy"
# target_address = "focus@auth.jitmeet.example.com"
if grep -q "Component \"focus.$JVB_HOSTNAME\"" $PROSODY_HOST_CONFIG && ! grep "Component \"focus.$JVB_HOSTNAME\" \"client_proxy\"" $PROSODY_HOST_CONFIG ;then
sed -i "s/Component \"focus.$JVB_HOSTNAME\"/Component \"focus.$JVB_HOSTNAME\" \"client_proxy\"\n target_address = \"$JICOFO_AUTH_USER@auth.$JVB_HOSTNAME\"/g" $PROSODY_HOST_CONFIG
PROSODY_CONFIG_PRESENT="false"
fi
# Old versions of jitsi-meet-prosody come with the extra plugin path commented out (https://github.com/jitsi/jitsi-meet/commit/e11d4d3101e5228bf956a69a9e8da73d0aee7949)
# Make sure it is uncommented, as it contains required modules.
if grep -q -- '--plugin_paths = { "/usr/share/jitsi-meet/prosody-plugins/" }' $PROSODY_HOST_CONFIG ;then
sed -i 's#--plugin_paths = { "/usr/share/jitsi-meet/prosody-plugins/" }#plugin_paths = { "/usr/share/jitsi-meet/prosody-plugins/" }#g' $PROSODY_HOST_CONFIG
PROSODY_CONFIG_PRESENT="false"
fi
# Make sure the focus@auth user's roster includes the proxy component (this is idempotent)
prosodyctl mod_roster_command subscribe focus.$JVB_HOSTNAME $JICOFO_AUTH_USER@auth.$JVB_HOSTNAME
if [ ! -f /var/lib/prosody/$JVB_HOSTNAME.crt ]; then
# prosodyctl takes care for the permissions
# echo for using all default values

View File

@@ -31,7 +31,7 @@ case "$1" in
purge)
db_get jitsi-meet-prosody/jvb-hostname
JVB_HOSTNAME=$RET
JVB_HOSTNAME=$(echo "$RET" | xargs echo -n)
if [ -n "$RET" ]; then
rm -f /etc/prosody/conf.avail/$JVB_HOSTNAME.cfg.lua
rm -f /etc/prosody/conf.d/$JVB_HOSTNAME.cfg.lua

View File

@@ -24,11 +24,6 @@ Type: password
_Description: Jicofo user password:
The secret used to connect to xmpp server as jicofo user.
Template: jicofo/jicofosecret
Type: password
_Description: Jicofo Component secret:
The secret used to connect to xmpp server as component
Template: jitsi-meet-prosody/turn-secret
Type: string
_Description: The turn server secret

View File

@@ -25,7 +25,7 @@ case "$1" in
. /usr/share/debconf/confmodule
db_get jitsi-meet-prosody/jvb-hostname
JVB_HOSTNAME="$RET"
JVB_HOSTNAME=$(echo "$RET" | xargs echo -n)
db_get jitsi-meet-tokens/appid
if [ "$RET" = "false" ] ; then

View File

@@ -30,7 +30,7 @@ case "$1" in
db_input critical jitsi-videobridge/jvb-hostname || true
db_go
fi
JVB_HOSTNAME="$RET"
JVB_HOSTNAME=$(echo "$RET" | xargs echo -n)
TURN_CONFIG="/etc/turnserver.conf"
NGINX_CONFIG="/etc/nginx/sites-available/$JVB_HOSTNAME.conf"
@@ -44,7 +44,7 @@ case "$1" in
# detect dpkg-reconfigure, just delete old links
db_get jitsi-meet-turnserver/jvb-hostname
JVB_HOSTNAME_OLD=$RET
JVB_HOSTNAME_OLD=$(echo "$RET" | xargs echo -n)
if [ -n "$RET" ] && [ ! "$JVB_HOSTNAME_OLD" = "$JVB_HOSTNAME" ] ; then
if [[ -f $TURN_CONFIG ]] && grep -q "jitsi-meet coturn config" "$TURN_CONFIG" ; then
rm -f $TURN_CONFIG

View File

@@ -30,13 +30,14 @@ case "$1" in
db_set jitsi-videobridge/jvb-hostname "localhost"
db_input critical jitsi-videobridge/jvb-hostname || true
db_go
db_get jitsi-videobridge/jvb-hostname
fi
JVB_HOSTNAME="$RET"
JVB_HOSTNAME=$(echo "$RET" | xargs echo -n)
# detect dpkg-reconfigure
RECONFIGURING="false"
db_get jitsi-meet/jvb-hostname
JVB_HOSTNAME_OLD=$RET
JVB_HOSTNAME_OLD=$(echo "$RET" | xargs echo -n)
if [ -n "$RET" ] && [ ! "$JVB_HOSTNAME_OLD" = "$JVB_HOSTNAME" ] ; then
RECONFIGURING="true"
rm -f /etc/jitsi/meet/$JVB_HOSTNAME_OLD-config.js
@@ -44,8 +45,9 @@ case "$1" in
JVB_SERVE="false"
# this detect only old installations
RET=""
db_get jitsi-meet/jvb-serve || true
if [ -n "$RET" ] && [ "$RET" = "true" ] ; then
if [ "$RET" = "true" ] ; then
JVB_SERVE="true"
fi
@@ -67,23 +69,38 @@ case "$1" in
if [ "$APACHE_INSTALL_CHECK" = "installed" ] || [ "$APACHE_INSTALL_CHECK" = "unpacked" ] ; then
FORCE_APACHE="true"
fi
# In case user enforces apache and if apache is available, unset nginx.
RET=""
db_get jitsi-meet/enforce_apache || RET="false"
if [ "$RET" = "true" ] && [ "$FORCE_APACHE" = "true" ]; then
FORCE_NGINX="false"
fi
UPLOADED_CERT_CHOICE="I want to use my own certificate"
# if first time config ask for certs, or if we are reconfiguring
if [ -z "$JVB_HOSTNAME_OLD" ] || [ "$RECONFIGURING" = "true" ] ; then
RET=""
db_get jitsi-meet/cert-choice
CERT_CHOICE="$RET"
if [ "$CERT_CHOICE" = "$UPLOADED_CERT_CHOICE" ] ; then
db_set jitsi-meet/cert-path-key "/etc/ssl/$JVB_HOSTNAME.key"
db_input critical jitsi-meet/cert-path-key || true
db_go
RET=""
db_get jitsi-meet/cert-path-key
if [ -z "$RET" ] ; then
db_set jitsi-meet/cert-path-key "/etc/ssl/$JVB_HOSTNAME.key"
db_input critical jitsi-meet/cert-path-key || true
db_go
db_get jitsi-meet/cert-path-key
fi
CERT_KEY="$RET"
db_set jitsi-meet/cert-path-crt "/etc/ssl/$JVB_HOSTNAME.crt"
db_input critical jitsi-meet/cert-path-crt || true
db_go
RET=""
db_get jitsi-meet/cert-path-crt
if [ -z "$RET" ] ; then
db_set jitsi-meet/cert-path-crt "/etc/ssl/$JVB_HOSTNAME.crt"
db_input critical jitsi-meet/cert-path-crt || true
db_go
db_get jitsi-meet/cert-path-crt
fi
CERT_CRT="$RET"
else
# create self-signed certs
@@ -139,12 +156,15 @@ case "$1" in
# Removing this value will force nginx or apache to be locally configured
JVB_HOSTNAME_OLD=""
RET=""
db_get jitsi-meet/cert-choice
CERT_CHOICE="$RET"
# Fix certs on upgrade from jetty
if [ "$CERT_CHOICE" = "$UPLOADED_CERT_CHOICE" ] ; then
RET=""
db_get jitsi-meet/cert-path-key
CERT_KEY="$RET"
RET=""
db_get jitsi-meet/cert-path-crt
CERT_CRT="$RET"
else
@@ -198,7 +218,7 @@ case "$1" in
# apache2 config
if [ ! -f /etc/apache2/sites-available/$JVB_HOSTNAME.conf ] ; then
# when creating new config, make sure all needed modules are enabled
a2enmod rewrite ssl headers proxy_http include
a2enmod rewrite ssl headers proxy_http proxy_wstunnel include
cp /usr/share/jitsi-meet-web-config/jitsi-meet.example-apache /etc/apache2/sites-available/$JVB_HOSTNAME.conf
a2ensite $JVB_HOSTNAME.conf
sed -i "s/jitsi-meet.example.com/$JVB_HOSTNAME/g" /etc/apache2/sites-available/$JVB_HOSTNAME.conf

View File

@@ -33,7 +33,7 @@ case "$1" in
;;
purge)
db_get jitsi-meet/jvb-hostname
JVB_HOSTNAME=$RET
JVB_HOSTNAME=$(echo "$RET" | xargs echo -n)
if [ -n "$RET" ]; then
rm -f /etc/jitsi/meet/$JVB_HOSTNAME-config.js
rm -f /etc/nginx/sites-available/$JVB_HOSTNAME.conf

View File

@@ -15,3 +15,5 @@ resources/robots.txt /usr/share/jitsi-meet/
resources/*.sh /usr/share/jitsi-meet/scripts/
pwa-worker.js /usr/share/jitsi-meet/
manifest.json /usr/share/jitsi-meet/
resources/load-test/*.html /usr/share/jitsi-meet/load-test/
resources/load-test/libs /usr/share/jitsi-meet/load-test/

View File

@@ -3,12 +3,11 @@ 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 = "jitmeet.example.com";
turncredentials_secret = "__turnSecret__";
turncredentials = {
{ type = "stun", host = "jitmeet.example.com", port = "3478" },
{ type = "turn", host = "jitmeet.example.com", port = "3478", transport = "udp" },
{ type = "turns", host = "jitmeet.example.com", port = "5349", transport = "tcp" }
external_service_secret = "__turnSecret__";
external_services = {
{ type = "stun", host = "jitmeet.example.com", port = 3478 },
{ type = "turn", host = "jitmeet.example.com", port = 3478, transport = "udp", secret = true, ttl = 86400, algorithm = "turn" },
{ type = "turns", host = "jitmeet.example.com", port = 5349, transport = "tcp", secret = true, ttl = 86400, algorithm = "turn" }
};
cross_domain_bosh = false;
@@ -17,48 +16,48 @@ consider_bosh_secure = true;
-- 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"
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
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/jitmeet.example.com.key";
certificate = "/etc/prosody/certs/jitmeet.example.com.crt";
}
speakerstats_component = "speakerstats.jitmeet.example.com"
conference_duration_component = "conferenceduration.jitmeet.example.com"
-- we need bosh
modules_enabled = {
"bosh";
"pubsub";
"ping"; -- Enable mod_ping
"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
-- 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/jitmeet.example.com.key";
certificate = "/etc/prosody/certs/jitmeet.example.com.crt";
}
speakerstats_component = "speakerstats.jitmeet.example.com"
conference_duration_component = "conferenceduration.jitmeet.example.com"
-- we need bosh
modules_enabled = {
"bosh";
"pubsub";
"ping"; -- Enable mod_ping
"speakerstats";
"external_services";
"conference_duration";
"muc_lobby_rooms";
}
c2s_require_encryption = false
lobby_muc = "lobby.jitmeet.example.com"
main_muc = "conference.jitmeet.example.com"
-- muc_lobby_whitelist = { "recorder.jitmeet.example.com" } -- Here we can whitelist jibri to enter lobby enabled rooms
Component "conference.jitmeet.example.com" "muc"
storage = "memory"
modules_enabled = {
"muc_meeting_id";
"muc_domain_mapper";
-- "token_verification";
--"token_verification";
}
admins = { "focusUser@auth.jitmeet.example.com" }
muc_room_locking = false
@@ -68,17 +67,18 @@ Component "conference.jitmeet.example.com" "muc"
Component "internal.auth.jitmeet.example.com" "muc"
storage = "memory"
modules_enabled = {
"ping";
"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"
authentication = "internal_hashed"
Component "focus.jitmeet.example.com"
component_secret = "focusSecret"
-- Proxy to jicofo's user JID, so that it doesn't have to register as a component.
Component "focus.jitmeet.example.com" "client_proxy"
target_address = "focusUser@auth.jitmeet.example.com"
Component "speakerstats.jitmeet.example.com" "speakerstats_component"
muc_component = "conference.jitmeet.example.com"

View File

@@ -1,19 +1,23 @@
server_names_hash_bucket_size 64;
types {
# nginx's default mime.types doesn't include a mapping for wasm
application/wasm wasm;
}
server {
listen 80;
listen [::]:80;
server_name jitsi-meet.example.com;
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /usr/share/jitsi-meet;
default_type "text/plain";
root /usr/share/jitsi-meet;
}
location = /.well-known/acme-challenge/ {
return 404;
return 404;
}
location / {
return 301 https://$host$request_uri;
return 301 https://$host$request_uri;
}
}
server {
@@ -21,7 +25,7 @@ server {
listen [::]:443 ssl;
server_name jitsi-meet.example.com;
# Mozilla Guideline v5.4, nginx 1.17.7, OpenSSL 1.1.1d, intermediate configuration
# 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;
@@ -58,7 +62,7 @@ server {
alias /usr/share/jitsi-meet/libs/external_api.min.js;
}
#ensure all static content can always be found first
# 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' '*';
@@ -66,13 +70,13 @@ server {
# cache all versioned files
if ($arg_v) {
expires 1y;
expires 1y;
}
}
# BOSH
location = /http-bind {
proxy_pass http://localhost:5280/http-bind;
proxy_pass http://localhost:5280/http-bind;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
}
@@ -89,13 +93,22 @@ server {
# colibri (JVB) websockets for jvb1
location ~ ^/colibri-ws/default-id/(.*) {
proxy_pass http://127.0.0.1:9090/colibri-ws/default-id/$1$is_args$args;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
tcp_nodelay on;
proxy_pass http://127.0.0.1:9090/colibri-ws/default-id/$1$is_args$args;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
tcp_nodelay on;
}
# load test minimal client, uncomment when used
#location ~ ^/_load-test/([^/?&:'"]+)$ {
# rewrite ^/_load-test/(.*)$ /load-test/index.html break;
#}
#location ~ ^/_load-test/libs/(.*)$ {
# add_header 'Access-Control-Allow-Origin' '*';
# alias /usr/share/jitsi-meet/load-test/libs/$1;
#}
location ~ ^/([^/?&:'"]+)$ {
try_files $uri @root_path;
}
@@ -106,13 +119,13 @@ server {
location ~ ^/([^/?&:'"]+)/config.js$
{
set $subdomain "$1.";
set $subdir "$1/";
set $subdomain "$1.";
set $subdir "$1/";
alias /etc/jitsi/meet/jitsi-meet.example.com-config.js;
alias /etc/jitsi/meet/jitsi-meet.example.com-config.js;
}
#Anything that didn't match above, and isn't a real file, assume it's a room name and redirect to /
# Anything that didn't match above, and isn't a real file, assume it's a room name and redirect to /
location ~ ^/([^/?&:'"]+)/(.*)$ {
set $subdomain "$1.";
set $subdir "$1/";

View File

@@ -2,56 +2,56 @@
<VirtualHost *:80>
ServerName jitsi-meet.example.com
Redirect permanent / https://jitsi-meet.example.com/
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>
<VirtualHost *:443>
ServerName jitsi-meet.example.com
ServerName jitsi-meet.example.com
# enable HTTP/2, if available
Protocols h2 http/1.1
# 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
SSLEngine on
SSLProxyEngine on
SSLCertificateFile /etc/jitsi/meet/jitsi-meet.example.com.crt
SSLCertificateKeyFile /etc/jitsi/meet/jitsi-meet.example.com.key
Header always set Strict-Transport-Security "max-age=63072000"
Header always set Strict-Transport-Security "max-age=63072000"
DocumentRoot "/usr/share/jitsi-meet"
<Directory "/usr/share/jitsi-meet">
Options Indexes MultiViews Includes FollowSymLinks
AddOutputFilter Includes html
AllowOverride All
Order allow,deny
Allow from all
</Directory>
DocumentRoot "/usr/share/jitsi-meet"
<Directory "/usr/share/jitsi-meet">
Options Indexes MultiViews Includes FollowSymLinks
AddOutputFilter Includes html
AllowOverride All
Order allow,deny
Allow from all
</Directory>
ErrorDocument 404 /static/404.html
ErrorDocument 404 /static/404.html
Alias "/config.js" "/etc/jitsi/meet/jitsi-meet.example.com-config.js"
<Location /config.js>
Require all granted
</Location>
Alias "/config.js" "/etc/jitsi/meet/jitsi-meet.example.com-config.js"
<Location /config.js>
Require all granted
</Location>
Alias "/external_api.js" "/usr/share/jitsi-meet/libs/external_api.min.js"
<Location /external_api.js>
Require all granted
</Location>
Alias "/external_api.js" "/usr/share/jitsi-meet/libs/external_api.min.js"
<Location /external_api.js>
Require all granted
</Location>
ProxyPreserveHost on
ProxyPass /http-bind http://localhost:5280/http-bind
ProxyPassReverse /http-bind http://localhost:5280/http-bind
ProxyPass /xmpp-websocket ws://localhost:5280/xmpp-websocket
ProxyPassReverse /xmpp-websocket ws://localhost:5280/xmpp-websocket
ProxyPass /colibri-ws/default-id ws://localhost:9090/colibri-ws/default-id
ProxyPassReverse /colibri-ws/default-id ws://localhost:9090/colibri-ws/default-id
ProxyPreserveHost on
ProxyPass /http-bind http://localhost:5280/http-bind/
ProxyPassReverse /http-bind http://localhost:5280/http-bind/
RewriteEngine on
RewriteRule ^/([a-zA-Z0-9]+)$ /index.html
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
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

@@ -10,7 +10,6 @@ server {
index index.html;
set $prefix "";
# BOSH
location /http-bind {
proxy_pass http://localhost:5280/http-bind;
@@ -44,13 +43,13 @@ server {
location ~ ^/([^/?&:'"]+)/config.js$
{
set $subdomain "$1.";
set $subdir "$1/";
set $subdomain "$1.";
set $subdir "$1/";
alias /etc/jitsi/meet/{{jitsi_meet_domain_name}}-config.js;
alias /etc/jitsi/meet/{{jitsi_meet_domain_name}}-config.js;
}
#Anything that didn't match above, and isn't a real file, assume it's a room name and redirect to /
# Anything that didn't match above, and isn't a real file, assume it's a room name and redirect to /
location ~ ^/([^/?&:'"]+)/(.*)$ {
set $subdomain "$1.";
set $subdir "$1/";

View File

@@ -34,55 +34,56 @@ component_ports = { 5347 }
-- Documentation on modules can be found at: http://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
"posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
-- 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
"posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
-- Not essential, but recommended
"private"; -- Private XML storage (for room bookmarks, etc.)
"vcard"; -- Allow users to set vCards
-- Not essential, but recommended
"private"; -- Private XML storage (for room bookmarks, etc.)
"vcard"; -- Allow users to set vCards
-- These are commented by default as they have a performance impact
--"privacy"; -- Support privacy lists
"compression"; -- Stream compression (requires the lua-zlib package installed)
-- These are commented by default as they have a performance impact
--"privacy"; -- Support privacy lists
"compression"; -- Stream compression (requires the lua-zlib package installed)
-- 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
"pep"; -- Enables users to publish their mood, activity, playing music and more
"register"; -- Allow users to register on this server using a client and change passwords
-- 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
"pep"; -- Enables users to publish their mood, activity, playing music and more
"register"; -- Allow users to register on this server using a client and change passwords
-- 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
-- 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"
--"http_files"; -- Serve static files from a directory over HTTP
-- HTTP modules
"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
--"http_files"; -- Serve static files from a directory over HTTP
-- Other specific functionality
--"groups"; -- Shared roster support
--"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.
-- jitsi
"smacks";
"carbons";
"mam";
"lastactivity";
"offline";
"pubsub";
"adhoc";
"websocket";
"http_altconnect";
-- Other specific functionality
--"groups"; -- Shared roster support
--"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.
-- jitsi
"smacks";
"carbons";
"mam";
"lastactivity";
"offline";
"pubsub";
"adhoc";
"websocket";
"http_altconnect";
}
-- domain mapper options, must at least have domain base set to use the mapper
@@ -91,9 +92,9 @@ muc_mapper_domain_base = "jitsi.example.com";
-- 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
--"offline"; -- Store offline messages
--"c2s"; -- Handle client connections
--"s2s"; -- Handle server-to-server connections
}
-- Disable account creation by default, for security
@@ -110,7 +111,7 @@ ssl = {
-- Force clients to use encrypted connections? This option will
-- prevent clients from authenticating unless they are using encryption.
-- c2s_require_encryption = true
--c2s_require_encryption = true
-- Force certificate authentication for server-to-server connections?
-- This provides ideal security, but requires servers you communicate
@@ -118,7 +119,7 @@ ssl = {
-- NOTE: Your version of LuaSec must support certificate verification!
-- For more information see http://prosody.im/doc/s2s#security
-- s2s_secure_auth = false
--s2s_secure_auth = false
-- Many servers don't support encryption or have invalid or self-signed
-- certificates. You can list domains here that will not be required to
@@ -141,7 +142,6 @@ pidfile = "/var/run/prosody/prosody.pid"
-- server please see http://prosody.im/doc/modules/mod_auth_internal_hashed
-- for information about using the hashed backend.
-- authentication = "internal_plain"
authentication = "internal_hashed"
-- Select the storage backend to use. By default Prosody uses flat files
@@ -159,9 +159,9 @@ authentication = "internal_hashed"
-- Logging configuration
-- For advanced logging see http://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";
info = "/var/log/prosody/prosody.log"; -- Change 'info' to 'debug' for verbose logging
error = "/var/log/prosody/prosody.err";
"*syslog";
}
----------- Virtual hosts -----------
@@ -171,25 +171,25 @@ log = {
--VirtualHost "localhost"
VirtualHost "jitsi.example.com"
-- enabled = false -- Remove this line to enable this host
authentication = "anonymous"
-- 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 = "/var/lib/prosody/jitsi.example.com.key";
certificate = "/var/lib/prosody/jitsi.example.com.crt";
}
-- enabled = false -- Remove this line to enable this host
authentication = "anonymous"
-- 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 = "/var/lib/prosody/jitsi.example.com.key";
certificate = "/var/lib/prosody/jitsi.example.com.crt";
}
c2s_require_encryption = false
c2s_require_encryption = false
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"
ssl = {
key = "/var/lib/prosody/auth.jitsi.example.com.key";
certificate = "/var/lib/prosody/auth.jitsi.example.com.crt";
}
authentication = "internal_hashed"
------ Components ------
-- You can specify components to add hosts that provide special services,
@@ -209,7 +209,7 @@ VirtualHost "auth.jitsi.example.com"
-- see: http://prosody.im/doc/components#adding_an_external_component
--
--Component "gateway.example.com"
-- component_secret = "password"
-- component_secret = "password"
Component "conference.jitsi.example.com" "muc"
modules_enabled = { "muc_domain_mapper" }

View File

@@ -34,63 +34,64 @@ component_ports = { 5347 }
-- Documentation on modules can be found at: http://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
"posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
-- 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
"posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
-- Not essential, but recommended
"private"; -- Private XML storage (for room bookmarks, etc.)
"vcard"; -- Allow users to set vCards
-- Not essential, but recommended
"private"; -- Private XML storage (for room bookmarks, etc.)
"vcard"; -- Allow users to set vCards
-- These are commented by default as they have a performance impact
--"privacy"; -- Support privacy lists
"compression"; -- Stream compression (requires the lua-zlib package installed)
-- These are commented by default as they have a performance impact
--"privacy"; -- Support privacy lists
"compression"; -- Stream compression (requires the lua-zlib package installed)
-- 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
"pep"; -- Enables users to publish their mood, activity, playing music and more
"register"; -- Allow users to register on this server using a client and change passwords
-- 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
"pep"; -- Enables users to publish their mood, activity, playing music and more
"register"; -- Allow users to register on this server using a client and change passwords
-- 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
-- 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"
--"http_files"; -- Serve static files from a directory over HTTP
-- HTTP modules
"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
--"http_files"; -- Serve static files from a directory over HTTP
-- Other specific functionality
--"groups"; -- Shared roster support
--"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.
-- jitsi
"smacks";
"carbons";
"mam";
"lastactivity";
"offline";
"pubsub";
"adhoc";
"websocket";
"http_altconnect";
-- Other specific functionality
--"groups"; -- Shared roster support
--"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.
-- jitsi
"smacks";
"carbons";
"mam";
"lastactivity";
"offline";
"pubsub";
"adhoc";
"websocket";
"http_altconnect";
}
-- 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
--"offline"; -- Store offline messages
--"c2s"; -- Handle client connections
--"s2s"; -- Handle server-to-server connections
}
-- Disable account creation by default, for security
@@ -107,7 +108,7 @@ ssl = {
-- Force clients to use encrypted connections? This option will
-- prevent clients from authenticating unless they are using encryption.
-- c2s_require_encryption = true
--c2s_require_encryption = true
-- Force certificate authentication for server-to-server connections?
-- This provides ideal security, but requires servers you communicate
@@ -115,7 +116,7 @@ ssl = {
-- NOTE: Your version of LuaSec must support certificate verification!
-- For more information see http://prosody.im/doc/s2s#security
-- s2s_secure_auth = false
--s2s_secure_auth = false
-- Many servers don't support encryption or have invalid or self-signed
-- certificates. You can list domains here that will not be required to
@@ -138,7 +139,6 @@ pidfile = "/var/run/prosody/prosody.pid"
-- server please see http://prosody.im/doc/modules/mod_auth_internal_hashed
-- for information about using the hashed backend.
-- authentication = "internal_plain"
authentication = "internal_hashed"
-- Select the storage backend to use. By default Prosody uses flat files
@@ -156,9 +156,9 @@ authentication = "internal_hashed"
-- Logging configuration
-- For advanced logging see http://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";
info = "/var/log/prosody/prosody.log"; -- Change 'info' to 'debug' for verbose logging
error = "/var/log/prosody/prosody.err";
"*syslog";
}
----------- Virtual hosts -----------
@@ -168,25 +168,25 @@ log = {
--VirtualHost "localhost"
VirtualHost "jitsi.example.com"
-- enabled = false -- Remove this line to enable this host
authentication = "anonymous"
-- 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 = "/var/lib/prosody/jitsi.example.com.key";
certificate = "/var/lib/prosody/jitsi.example.com.crt";
}
-- enabled = false -- Remove this line to enable this host
authentication = "anonymous"
-- 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 = "/var/lib/prosody/jitsi.example.com.key";
certificate = "/var/lib/prosody/jitsi.example.com.crt";
}
c2s_require_encryption = false
c2s_require_encryption = false
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"
ssl = {
key = "/var/lib/prosody/auth.jitsi.example.com.key";
certificate = "/var/lib/prosody/auth.jitsi.example.com.crt";
}
authentication = "internal_hashed"
------ Components ------
-- You can specify components to add hosts that provide special services,
@@ -206,7 +206,7 @@ VirtualHost "auth.jitsi.example.com"
-- see: http://prosody.im/doc/components#adding_an_external_component
--
--Component "gateway.example.com"
-- component_secret = "password"
-- component_secret = "password"
Component "conference.jitsi.example.com" "muc"

View File

@@ -24,4 +24,9 @@ JICOFO_AUTH_PASSWORD=$JICOFO_PASSWORD
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"
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

@@ -6,48 +6,48 @@ 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" }
{ 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
-- 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";
--"token_verification";
}
admins = { "focus@auth.meet.example.com" }
muc_room_locking = false
@@ -58,7 +58,7 @@ Component "conference.meet.example.com" "muc"
Component "internal.auth.meet.example.com" "muc"
storage = "memory"
modules_enabled = {
"ping";
"ping";
}
admins = { "focus@auth.meet.example.com", "jvb@auth.meet.example.com" }
@@ -67,7 +67,7 @@ VirtualHost "auth.meet.example.com"
key = "/etc/prosody/certs/auth.meet.example.com.key";
certificate = "/etc/prosody/certs/auth.meet.example.com.crt";
}
authentication = "internal_plain"
authentication = "internal_hashed"
Component "focus.meet.example.com"
component_secret = "jicofo_secret_test"
@@ -75,7 +75,6 @@ Component "focus.meet.example.com"
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"
@@ -84,5 +83,5 @@ VirtualHost "recorder.meet.example.com"
modules_enabled = {
"ping";
}
authentication = "internal_plain"
authentication = "internal_hashed"
c2s_require_encryption = false

View File

@@ -13,58 +13,58 @@ network_backend = "epoll"
-- 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
-- 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
-- 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
-- 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
-- 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
-- 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
-- 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.
--"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
@@ -85,7 +85,6 @@ s2s_require_encryption = true
s2s_secure_auth = false
-- Required for init scripts and prosodyctl
pidfile = "/var/run/prosody/prosody.pid"
@@ -99,13 +98,12 @@ 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
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"

View File

@@ -15,6 +15,10 @@ 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"
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 \
"

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 KiB

View File

@@ -3,7 +3,7 @@
<!--#include virtual="head.html" -->
<meta charset="utf-8">
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<meta name="theme-color" content="#2A3A4B">
<!--#include virtual="base.html" -->

View File

@@ -168,6 +168,13 @@ var interfaceConfig = {
REMOTE_THUMBNAIL_RATIO: 1, // 1:1
SETTINGS_SECTIONS: [ 'devices', 'language', 'moderator', 'profile', 'calendar' ],
/**
* Specify which sharing features should be displayed. If the value is not set
* all sharing features will be shown. You can set [] to disable all.
*/
// SHARING_FEATURES: ['email', 'url', 'dial-in', 'embed'],
SHOW_BRAND_WATERMARK: false,
/**
@@ -191,23 +198,16 @@ var interfaceConfig = {
TOOLBAR_ALWAYS_VISIBLE: false,
/**
* The name of the toolbar buttons to display in the toolbar, including the
* "More actions" menu. If present, the button will display. Exceptions are
* "livestreaming" and "recording" which also require being a moderator and
* some values in config.js to be enabled. Also, the "profile" button will
* not display for users with a JWT.
* Notes:
* - it's impossible to choose which buttons go in the "More actions" menu
* - it's impossible to control the placement of buttons
* - 'desktop' controls the "Share your screen" button
* DEPRECATED!
* This config was moved to config.js as `toolbarButtons`.
*/
TOOLBAR_BUTTONS: [
'microphone', 'camera', 'closedcaptions', 'desktop', 'embedmeeting', 'fullscreen',
'fodeviceselection', 'hangup', 'profile', 'chat', 'recording',
'livestreaming', 'etherpad', 'sharedvideo', 'settings', 'raisehand',
'videoquality', 'filmstrip', 'invite', 'feedback', 'stats', 'shortcuts',
'tileview', 'videobackgroundblur', 'download', 'help', 'mute-everyone', 'security'
],
// TOOLBAR_BUTTONS: [
// 'microphone', 'camera', 'closedcaptions', 'desktop', 'embedmeeting', 'fullscreen',
// 'fodeviceselection', 'hangup', 'profile', 'chat', 'recording',
// 'livestreaming', 'etherpad', 'sharedvideo', 'settings', 'raisehand',
// 'videoquality', 'filmstrip', 'invite', 'feedback', 'stats', 'shortcuts',
// 'tileview', 'select-background', 'download', 'help', 'mute-everyone', 'mute-video-everyone', 'security'
// ],
TOOLBAR_TIMEOUT: 4000,

View File

@@ -3,7 +3,7 @@ workspace 'jitsi-meet'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
install! 'cocoapods', :deterministic_uuids => false
target 'jitsi-meet' do
target 'JitsiMeet' do
project 'app/app.xcodeproj'
pod 'Firebase/Analytics', '~> 6.33.0'
@@ -11,7 +11,7 @@ target 'jitsi-meet' do
pod 'Firebase/DynamicLinks', '~> 6.33.0'
end
target 'JitsiMeet' do
target 'JitsiMeetSDK' do
project 'sdk/sdk.xcodeproj'
# React Native and its dependencies
@@ -58,21 +58,21 @@ target 'JitsiMeet' do
pod 'react-native-calendar-events', :path => '../node_modules/react-native-calendar-events'
pod 'react-native-keep-awake', :path => '../node_modules/react-native-keep-awake'
pod 'react-native-netinfo', :path => '../node_modules/@react-native-community/netinfo'
pod 'react-native-splash-screen', :path => '../node_modules/react-native-splash-screen'
pod 'react-native-webview', :path => '../node_modules/react-native-webview'
pod 'react-native-webrtc', :path => '../node_modules/react-native-webrtc'
pod 'BVLinearGradient', :path => '../node_modules/react-native-linear-gradient'
pod 'RNCAsyncStorage', :path => '../node_modules/@react-native-community/async-storage'
pod 'RNCAsyncStorage', :path => '../node_modules/@react-native-async-storage/async-storage'
pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info'
pod 'RNGoogleSignin', :path => '../node_modules/@react-native-community/google-signin'
pod 'RNSound', :path => '../node_modules/react-native-sound'
pod 'RNSVG', :path => '../node_modules/react-native-svg'
pod 'RNWatch', :path => '../node_modules/react-native-watch-connectivity'
pod 'RNDefaultPreference', :path => '../node_modules/react-native-default-preference'
pod 'react-native-splash-screen', :path => '../node_modules/react-native-splash-screen'
# Native pod dependencies
#
pod 'Amplitude-iOS', '~> 4.0.4'
pod 'CocoaLumberjack', '~>3.5.3'
pod 'ObjectiveDropboxOfficial', '~> 3.9.4'

View File

@@ -1,5 +1,4 @@
PODS:
- Amplitude-iOS (4.0.4)
- AppAuth (1.2.0):
- AppAuth/Core (= 1.2.0)
- AppAuth/ExternalUserAgent (= 1.2.0)
@@ -293,7 +292,7 @@ PODS:
- React
- react-native-splash-screen (3.2.0):
- React
- react-native-webrtc (1.87.1):
- react-native-webrtc (1.89.1):
- React-Core
- react-native-webview (11.0.2):
- React-Core
@@ -351,10 +350,12 @@ PODS:
- React-jsi (= 0.61.5-jitsi.2)
- ReactCommon/jscallinvoker (= 0.61.5-jitsi.2)
- ReactCommon/turbomodule/core (= 0.61.5-jitsi.2)
- RNCAsyncStorage (1.3.4):
- RNCAsyncStorage (1.13.2):
- React
- RNDefaultPreference (1.4.2):
- React
- RNDeviceInfo (8.0.0):
- React-Core
- RNGoogleSignin (3.0.1):
- GoogleSignIn (~> 5.0.0)
- React
@@ -363,14 +364,13 @@ PODS:
- RNSound/Core (= 0.11.0)
- RNSound/Core (0.11.0):
- React
- RNSVG (10.1.0):
- RNSVG (12.1.0):
- React
- RNWatch (0.4.3):
- React
- Yoga (1.14.0)
DEPENDENCIES:
- Amplitude-iOS (~> 4.0.4)
- BVLinearGradient (from `../node_modules/react-native-linear-gradient`)
- CocoaLumberjack (~> 3.5.3)
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
@@ -410,8 +410,9 @@ DEPENDENCIES:
- React-RCTText (from `../node_modules/react-native/Libraries/Text`)
- 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`)"
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
- RNDefaultPreference (from `../node_modules/react-native-default-preference`)
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- "RNGoogleSignin (from `../node_modules/@react-native-community/google-signin`)"
- RNSound (from `../node_modules/react-native-sound`)
- RNSVG (from `../node_modules/react-native-svg`)
@@ -420,7 +421,6 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- Amplitude-iOS
- AppAuth
- boost-for-react-native
- CocoaLumberjack
@@ -507,9 +507,11 @@ EXTERNAL SOURCES:
ReactCommon:
:path: "../node_modules/react-native/ReactCommon"
RNCAsyncStorage:
:path: "../node_modules/@react-native-community/async-storage"
:path: "../node_modules/@react-native-async-storage/async-storage"
RNDefaultPreference:
:path: "../node_modules/react-native-default-preference"
RNDeviceInfo:
:path: "../node_modules/react-native-device-info"
RNGoogleSignin:
:path: "../node_modules/@react-native-community/google-signin"
RNSound:
@@ -522,7 +524,6 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/yoga"
SPEC CHECKSUMS:
Amplitude-iOS: 2ad4d7270c99186236c1272a3a9425463b1ae1a7
AppAuth: bce82c76043657c99d91e7882e8a9e1a93650cd4
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
@@ -562,7 +563,7 @@ SPEC CHECKSUMS:
react-native-keep-awake: eba3137546b10003361b37c761f6c429b59814ae
react-native-netinfo: 8d8db463bcc5db66a8ac5c48a7d86beb3b92f61a
react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865
react-native-webrtc: 40eca4cac200fda34fb843da07e3402211bbbd10
react-native-webrtc: ccb0c21eb4fb04326648fbdb4a5d49977e2cf274
react-native-webview: b2542d6fd424bcc3e3b2ec5f854f0abb4ec86c87
React-RCTActionSheet: bcbc311dc3b47bc8efb2737ff0940239a45789a9
React-RCTAnimation: 65f61080ce632f6dea23d52e354ffac9948396c6
@@ -574,14 +575,15 @@ SPEC CHECKSUMS:
React-RCTText: 4f1b99f228278d2a5e9008eced8dc9c974c4a270
React-RCTVibration: c1041024893fdfdb8371e7c720c437751b711676
ReactCommon: 18014e1d98dbeb9141e935cfe35fc93bd511ffb6
RNCAsyncStorage: 8e31405a9f12fbf42c2bb330e4560bfd79c18323
RNCAsyncStorage: bc2f81cc1df90c267ce9ed30bb2dbc93b945a8ee
RNDefaultPreference: 56a405ce61033ac77b95004dccd7ac54c2eb50d1
RNDeviceInfo: 72ded653ce636b3f03571e90bed99309a714944e
RNGoogleSignin: 39336070b35fc4cea6a98cf111e00480317be0ae
RNSound: c980916b596cc15c8dcd2f6ecd3b13c4881dbe20
RNSVG: 069864be08c9fe065a2cf7e63656a34c78653c99
RNSVG: ce9d996113475209013317e48b05c21ee988d42e
RNWatch: a5320c959c75e72845c07985f3e935e58998f1d3
Yoga: 96b469c5e81ff51b917b92e8c3390642d4ded30c
PODFILE CHECKSUM: f6626cd705333112182cedbe175ae2f9006e8874
PODFILE CHECKSUM: 5be5132e41831a98362eeed760558227a4df89ae
COCOAPODS: 1.10.0
COCOAPODS: 1.10.1

View File

@@ -8,6 +8,10 @@
<string>applinks:beta.meet.jit.si</string>
<string>applinks:meet.jit.si</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.jitsi.meet.appgroup</string>
</array>
<key>com.apple.developer.siri</key>
<true/>
</dict>

View File

@@ -7,8 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
0B26BE6E1EC5BC3C00EEFB41 /* JitsiMeet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B26BE6D1EC5BC3C00EEFB41 /* JitsiMeet.framework */; };
0B26BE6F1EC5BC3C00EEFB41 /* JitsiMeet.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0B26BE6D1EC5BC3C00EEFB41 /* JitsiMeet.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
0B412F1F1EDEE6E800B1A0A6 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B412F1E1EDEE6E800B1A0A6 /* ViewController.m */; };
0B412F211EDEE95300B1A0A6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0B412F201EDEE95300B1A0A6 /* Main.storyboard */; };
0B5418471F7C5D8C00A2DD86 /* MeetingRowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B5418461F7C5D8C00A2DD86 /* MeetingRowController.swift */; };
@@ -25,10 +23,18 @@
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
695AF3ED6F686F9C5EE40F9A /* libPods-jitsi-meet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 489E8EFE2C720D10F5961AEF /* libPods-jitsi-meet.a */; };
4E51B75E25E4115F0038575A /* DarwinNotificationCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E51B75D25E4115F0038575A /* DarwinNotificationCenter.m */; };
4EC49BB725BEDAC100E76218 /* ReplayKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4EC49B8625BED71300E76218 /* ReplayKit.framework */; };
4EC49BBB25BEDAC100E76218 /* SampleHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EC49BBA25BEDAC100E76218 /* SampleHandler.m */; };
4EC49BBF25BEDAC100E76218 /* JitsiMeetBroadcast Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 4EC49BB625BEDAC100E76218 /* JitsiMeetBroadcast Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
4EC49BCB25BEDB6400E76218 /* SocketConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EC49BCA25BEDB6400E76218 /* SocketConnection.m */; };
4EC49BD125BF19CF00E76218 /* SampleUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EC49BD025BF19CF00E76218 /* SampleUploader.m */; };
55BEDABDA92D47D399A70A5E /* libPods-JitsiMeet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D878B07B3FBD6E305EAA6B27 /* libPods-JitsiMeet.a */; };
DE050389256E904600DEE3A5 /* WebRTC.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = DE050388256E904600DEE3A5 /* WebRTC.xcframework */; };
DE05038A256E904600DEE3A5 /* WebRTC.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DE050388256E904600DEE3A5 /* WebRTC.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
DE4C456121DE1E4E00EA0709 /* FIRUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = DE4C455F21DE1E4E00EA0709 /* FIRUtilities.m */; };
DEA9F289258A6EA800D4CD74 /* JitsiMeetSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEA9F288258A6EA800D4CD74 /* JitsiMeetSDK.framework */; };
DEA9F28A258A6EA800D4CD74 /* JitsiMeetSDK.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DEA9F288258A6EA800D4CD74 /* JitsiMeetSDK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
E588011722789D43008B0561 /* JitsiMeetContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = E58801132278944E008B0561 /* JitsiMeetContext.swift */; };
E5C97B63227A1EB400199214 /* JitsiMeetCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5C97B62227A1EB400199214 /* JitsiMeetCommands.swift */; };
/* End PBXBuildFile section */
@@ -48,6 +54,13 @@
remoteGlobalIDString = 0BEA5C241F7B8F73000D0AB4;
remoteInfo = JitsiMeetCompanion;
};
4EC49BBD25BEDAC100E76218 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 4EC49BB525BEDAC100E76218;
remoteInfo = "JitsiMeetBroadcast Extension";
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -57,8 +70,8 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
DEA9F28A258A6EA800D4CD74 /* JitsiMeetSDK.framework in Embed Frameworks */,
DE05038A256E904600DEE3A5 /* WebRTC.xcframework in Embed Frameworks */,
0B26BE6F1EC5BC3C00EEFB41 /* JitsiMeet.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@@ -85,6 +98,17 @@
name = "Embed Watch Content";
runOnlyForDeploymentPostprocessing = 0;
};
4EC49B9025BED71300E76218 /* Embed App Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
4EC49BBF25BEDAC100E76218 /* JitsiMeetBroadcast Extension.appex in Embed App Extensions */,
);
name = "Embed App Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
@@ -115,14 +139,29 @@
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
4670A512A688E2DC34528282 /* Pods-jitsi-meet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-jitsi-meet.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-jitsi-meet/Pods-jitsi-meet.debug.xcconfig"; sourceTree = "<group>"; };
489E8EFE2C720D10F5961AEF /* libPods-jitsi-meet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-jitsi-meet.a"; sourceTree = BUILT_PRODUCTS_DIR; };
4E51B75C25E4115F0038575A /* DarwinNotificationCenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DarwinNotificationCenter.h; sourceTree = "<group>"; };
4E51B75D25E4115F0038575A /* DarwinNotificationCenter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DarwinNotificationCenter.m; sourceTree = "<group>"; };
4EC49B8625BED71300E76218 /* ReplayKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReplayKit.framework; path = System/Library/Frameworks/ReplayKit.framework; sourceTree = SDKROOT; };
4EC49BB625BEDAC100E76218 /* JitsiMeetBroadcast Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "JitsiMeetBroadcast Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
4EC49BB925BEDAC100E76218 /* SampleHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SampleHandler.h; sourceTree = "<group>"; };
4EC49BBA25BEDAC100E76218 /* SampleHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleHandler.m; sourceTree = "<group>"; };
4EC49BBC25BEDAC100E76218 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4EC49BC925BEDB6400E76218 /* SocketConnection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SocketConnection.h; sourceTree = "<group>"; };
4EC49BCA25BEDB6400E76218 /* SocketConnection.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SocketConnection.m; sourceTree = "<group>"; };
4EC49BCF25BF19CF00E76218 /* SampleUploader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SampleUploader.h; sourceTree = "<group>"; };
4EC49BD025BF19CF00E76218 /* SampleUploader.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleUploader.m; sourceTree = "<group>"; };
4EC49BDB25BF280A00E76218 /* extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = extension.entitlements; sourceTree = "<group>"; };
609CB2080B75F75A89923F3D /* Pods-JitsiMeet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.debug.xcconfig"; sourceTree = "<group>"; };
B3B083EB1D4955FF0069CEE7 /* app.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = app.entitlements; sourceTree = "<group>"; };
D878B07B3FBD6E305EAA6B27 /* libPods-JitsiMeet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-JitsiMeet.a"; sourceTree = BUILT_PRODUCTS_DIR; };
DE050388256E904600DEE3A5 /* WebRTC.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = WebRTC.xcframework; path = "../../node_modules/react-native-webrtc/apple/WebRTC.xcframework"; sourceTree = "<group>"; };
DE4C455F21DE1E4E00EA0709 /* FIRUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FIRUtilities.m; sourceTree = "<group>"; };
DE4C456021DE1E4E00EA0709 /* FIRUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FIRUtilities.h; sourceTree = "<group>"; };
DEA9F288258A6EA800D4CD74 /* JitsiMeetSDK.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = JitsiMeetSDK.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DEFDBBDB25656E3B00344B23 /* WebRTC.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = WebRTC.xcframework; path = "../../node_modules/react-native-webrtc/ios/WebRTC.xcframework"; sourceTree = "<group>"; };
E58801132278944E008B0561 /* JitsiMeetContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JitsiMeetContext.swift; sourceTree = "<group>"; };
E5C97B62227A1EB400199214 /* JitsiMeetCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JitsiMeetCommands.swift; sourceTree = "<group>"; };
FC040BBED70876444D89E91C /* Pods-JitsiMeet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.release.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -137,9 +176,9 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0B26BE6E1EC5BC3C00EEFB41 /* JitsiMeet.framework in Frameworks */,
695AF3ED6F686F9C5EE40F9A /* libPods-jitsi-meet.a in Frameworks */,
DE050389256E904600DEE3A5 /* WebRTC.xcframework in Frameworks */,
DEA9F289258A6EA800D4CD74 /* JitsiMeetSDK.framework in Frameworks */,
55BEDABDA92D47D399A70A5E /* libPods-JitsiMeet.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -150,17 +189,27 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
4EC49BB325BEDAC100E76218 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
4EC49BB725BEDAC100E76218 /* ReplayKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
0B26BE711EC5BC4D00EEFB41 /* Frameworks */ = {
isa = PBXGroup;
children = (
DEA9F288258A6EA800D4CD74 /* JitsiMeetSDK.framework */,
DE050388256E904600DEE3A5 /* WebRTC.xcframework */,
0B26BE6D1EC5BC3C00EEFB41 /* JitsiMeet.framework */,
DEFDBBDB25656E3B00344B23 /* WebRTC.xcframework */,
0BD6B4361EF82A6B00D1F4CD /* WebRTC.framework */,
489E8EFE2C720D10F5961AEF /* libPods-jitsi-meet.a */,
D878B07B3FBD6E305EAA6B27 /* libPods-JitsiMeet.a */,
4EC49B8625BED71300E76218 /* ReplayKit.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -212,11 +261,31 @@
path = src;
sourceTree = "<group>";
};
4EC49BB825BEDAC100E76218 /* JitsiMeetBroadcast Extension */ = {
isa = PBXGroup;
children = (
4EC49BDB25BF280A00E76218 /* extension.entitlements */,
4EC49BB925BEDAC100E76218 /* SampleHandler.h */,
4EC49BBA25BEDAC100E76218 /* SampleHandler.m */,
4EC49BC925BEDB6400E76218 /* SocketConnection.h */,
4EC49BCA25BEDB6400E76218 /* SocketConnection.m */,
4EC49BCF25BF19CF00E76218 /* SampleUploader.h */,
4EC49BD025BF19CF00E76218 /* SampleUploader.m */,
4EC49BBC25BEDAC100E76218 /* Info.plist */,
4E51B75C25E4115F0038575A /* DarwinNotificationCenter.h */,
4E51B75D25E4115F0038575A /* DarwinNotificationCenter.m */,
);
name = "JitsiMeetBroadcast Extension";
path = "broadcast-extension";
sourceTree = "<group>";
};
5E96ADD5E49F3B3822EF9A52 /* Pods */ = {
isa = PBXGroup;
children = (
4670A512A688E2DC34528282 /* Pods-jitsi-meet.debug.xcconfig */,
09AA3B93E4CC62D84B424690 /* Pods-jitsi-meet.release.xcconfig */,
609CB2080B75F75A89923F3D /* Pods-JitsiMeet.debug.xcconfig */,
FC040BBED70876444D89E91C /* Pods-JitsiMeet.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
@@ -230,6 +299,7 @@
13B07FAE1A68108700A75B9A /* src */,
5E96ADD5E49F3B3822EF9A52 /* Pods */,
0BEA5C261F7B8F73000D0AB4 /* Watch app */,
4EC49BB825BEDAC100E76218 /* JitsiMeetBroadcast Extension */,
0BEA5C351F7B8F73000D0AB4 /* WatchKit extension */,
);
indentWidth = 2;
@@ -242,6 +312,7 @@
13B07F961A680F5B00A75B9A /* jitsi-meet.app */,
0BEA5C251F7B8F73000D0AB4 /* JitsiMeetCompanion.app */,
0BEA5C311F7B8F73000D0AB4 /* JitsiMeetCompanion Extension.appex */,
4EC49BB625BEDAC100E76218 /* JitsiMeetBroadcast Extension.appex */,
);
name = Products;
sourceTree = "<group>";
@@ -284,9 +355,9 @@
productReference = 0BEA5C311F7B8F73000D0AB4 /* JitsiMeetCompanion Extension.appex */;
productType = "com.apple.product-type.watchkit2-extension";
};
13B07F861A680F5B00A75B9A /* jitsi-meet */ = {
13B07F861A680F5B00A75B9A /* JitsiMeet */ = {
isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "jitsi-meet" */;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "JitsiMeet" */;
buildPhases = (
B6607F42A5CF0C76E98929E2 /* [CP] Check Pods Manifest.lock */,
0BBA83C41EC9F7600075A103 /* Run React packager */,
@@ -299,17 +370,36 @@
DE11877A21EE09640078D059 /* Setup Google reverse URL handler */,
DE4F6D6E22005C0400DE699E /* Setup Dropbox */,
0BEA5C491F7B8F73000D0AB4 /* Embed Watch Content */,
4EC49B9025BED71300E76218 /* Embed App Extensions */,
);
buildRules = (
);
dependencies = (
0BEA5C401F7B8F73000D0AB4 /* PBXTargetDependency */,
4EC49BBE25BEDAC100E76218 /* PBXTargetDependency */,
);
name = "jitsi-meet";
name = JitsiMeet;
productName = "Jitsi Meet";
productReference = 13B07F961A680F5B00A75B9A /* jitsi-meet.app */;
productType = "com.apple.product-type.application";
};
4EC49BB525BEDAC100E76218 /* JitsiMeetBroadcast Extension */ = {
isa = PBXNativeTarget;
buildConfigurationList = 4EC49BC025BEDAC100E76218 /* Build configuration list for PBXNativeTarget "JitsiMeetBroadcast Extension" */;
buildPhases = (
4EC49BB225BEDAC100E76218 /* Sources */,
4EC49BB325BEDAC100E76218 /* Frameworks */,
4EC49BB425BEDAC100E76218 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = "JitsiMeetBroadcast Extension";
productName = "JitsiMeetBroadcast Extension";
productReference = 4EC49BB625BEDAC100E76218 /* JitsiMeetBroadcast Extension.appex */;
productType = "com.apple.product-type.app-extension";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@@ -330,8 +420,6 @@
ProvisioningStyle = Automatic;
};
13B07F861A680F5B00A75B9A = {
DevelopmentTeam = FC967L3QRG;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.SafariKeychain = {
enabled = 1;
@@ -341,6 +429,9 @@
};
};
};
4EC49BB525BEDAC100E76218 = {
CreatedOnToolsVersion = 12.2;
};
};
};
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "app" */;
@@ -356,9 +447,10 @@
projectDirPath = "";
projectRoot = "";
targets = (
13B07F861A680F5B00A75B9A /* jitsi-meet */,
13B07F861A680F5B00A75B9A /* JitsiMeet */,
0BEA5C241F7B8F73000D0AB4 /* JitsiMeetCompanion */,
0BEA5C301F7B8F73000D0AB4 /* JitsiMeetCompanion Extension */,
4EC49BB525BEDAC100E76218 /* JitsiMeetBroadcast Extension */,
);
};
/* End PBXProject section */
@@ -391,6 +483,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
4EC49BB425BEDAC100E76218 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
@@ -437,7 +536,7 @@
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-jitsi-meet-checkManifestLockResult.txt",
"$(DERIVED_FILE_DIR)/Pods-JitsiMeet-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@@ -526,6 +625,17 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
4EC49BB225BEDAC100E76218 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4EC49BCB25BEDB6400E76218 /* SocketConnection.m in Sources */,
4EC49BBB25BEDAC100E76218 /* SampleHandler.m in Sources */,
4E51B75E25E4115F0038575A /* DarwinNotificationCenter.m in Sources */,
4EC49BD125BF19CF00E76218 /* SampleUploader.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
@@ -539,6 +649,11 @@
target = 0BEA5C241F7B8F73000D0AB4 /* JitsiMeetCompanion */;
targetProxy = 0BEA5C3F1F7B8F73000D0AB4 /* PBXContainerItemProxy */;
};
4EC49BBE25BEDAC100E76218 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 4EC49BB525BEDAC100E76218 /* JitsiMeetBroadcast Extension */;
targetProxy = 4EC49BBD25BEDAC100E76218 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
@@ -707,11 +822,12 @@
};
13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 4670A512A688E2DC34528282 /* Pods-jitsi-meet.debug.xcconfig */;
baseConfigurationReference = 609CB2080B75F75A89923F3D /* Pods-JitsiMeet.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconDebug;
CODE_SIGN_ENTITLEMENTS = app.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = NO;
@@ -736,11 +852,12 @@
};
13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 09AA3B93E4CC62D84B424690 /* Pods-jitsi-meet.release.xcconfig */;
baseConfigurationReference = FC040BBED70876444D89E91C /* Pods-JitsiMeet.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconRelease;
CODE_SIGN_ENTITLEMENTS = app.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = FC967L3QRG;
@@ -762,6 +879,70 @@
};
name = Release;
};
4EC49BC125BEDAC100E76218 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = "broadcast-extension/extension.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = FC967L3QRG;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "broadcast-extension/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet.broadcast.extension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
4EC49BC225BEDAC100E76218 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = "broadcast-extension/extension.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = FC967L3QRG;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "broadcast-extension/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet.broadcast.extension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
83CBBA201A601CBA00E9B192 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -897,7 +1078,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "jitsi-meet" */ = {
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "JitsiMeet" */ = {
isa = XCConfigurationList;
buildConfigurations = (
13B07F941A680F5B00A75B9A /* Debug */,
@@ -906,6 +1087,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
4EC49BC025BEDAC100E76218 /* Build configuration list for PBXNativeTarget "JitsiMeetBroadcast Extension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
4EC49BC125BEDAC100E76218 /* Debug */,
4EC49BC225BEDAC100E76218 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "app" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

@@ -15,8 +15,8 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0BD906E41EC0C00300C8C18E"
BuildableName = "JitsiMeet.framework"
BlueprintName = "JitsiMeet"
BuildableName = "JitsiMeetSDK.framework"
BlueprintName = "JitsiMeetSDK"
ReferencedContainer = "container:../sdk/sdk.xcodeproj">
</BuildableReference>
</BuildActionEntry>
@@ -30,7 +30,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "jitsi-meet.app"
BlueprintName = "jitsi-meet"
BlueprintName = "JitsiMeet"
ReferencedContainer = "container:app.xcodeproj">
</BuildableReference>
</BuildActionEntry>
@@ -46,7 +46,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "jitsi-meet.app"
BlueprintName = "jitsi-meet"
BlueprintName = "JitsiMeet"
ReferencedContainer = "container:app.xcodeproj">
</BuildableReference>
</MacroExpansion>
@@ -69,7 +69,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "jitsi-meet.app"
BlueprintName = "jitsi-meet"
BlueprintName = "JitsiMeet"
ReferencedContainer = "container:app.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
@@ -86,7 +86,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "jitsi-meet.app"
BlueprintName = "jitsi-meet"
BlueprintName = "JitsiMeet"
ReferencedContainer = "container:app.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>

View File

@@ -0,0 +1,31 @@
/*
* Copyright @ 2021-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
extern NSNotificationName const kBroadcastStartedNotification;
extern NSNotificationName const kBroadcastStoppedNotification;
@interface DarwinNotificationCenter: NSObject
+ (instancetype)sharedInstance;
- (void)postNotificationWithName:(NSNotificationName)name;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,50 @@
/*
* Copyright @ 2021-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "DarwinNotificationCenter.h"
NSNotificationName const kBroadcastStartedNotification = @"iOS_BroadcastStarted";
NSNotificationName const kBroadcastStoppedNotification = @"iOS_BroadcastStopped";
@implementation DarwinNotificationCenter {
CFNotificationCenterRef _notificationCenter;
}
+ (instancetype)sharedInstance {
static DarwinNotificationCenter *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (instancetype)init {
self = [super init];
if (self) {
_notificationCenter = CFNotificationCenterGetDarwinNotifyCenter();
}
return self;
}
- (void)postNotificationWithName:(NSString*)name {
CFNotificationCenterPostNotification(_notificationCenter, (__bridge CFStringRef)name, NULL, NULL, true);
}
@end

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>JitsiMeet Broadcast Extension</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>21.0.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.broadcast-services-upload</string>
<key>NSExtensionPrincipalClass</key>
<string>SampleHandler</string>
<key>RPBroadcastProcessMode</key>
<string>RPBroadcastProcessModeSampleBuffer</string>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,21 @@
/*
* Copyright @ 2021-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <ReplayKit/ReplayKit.h>
@interface SampleHandler : RPBroadcastSampleHandler
@end

View File

@@ -0,0 +1,123 @@
/*
* Copyright @ 2021-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "SampleHandler.h"
#import "SocketConnection.h"
#import "SampleUploader.h"
#import "DarwinNotificationCenter.h"
@interface SampleHandler ()
@property (nonatomic, retain) SocketConnection *clientConnection;
@property (nonatomic, retain) SampleUploader *uploader;
@end
@implementation SampleHandler
- (instancetype)init {
self = [super init];
if (self) {
self.clientConnection = [[SocketConnection alloc] initWithFilePath:self.socketFilePath];
[self setupConnection];
self.uploader = [[SampleUploader alloc] initWithConnection:self.clientConnection];
}
return self;
}
- (void)broadcastStartedWithSetupInfo:(NSDictionary<NSString *,NSObject *> *)setupInfo {
// User has requested to start the broadcast. Setup info from the UI extension can be supplied but optional.
NSLog(@"broadcast started");
[[DarwinNotificationCenter sharedInstance] postNotificationWithName:kBroadcastStartedNotification];
[self openConnection];
}
- (void)broadcastPaused {
// User has requested to pause the broadcast. Samples will stop being delivered.
}
- (void)broadcastResumed {
// User has requested to resume the broadcast. Samples delivery will resume.
}
- (void)broadcastFinished {
// User has requested to finish the broadcast.
[[DarwinNotificationCenter sharedInstance] postNotificationWithName:kBroadcastStoppedNotification];
[self.clientConnection close];
}
- (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType {
static NSUInteger frameCount = 0;
switch (sampleBufferType) {
case RPSampleBufferTypeVideo:
// adjust frame rate by using every third frame
if (++frameCount%3 == 0 && self.uploader.isReady) {
[self.uploader sendSample:sampleBuffer];
}
break;
default:
break;
}
}
// MARK: Private Methods
- (NSString *)socketFilePath {
// the appGroupIdentifier must match the value provided in the app's info.plist for the RTCAppGroupIdentifier key
NSString *appGroupIdentifier = @"group.org.jitsi.meet.appgroup";
NSURL *sharedContainer = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:appGroupIdentifier];
NSString *socketFilePath = [[sharedContainer URLByAppendingPathComponent:@"rtc_SSFD"] path];
return socketFilePath;
}
- (void)setupConnection {
__weak __typeof(self) weakSelf = self;
self.clientConnection.didClose = ^(NSError *error) {
NSLog(@"client connection did close: %@", error);
if (error) {
[weakSelf finishBroadcastWithError:error];
}
else {
NSInteger JMScreenSharingStopped = 10001;
NSError *customError = [NSError errorWithDomain:RPRecordingErrorDomain
code:JMScreenSharingStopped
userInfo:@{NSLocalizedDescriptionKey: @"Screen sharing stopped"}];
[weakSelf finishBroadcastWithError:customError];
}
};
}
- (void)openConnection {
dispatch_queue_t queue = dispatch_queue_create("org.jitsi.meet.broadcast.connectTimer", 0);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), 0.1 * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
BOOL success = [self.clientConnection open];
if (success) {
dispatch_source_cancel(timer);
}
});
dispatch_resume(timer);
}
@end

View File

@@ -0,0 +1,33 @@
/*
* Copyright @ 2021-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <ReplayKit/ReplayKit.h>
NS_ASSUME_NONNULL_BEGIN
@class SocketConnection;
@interface SampleUploader : NSObject
@property (nonatomic, assign, readonly) BOOL isReady;
- (instancetype)initWithConnection:(SocketConnection *)connection;
- (void)sendSample:(CMSampleBufferRef)sampleBuffer;
@end
NS_ASSUME_NONNULL_END

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