Compare commits

...

158 Commits

Author SHA1 Message Date
Saúl Ibarra Corretgé
fbdd1d2f38 settings: fix loading disableCallIntegration 2019-11-08 12:22:41 +01:00
Saúl Ibarra Corretgé
53ebab33b3 android: fix selecting the Bluetooth route
Samsung devices (of course) seem to stick with the earpiece if we first select
Bluetooth but then set speaker to false. Reverse the order to make everyone
happy.

This only applies to the generic and legacy handlers.
2019-11-08 12:22:41 +01:00
Saúl Ibarra Corretgé
a36965e908 android: fix initializing audio device handler modules too early
When ConnectionService is used (the default) we were attaching the handlers too
early, and since attaching them requires that the RNConnectionService module is
loaded, it silently failed. Instead, use the initialize() method, which gets
called after all the Catalyst (aka native) modules have been loaded.
2019-11-08 12:22:41 +01:00
Saúl Ibarra Corretgé
9bf859ee50 android: log a warning if listeners could not be attached 2019-11-08 12:22:41 +01:00
Saúl Ibarra Corretgé
24ff6f58a5 android: make code a bit more readable 2019-11-08 12:22:41 +01:00
Saúl Ibarra Corretgé
6338624095 android,hack: send custom UA to fool spartan nginx config on meet.jit.si 2019-11-07 15:28:04 +01:00
Saúl Ibarra Corretgé
9634d58d4e Merge branch 'master' into mobile-19.4 2019-11-07 08:40:06 +01:00
Saúl Ibarra Corretgé
ad0064993d ios: enable Swift mobule stability for the SDK target
Supersedes: https://github.com/jitsi/jitsi-meet/pull/4818
Fixes: https://github.com/jitsi/jitsi-meet/issues/4812
2019-11-06 18:30:26 +01:00
Saúl Ibarra Corretgé
458d4acd22 ios: use the "new" Xcode build system
It was introduced in Xcode 9 and made the default in Xcode 10. We were forcing
the use of the legacy version, which doesn't support some new features that we
wish to enable, such as building the SDK for distribution.
2019-11-06 18:30:26 +01:00
Saúl Ibarra Corretgé
8ebc99175c ios: set deployment target on Pods to 10.0
Matches the app / SDK deployment target and avoids compilation warnings.
2019-11-06 18:30:26 +01:00
Vlad Piersec
9889cb2b69 Add conference name as fallback for subject 2019-11-06 17:23:18 +01:00
Saúl Ibarra Corretgé
95a6f1355f uri: avoid using String.prototype.normalize
It crashes on Android. Well, on the JSC version React Native uses on Android.

While we could use this fallback only on Android, we have decided to use it
on all mobile platforms for consistency.
2019-11-06 15:37:52 +01:00
Saúl Ibarra Corretgé
191e530071 uri: avoid using String.prototype.normalize
It crashes on Android. Well, on the JSC version React Native uses on Android.

While we could use this fallback only on Android, we have decided to use it
on all mobile platforms for consistency.
2019-11-06 15:37:14 +01:00
Mihai Uscat
ae30d39b4d feat(PromotionalFooter): Implement 2019-11-06 03:29:49 -08:00
Leonard Kim
c354e46846 chore(deps): update lib so newer FF does not need click for gum 2019-11-06 07:47:14 +00:00
Hristo Terezov
5da4e43e50 fix(settings): respect configWhitelist 2019-11-05 02:13:54 -08:00
Hristo Terezov
eae6f7760f fix(configWhitelist): add startWithAudioMuted. 2019-11-05 02:13:54 -08:00
Mihai Uscat
00161212c8 feat(welcome): Add responsive text to go button 2019-11-04 05:48:55 -08:00
Mark Anthony Sison
8976b92842 doc(install): adds cd command to jitsi-meet installation 2019-11-03 19:46:34 +00:00
Vlad Piersec
c3a6a8fb17 Add participants count 2019-10-31 09:08:59 -07:00
Saúl Ibarra Corretgé
fd3fb7ef55 Merge branch 'master' into mobile-19.4 2019-10-31 16:45:37 +01:00
Saúl Ibarra Corretgé
391e5ca483 deps: react-native@0.61.3 2019-10-31 16:44:31 +01:00
Saúl Ibarra Corretgé
36654cb808 rn: disable H.264 on select devices even when not in P2P
iOS 10 crashes, so don't use it there, in any case.
2019-10-31 16:41:08 +01:00
Saúl Ibarra Corretgé
6d16e087d9 rn: add a new advanced settings section
Currently only 2 options are implemented, mainly aimed at helping troubleshoot
audio related problems:

- Disable native call integration (it disables CallKit / ConnectionService)
- Disable P2P
2019-10-31 16:41:08 +01:00
Saúl Ibarra Corretgé
fe90e5aa8f rn,settings: remove top margin 2019-10-31 16:41:08 +01:00
Saúl Ibarra Corretgé
3c22cd8ef4 rn,android: refactor audio device handling module
Separate each implementation (3 as of this writing) into each own "handler"
class.

This should make the code easier to understand, maintain and extend.
2019-10-31 16:41:08 +01:00
Bettenbuk Zoltan
5429b8568e feat: feature flag for invite functionalities 2019-10-29 11:27:25 +01:00
George Politis
0eccaf9a21 bumps ljm@5521a40aa85cb6f128f8a6dad9b72a5646132484 (#4791) 2019-10-24 14:52:38 +02:00
Aaron van Meerten
be0950c1ec multidomain mapper functionality and examples (#4773)
* first pass at mod_muc_domain open source plus example

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

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

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

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

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

2nd we return false if we're in audio only mode, because it's
(obviously) undesirable to have a playable video when in audio only
mode.
2019-09-17 18:18:44 +02:00
George Politis
324a9eba91 minor change in debug log wording 2019-09-17 18:18:44 +02:00
George Politis
fb1ed22c6c ref: Tweak logging logic for thumbnail display mode and tile view. 2019-09-17 18:18:44 +02:00
Saúl Ibarra Corretgé
00c8409e31 ios,android: update SDK version to 2.3.0 2019-09-17 13:42:08 +02:00
Leonard Kim
1b43c22940 fix(chat): update thumbs emoji strings
react-emoji-renderer 1.0.0 removed the
thumbsup and thumbsdown aliases.
2019-09-16 09:55:36 -07:00
Saúl Ibarra Corretgé
efddb36164 thumbnail: fix accessing props 2019-09-16 13:27:10 +02:00
Saúl Ibarra Corretgé
385e1c1047 media: fix creating video track when toggling the welcome page switch 2019-09-13 19:07:26 +02:00
Saúl Ibarra Corretgé
3cc181a2e5 rn,config: create a fake config if we cannot load one on the welcome page
We try to load the configuration with every room change, even when there is no
room. There is a bad (corner) case: when we have no config cached (first boot or
wiped app data). In such case the user is trapped in an infinite loop because we
require the config to show the welcome page, oh well.

Pretend we have a configuration by creating the most minimal one to at least get
to the welcome page.
2019-09-13 19:07:26 +02:00
Saúl Ibarra Corretgé
bcc1be675f thumbnail: use a functional component
Simplifies the code a bit, and we use no lifecycle methods.
2019-09-13 17:37:23 +02:00
Saúl Ibarra Corretgé
d1be5742ba thumbnail: remove dead code
Audio streams are automatically played by WebRTC and this won't change, probably
ever. There is no point in having checks and an Audio component which does
nothing.
2019-09-13 17:37:23 +02:00
Saúl Ibarra Corretgé
1b27e331da thumbnail: use a more explicit prop 2019-09-13 17:37:23 +02:00
Saúl Ibarra Corretgé
c1f7bf75c1 thumbnail: don't render dominant speaker indicator on 1-1 calls 2019-09-13 17:37:23 +02:00
Bettenbuk Zoltan
382ec011eb ref: reduce device popup bundle size 2019-09-13 17:25:32 +02:00
Bettenbuk Zoltan
8a3ddd8596 feat: SVG icons 2019-09-13 14:07:53 +02:00
Saúl Ibarra Corretgé
738a199b4c welcome: tame the linter 2019-09-13 12:28:53 +02:00
Saúl Ibarra Corretgé
40a1af5302 dev: use alpha as the default proxy target 2019-09-13 11:51:22 +02:00
Maximilian Ruta
be5dba7eea welcome: add room validation pattern
Fixes: #312
2019-09-13 11:18:58 +02:00
Saúl Ibarra Corretgé
eb15f73e59 android: don't use proguard on debug builds
It's not necessary and makes the build faster.
2019-09-12 19:43:05 +02:00
Saúl Ibarra Corretgé
2f7b485b8f android: remove unneded code 2019-09-12 19:43:05 +02:00
Saúl Ibarra Corretgé
3a885c893a android: fix running on Android 5
For some reason ART complains about these methods being overrides of package
private ones from Timber.
2019-09-12 19:43:05 +02:00
Saúl Ibarra Corretgé
6c4901a826 ios,callkit: delay updating the muted state until conference starts
In iOS 13 if the call is not unmuted when we report it to the system as started,
an action to unmute it is dispatched automagically. Thanks, Apple.

So, delay synchronizing the muted state until the conference is started (after
the join action). This creates a small window for de-synchronization, but it's
very short and it seems unavoidable.

This change is only applied to operating systems built by the fruit company in
Cupertino.
2019-09-12 12:55:02 +02:00
Saúl Ibarra Corretgé
91c1c91950 android: fix log formatting issues 2019-09-11 14:29:37 +02:00
Saúl Ibarra Corretgé
1091ac7e7d log: fix log formatting 2019-09-10 10:34:52 +02:00
damencho
0c0bd001e5 Removes disableSuspendVideo option. Updates @jitsi/lib-jitsi-meet. 2019-09-10 08:58:55 +02:00
Bettenbuk Zoltan
256994e1f8 fix: webpack proxy fix 2019-09-09 18:27:30 +02:00
Saúl Ibarra Corretgé
f6fb859531 build: exit with an error if bundle sizes increase too much
The currently selected values are a bit above the actual sizes, so if a PR
increases the bundle size enough to trigger the failure, it should bump it.
It better have a good reason for it though!
2019-09-06 17:46:25 +02:00
Saúl Ibarra Corretgé
7deb2006c3 build: add integration with webpack-bundle-analyzer
Build as follows to build (production) bundle size stats:

npx webpack -p --progress --analyze-bundle

Then open the report:

npx webpack-bundle-analyzer build/stats.json build/
2019-09-06 17:46:25 +02:00
Saúl Ibarra Corretgé
2aea24ffad dial-in-info: fix bundle bloat
The direct import sidesteps many chained-effect imports, halving the bundle
size.
2019-09-06 16:29:23 +02:00
Saúl Ibarra Corretgé
b5aae0b58d build: style 2019-09-06 16:29:23 +02:00
Saúl Ibarra Corretgé
d436825a45 flacworker: don't use the Grand Unified Logger
There are just a couple of logs in this feature, and it's a standalone bundle,
which would bloat it due to cascaded dependencis.
2019-09-06 16:29:23 +02:00
Saúl Ibarra Corretgé
5276cb6bc8 alwaysontop: don't use the Grand Unified Logger
There are just a couple of logs in this feature, and it's a standalone bundle,
which would bloat it due to cascaded dependencis.
2019-09-06 16:29:23 +02:00
Saúl Ibarra Corretgé
f863733dd3 base/util: don't use the Grand Unified Logger
There are just a couple of logs in this feature, and it's included in bundles
like external_api, which would bloat it due to cascaded dependencis.
2019-09-06 16:29:23 +02:00
Saúl Ibarra Corretgé
2ccd4968a4 external_api: don't use the Jitsi Meet logger
This is for other applications to use, and it's currently only used for logging
1 line, so use console.error.
2019-09-06 16:29:23 +02:00
Saúl Ibarra Corretgé
c233433243 deps: react-native-webrtc@latest 2019-09-05 16:37:51 +02:00
Saúl Ibarra Corretgé
6861f463b3 android: update SDK release script to publish JSC artifacts
In
b53a034aaf (diff-0339cf92cc68bc5981fe6df601316c1c)
I removed this, because RN has updated the builtin JSC version. On the next
release, however, RN introduced a new JS interpreter (Hermes) so JSC is now a RN
dependency. Thus, add the magic spells to publish the AARs to Maven.
2019-09-05 16:32:53 +02:00
Hristo Terezov
ac065f0225 chore(package.json): Update LJM 2019-09-05 04:33:02 -07:00
Saúl Ibarra Corretgé
b4b33c94dd ios: update Podfile.lock 2019-09-05 12:53:26 +02:00
Saúl Ibarra Corretgé
c8753230a4 deps: react-native-webrtc@latest 2019-09-04 20:27:33 +02:00
paweldomas
dbf569e29e chore(deps): update LJM to 00920c0f655a74c757c7fef2cdbd053ae4d1f485 2019-09-04 10:46:18 -05:00
Saúl Ibarra Corretgé
27205e3119 ios: divert RN logs to our logger 2019-09-04 17:45:18 +02:00
Saúl Ibarra Corretgé
f2fdef8361 ios: log fatal errors, don't swallow exceptions 2019-09-04 17:45:18 +02:00
George Politis
d4dd5ab46a deps: lib-jitsi-meet@latest 2019-09-04 17:29:28 +02:00
Saúl Ibarra Corretgé
902da8cc4f rn: add native loggers
These provide the ability to integrate the SDK with some other application
loggers.

At the time this was written we use Timber on Android and CocoaLumberjack on iOS.

In addition to the integration capabilities, a LogBridge React Native module
provides log transports for JavaScript code, thus centralizing all logs on the
native loggers.
2019-09-04 10:50:30 +02:00
454 changed files with 14169 additions and 8046 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -31,82 +31,9 @@ You can get our mobile versions from here:
* [Android](https://play.google.com/store/apps/details?id=org.jitsi.meet)
* [iOS](https://itunes.apple.com/us/app/jitsi-meet/id1165103905)
## Building the sources
## Development
Node.js >= 10 and npm >= 6 are required.
On Debian/Ubuntu systems, the required packages can be installed with:
```
sudo apt-get install npm nodejs
cd jitsi-meet
npm install
```
To build the Jitsi Meet application, just type
```
make
```
### Working with the library sources (lib-jitsi-meet)
By default the library is build from its git repository sources. The default dependency path in package.json is :
```json
"lib-jitsi-meet": "jitsi/lib-jitsi-meet",
```
To work with local copy you must change the path to:
```json
"lib-jitsi-meet": "file:///Users/name/local-lib-jitsi-meet-copy",
```
To make the project you must force it to take the sources as 'npm update':
```
npm install lib-jitsi-meet --force && make
```
Or if you are making only changes to the library:
```
npm install lib-jitsi-meet --force && make deploy-lib-jitsi-meet
```
Alternative way is to use [npm link](https://docs.npmjs.com/cli/link).
It allows to link `lib-jitsi-meet` dependency to local source in few steps:
```bash
cd lib-jitsi-meet
#### create global symlink for lib-jitsi-meet package
npm link
cd ../jitsi-meet
#### create symlink from the local node_modules folder to the global lib-jitsi-meet symlink
npm link lib-jitsi-meet
```
After changes in local `lib-jitsi-meet` repository, you can rebuild it with `npm run install` and your `jitsi-meet` repository will use that modified library.
Note: when using node version 4.x, the make file of jitsi-meet do npm update which will delete the link. It is no longer the case with version 6.x.
If you do not want to use local repository anymore you should run
```bash
cd jitsi-meet
npm unlink lib-jitsi-meet
npm install
```
### Running with webpack-dev-server for development
Use it at the CLI, type
```
make dev
```
By default the backend deployment used is `beta.meet.jit.si`. You can point the Jitsi-Meet app at a different backend by using a proxy server. To do this, set the WEBPACK_DEV_SERVER_PROXY_TARGET variable:
```
export WEBPACK_DEV_SERVER_PROXY_TARGET=https://your-example-server.com
make dev
```
The app should be running at https://localhost:8080/
For web development see [here](doc/development.md), and for mobile see [here](doc/mobile.md).
## Contributing
@@ -118,7 +45,8 @@ see our [guidelines for contributing](CONTRIBUTING.md).
Jitsi Meet provides a very flexible way of embedding in external applications by using the [Jitsi Meet API](doc/api.md).
## Security
WebRTC does not provide a way of conducting multi-party conversations with end-to-end encryption.
WebRTC does not (yet) provide a way of conducting multi-party conversations with end-to-end encryption.
Unless you consistently compare DTLS fingerprints with your peers vocally, the same goes for one-to-one calls.
As a result, your stream is encrypted on the network but decrypted on the machine that hosts the bridge when using Jitsi Meet.
@@ -130,9 +58,13 @@ Jitsi Meet in terms of security.
The [meet.jit.si](https://meet.jit.si) service is maintained by the Jitsi team
at [8x8](https://8x8.com).
## Mobile app
Jitsi Meet is also available as a React Native app for Android and iOS.
Instructions on how to build it can be found [here](doc/mobile.md).
## Security issues
We take security very seriously and develop all Jitsi projects to be secure and safe.
If you find (or simply suspect) a security issue in any of the Jitsi projects, please send us an email to security@jitsi.org.
**We encourage responsible disclosure for the sake of our users, so please reach out before posting in a public space.**
## Acknowledgements

View File

@@ -34,8 +34,6 @@ android {
buildTypes {
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-debug.pro'
buildConfigField "boolean", "GOOGLE_SERVICES_ENABLED", "${googleServicesEnabled}"
buildConfigField "boolean", "LIBRE_BUILD", "${rootProject.ext.libreBuild}"
}

View File

@@ -1,5 +0,0 @@
-include proguard-rules.pro
# Disabling obfuscation is useful if you collect stack traces from production crashes
# (unless you are using a system that supports de-obfuscate the stack traces).
-dontobfuscate

View File

@@ -83,3 +83,6 @@
-dontwarn javax.servlet.**
# ^^^ We added the above when we switched minifyEnabled on.
# Rule to avoid build errors related to SVGs.
-keep public class com.horcrux.svg.** {*;}

View File

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

View File

@@ -10,6 +10,7 @@ MVN_HTTP=0
DEFAULT_SDK_VERSION=$(grep sdkVersion ${THIS_DIR}/../gradle.properties | cut -d"=" -f2)
SDK_VERSION=${OVERRIDE_SDK_VERSION:-${DEFAULT_SDK_VERSION}}
RN_VERSION=$(jq -r '.dependencies."react-native"' ${THIS_DIR}/../../package.json)
JSC_VERSION="r"$(jq -r '.dependencies."jsc-android"' ${THIS_DIR}/../../node_modules/react-native/package.json | cut -d . -f 1 | cut -c 2-)
DO_GIT_TAG=${GIT_TAG:-0}
if [[ $THE_MVN_REPO == http* ]]; then
@@ -37,14 +38,20 @@ if [[ $MVN_HTTP == 1 ]]; then
-DgeneratePom=false \
-DpomFile=react-native-${RN_VERSION}.pom || true
popd
# Push JSC
echo "Pushing JSC ${JSC_VERSION} to the Maven repo"
pushd ${THIS_DIR}/../../node_modules/jsc-android/dist/org/webkit/android-jsc/${JSC_VERSION}
mvn \
deploy:deploy-file \
-Durl=${MVN_REPO} \
-DrepositoryId=${MVN_REPO_ID} \
-Dfile=android-jsc-${JSC_VERSION}.aar \
-Dpackaging=aar \
-DgeneratePom=false \
-DpomFile=android-jsc-${JSC_VERSION}.pom || true
popd
else
# Check if an SDK with that same version has already been released
if [[ -d ${MVN_REPO}/org/jitsi/react/jitsi-meet-sdk/${SDK_VERSION} ]]; then
echo "There is already a release with that version in the Maven repo!"
exit 1
fi
# First push React Native, if necessary
# Push React Native, if necessary
if [[ ! -d ${MVN_REPO}/com/facebook/react/react-native/${RN_VERSION} ]]; then
echo "Pushing React Native ${RN_VERSION} to the Maven repo"
pushd ${THIS_DIR}/../../node_modules/react-native/android/com/facebook/react/react-native/${RN_VERSION}
@@ -57,6 +64,26 @@ else
-DpomFile=react-native-${RN_VERSION}.pom
popd
fi
# Push JSC, if necessary
if [[ ! -d ${MVN_REPO}/org/webkit/android-jsc/${JSC_VERSION} ]]; then
echo "Pushing JSC ${JSC_VERSION} to the Maven repo"
pushd ${THIS_DIR}/../../node_modules/jsc-android/dist/org/webkit/android-jsc/${JSC_VERSION}
mvn \
deploy:deploy-file \
-Durl=${MVN_REPO} \
-Dfile=android-jsc-${JSC_VERSION}.aar \
-Dpackaging=aar \
-DgeneratePom=false \
-DpomFile=android-jsc-${JSC_VERSION}.pom
popd
fi
# Check if an SDK with that same version has already been released
if [[ -d ${MVN_REPO}/org/jitsi/react/jitsi-meet-sdk/${SDK_VERSION} ]]; then
echo "There is already a release with that version in the Maven repo!"
exit 1
fi
fi
# Now build and publish the Jitsi Meet SDK and its dependencies

View File

@@ -44,6 +44,8 @@ dependencies {
implementation 'org.webkit:android-jsc:+'
implementation 'com.dropbox.core:dropbox-core-sdk:3.0.8'
implementation 'com.jakewharton.timber:timber:4.7.1'
implementation 'com.squareup.duktape:duktape-android:1.3.0'
if (!rootProject.ext.libreBuild) {
implementation 'com.amplitude:android-sdk:2.14.1'
@@ -61,7 +63,7 @@ dependencies {
implementation project(':react-native-keep-awake')
implementation project(':react-native-linear-gradient')
implementation project(':react-native-sound')
implementation project(':react-native-vector-icons')
implementation project(':react-native-svg')
implementation project(':react-native-webrtc')
implementation project(':react-native-webview')
@@ -139,13 +141,6 @@ android.libraryVariants.all { def variant ->
mergeAssetsTask.doLast {
def assetsDir = mergeAssetsTask.outputDir
// Bundle fonts
//
copy {
from("${projectDir}/../../fonts/jitsi.ttf")
into("${assetsDir}/fonts")
}
// Bundle sounds
//
copy {

View File

@@ -24,6 +24,7 @@ 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;
@@ -90,7 +91,7 @@ class AmplitudeModule
JSONObject eventProps = new JSONObject(eventPropsString);
Amplitude.getInstance(instanceName).logEvent(eventType, eventProps);
} catch (JSONException e) {
e.printStackTrace();
JitsiMeetLogger.e(e, "Error logging event");
}
}

View File

@@ -0,0 +1,165 @@
/*
* 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.
* 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.content.Context;
import android.os.Build;
import android.telecom.CallAudioState;
import androidx.annotation.RequiresApi;
import java.util.HashSet;
import java.util.Set;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
/**
* {@link AudioModeModule.AudioDeviceHandlerInterface} module implementing device handling for
* Android versions >= O when ConnectionService is enabled.
*/
@RequiresApi(Build.VERSION_CODES.O)
class AudioDeviceHandlerConnectionService implements
AudioModeModule.AudioDeviceHandlerInterface,
RNConnectionService.CallAudioStateListener {
private final static String TAG = AudioDeviceHandlerConnectionService.class.getSimpleName();
/**
* Reference to the main {@code AudioModeModule}.
*/
private AudioModeModule module;
/**
* Converts any of the "DEVICE_" constants into the corresponding
* {@link android.telecom.CallAudioState} "ROUTE_" number.
*
* @param audioDevice one of the "DEVICE_" constants.
* @return a route number {@link android.telecom.CallAudioState#ROUTE_EARPIECE} if
* no match is found.
*/
private static int audioDeviceToRouteInt(String audioDevice) {
if (audioDevice == null) {
return CallAudioState.ROUTE_EARPIECE;
}
switch (audioDevice) {
case AudioModeModule.DEVICE_BLUETOOTH:
return CallAudioState.ROUTE_BLUETOOTH;
case AudioModeModule.DEVICE_EARPIECE:
return CallAudioState.ROUTE_EARPIECE;
case AudioModeModule.DEVICE_HEADPHONES:
return CallAudioState.ROUTE_WIRED_HEADSET;
case AudioModeModule.DEVICE_SPEAKER:
return CallAudioState.ROUTE_SPEAKER;
default:
JitsiMeetLogger.e(TAG + " Unsupported device name: " + audioDevice);
return CallAudioState.ROUTE_EARPIECE;
}
}
/**
* Populates given route mask into the "DEVICE_" list.
*
* @param supportedRouteMask an integer coming from
* {@link android.telecom.CallAudioState#getSupportedRouteMask()}.
* @return a list of device names.
*/
private static Set<String> routesToDeviceNames(int supportedRouteMask) {
Set<String> devices = new HashSet<>();
if ((supportedRouteMask & CallAudioState.ROUTE_EARPIECE) == CallAudioState.ROUTE_EARPIECE) {
devices.add(AudioModeModule.DEVICE_EARPIECE);
}
if ((supportedRouteMask & CallAudioState.ROUTE_BLUETOOTH) == CallAudioState.ROUTE_BLUETOOTH) {
devices.add(AudioModeModule.DEVICE_BLUETOOTH);
}
if ((supportedRouteMask & CallAudioState.ROUTE_SPEAKER) == CallAudioState.ROUTE_SPEAKER) {
devices.add(AudioModeModule.DEVICE_SPEAKER);
}
if ((supportedRouteMask & CallAudioState.ROUTE_WIRED_HEADSET) == CallAudioState.ROUTE_WIRED_HEADSET) {
devices.add(AudioModeModule.DEVICE_HEADPHONES);
}
return devices;
}
/**
* Used to store the most recently reported audio devices.
* Makes it easier to compare for a change, because the devices are stored
* as a mask in the {@link android.telecom.CallAudioState}. The mask is populated into
* the {@code availableDevices} on each update.
*/
private int supportedRouteMask = -1;
public AudioDeviceHandlerConnectionService() {
}
@Override
public void onCallAudioStateChange(final CallAudioState state) {
module.runInAudioThread(new Runnable() {
@Override
public void run() {
boolean audioRouteChanged
= audioDeviceToRouteInt(module.getSelectedDevice()) != state.getRoute();
int newSupportedRoutes = state.getSupportedRouteMask();
boolean audioDevicesChanged = supportedRouteMask != newSupportedRoutes;
if (audioDevicesChanged) {
supportedRouteMask = newSupportedRoutes;
Set<String> devices = routesToDeviceNames(supportedRouteMask);
module.replaceDevices(devices);
JitsiMeetLogger.i(TAG + " Available audio devices: " + devices.toString());
}
if (audioRouteChanged || audioDevicesChanged) {
module.resetSelectedDevice();
module.updateAudioRoute();
}
}
});
}
@Override
public void start(Context context, AudioModeModule audioModeModule) {
JitsiMeetLogger.i("Using " + TAG + " as the audio device handler");
module = audioModeModule;
RNConnectionService rcs = ReactInstanceManagerHolder.getNativeModule(RNConnectionService.class);
if (rcs != null) {
rcs.setCallAudioStateListener(this);
} else {
JitsiMeetLogger.w(TAG + " Couldn't set call audio state listener, module is null");
}
}
@Override
public void stop() {
RNConnectionService rcs = ReactInstanceManagerHolder.getNativeModule(RNConnectionService.class);
if (rcs != null) {
rcs.setCallAudioStateListener(null);
} else {
JitsiMeetLogger.w(TAG + " Couldn't set call audio state listener, module is null");
}
}
public void setAudioRoute(String audioDevice) {
int newAudioRoute = audioDeviceToRouteInt(audioDevice);
RNConnectionService.setAudioRoute(newAudioRoute);
}
@Override
public boolean setMode(int mode) {
return true;
}
}

View File

@@ -0,0 +1,231 @@
/*
* 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.
* 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.content.Context;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.os.Build;
import androidx.annotation.RequiresApi;
import java.util.HashSet;
import java.util.Set;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
/**
* {@link AudioModeModule.AudioDeviceHandlerInterface} module implementing device handling for
* all post-M Android versions. This handler can be used on any Android versions >= M, but by
* default it's only used on versions < O, since versions >= O use ConnectionService, but it
* can be disabled.
*/
@RequiresApi(Build.VERSION_CODES.M)
class AudioDeviceHandlerGeneric implements
AudioModeModule.AudioDeviceHandlerInterface,
AudioManager.OnAudioFocusChangeListener {
private final static String TAG = AudioDeviceHandlerGeneric.class.getSimpleName();
/**
* Reference to the main {@code AudioModeModule}.
*/
private AudioModeModule module;
/**
* Constant defining a USB headset. Only available on API level >= 26.
* The value of: AudioDeviceInfo.TYPE_USB_HEADSET
*/
private static final int TYPE_USB_HEADSET = 22;
/**
* Indicator that we have lost audio focus.
*/
private boolean audioFocusLost = false;
/**
* {@link AudioManager} instance used to interact with the Android audio
* subsystem.
*/
private AudioManager audioManager;
/**
* {@link Runnable} for running audio device detection the main thread.
* This is only used on Android >= M.
*/
private final Runnable onAudioDeviceChangeRunner = new Runnable() {
@Override
public void run() {
Set<String> devices = new HashSet<>();
AudioDeviceInfo[] deviceInfos = audioManager.getDevices(AudioManager.GET_DEVICES_ALL);
for (AudioDeviceInfo info: deviceInfos) {
switch (info.getType()) {
case AudioDeviceInfo.TYPE_BLUETOOTH_SCO:
devices.add(AudioModeModule.DEVICE_BLUETOOTH);
break;
case AudioDeviceInfo.TYPE_BUILTIN_EARPIECE:
devices.add(AudioModeModule.DEVICE_EARPIECE);
break;
case AudioDeviceInfo.TYPE_BUILTIN_SPEAKER:
devices.add(AudioModeModule.DEVICE_SPEAKER);
break;
case AudioDeviceInfo.TYPE_WIRED_HEADPHONES:
case AudioDeviceInfo.TYPE_WIRED_HEADSET:
case TYPE_USB_HEADSET:
devices.add(AudioModeModule.DEVICE_HEADPHONES);
break;
}
}
module.replaceDevices(devices);
JitsiMeetLogger.i(TAG + " Available audio devices: " + devices.toString());
module.updateAudioRoute();
}
};
private final android.media.AudioDeviceCallback audioDeviceCallback =
new android.media.AudioDeviceCallback() {
@Override
public void onAudioDevicesAdded(
AudioDeviceInfo[] addedDevices) {
JitsiMeetLogger.d(TAG + " Audio devices added");
onAudioDeviceChange();
}
@Override
public void onAudioDevicesRemoved(
AudioDeviceInfo[] removedDevices) {
JitsiMeetLogger.d(TAG + " Audio devices removed");
onAudioDeviceChange();
}
};
public AudioDeviceHandlerGeneric() {
}
/**
* Helper method to trigger an audio route update when devices change. It
* makes sure the operation is performed on the audio thread.
*/
private void onAudioDeviceChange() {
module.runInAudioThread(onAudioDeviceChangeRunner);
}
/**
* {@link AudioManager.OnAudioFocusChangeListener} interface method. Called
* when the audio focus of the system is updated.
*
* @param focusChange - The type of focus change.
*/
@Override
public void onAudioFocusChange(final int focusChange) {
module.runInAudioThread(new Runnable() {
@Override
public void run() {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN: {
JitsiMeetLogger.d(TAG + " Audio focus gained");
// Some other application potentially stole our audio focus
// temporarily. Restore our mode.
if (audioFocusLost) {
module.updateAudioRoute();
}
audioFocusLost = false;
break;
}
case AudioManager.AUDIOFOCUS_LOSS:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: {
JitsiMeetLogger.d(TAG + " Audio focus lost");
audioFocusLost = true;
break;
}
}
}
});
}
/**
* Helper method to set the output route to a Bluetooth device.
*
* @param enabled true if Bluetooth should use used, false otherwise.
*/
private void setBluetoothAudioRoute(boolean enabled) {
if (enabled) {
audioManager.startBluetoothSco();
audioManager.setBluetoothScoOn(true);
} else {
audioManager.setBluetoothScoOn(false);
audioManager.stopBluetoothSco();
}
}
@Override
public void start(Context context, AudioModeModule audioModeModule) {
JitsiMeetLogger.i("Using " + TAG + " as the audio device handler");
module = audioModeModule;
audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
// Setup runtime device change detection.
audioManager.registerAudioDeviceCallback(audioDeviceCallback, null);
// Do an initial detection.
onAudioDeviceChange();
}
@Override
public void stop() {
audioManager.unregisterAudioDeviceCallback(audioDeviceCallback);
}
@Override
public void setAudioRoute(String device) {
// Turn speaker on / off
audioManager.setSpeakerphoneOn(device.equals(AudioModeModule.DEVICE_SPEAKER));
// Turn bluetooth on / off
setBluetoothAudioRoute(device.equals(AudioModeModule.DEVICE_BLUETOOTH));
}
@Override
public boolean setMode(int mode) {
if (mode == AudioModeModule.DEFAULT) {
audioFocusLost = false;
audioManager.setMode(AudioManager.MODE_NORMAL);
audioManager.abandonAudioFocus(this);
audioManager.setSpeakerphoneOn(false);
setBluetoothAudioRoute(false);
return true;
}
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
audioManager.setMicrophoneMute(false);
if (audioManager.requestAudioFocus(this, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN)
== AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
JitsiMeetLogger.w(TAG + " Audio focus request failed");
return false;
}
return true;
}
}

View File

@@ -0,0 +1,229 @@
/*
* 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.
* 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.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
/**
* {@link AudioModeModule.AudioDeviceHandlerInterface} module implementing device handling for
* legacy (pre-M) Android versions.
*/
class AudioDeviceHandlerLegacy implements
AudioModeModule.AudioDeviceHandlerInterface,
AudioManager.OnAudioFocusChangeListener,
BluetoothHeadsetMonitor.Listener {
private final static String TAG = AudioDeviceHandlerLegacy.class.getSimpleName();
/**
* Reference to the main {@code AudioModeModule}.
*/
private AudioModeModule module;
/**
* Indicator that we have lost audio focus.
*/
private boolean audioFocusLost = false;
/**
* {@link AudioManager} instance used to interact with the Android audio
* subsystem.
*/
private AudioManager audioManager;
/**
* {@link BluetoothHeadsetMonitor} for detecting Bluetooth device changes in
* old (< M) Android versions.
*/
private BluetoothHeadsetMonitor bluetoothHeadsetMonitor;
public AudioDeviceHandlerLegacy() {
}
/**
* Helper method to trigger an audio route update when Bluetooth devices are
* connected / disconnected.
*/
@Override
public void onBluetoothDeviceChange(final boolean deviceAvailable) {
module.runInAudioThread(new Runnable() {
@Override
public void run() {
if (deviceAvailable) {
module.addDevice(AudioModeModule.DEVICE_BLUETOOTH);
} else {
module.removeDevice(AudioModeModule.DEVICE_BLUETOOTH);
}
module.updateAudioRoute();
}
});
}
/**
* Helper method to trigger an audio route update when a headset is plugged
* or unplugged.
*/
private void onHeadsetDeviceChange() {
module.runInAudioThread(new Runnable() {
@Override
public void run() {
// XXX: isWiredHeadsetOn is not deprecated when used just for
// knowing if there is a wired headset connected, regardless of
// audio being routed to it.
//noinspection deprecation
if (audioManager.isWiredHeadsetOn()) {
module.addDevice(AudioModeModule.DEVICE_HEADPHONES);
} else {
module.removeDevice(AudioModeModule.DEVICE_HEADPHONES);
}
module.updateAudioRoute();
}
});
}
/**
* {@link AudioManager.OnAudioFocusChangeListener} interface method. Called
* when the audio focus of the system is updated.
*
* @param focusChange - The type of focus change.
*/
@Override
public void onAudioFocusChange(final int focusChange) {
module.runInAudioThread(new Runnable() {
@Override
public void run() {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN: {
JitsiMeetLogger.d(TAG + " Audio focus gained");
// Some other application potentially stole our audio focus
// temporarily. Restore our mode.
if (audioFocusLost) {
module.updateAudioRoute();
}
audioFocusLost = false;
break;
}
case AudioManager.AUDIOFOCUS_LOSS:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: {
JitsiMeetLogger.d(TAG + " Audio focus lost");
audioFocusLost = true;
break;
}
}
}
});
}
/**
* Helper method to set the output route to a Bluetooth device.
*
* @param enabled true if Bluetooth should use used, false otherwise.
*/
private void setBluetoothAudioRoute(boolean enabled) {
if (enabled) {
audioManager.startBluetoothSco();
audioManager.setBluetoothScoOn(true);
} else {
audioManager.setBluetoothScoOn(false);
audioManager.stopBluetoothSco();
}
}
@Override
public void start(Context context, AudioModeModule audioModeModule) {
JitsiMeetLogger.i("Using " + TAG + " as the audio device handler");
module = audioModeModule;
audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
// Setup runtime device change detection.
//
// Detect changes in wired headset connections.
IntentFilter wiredHeadSetFilter = new IntentFilter(AudioManager.ACTION_HEADSET_PLUG);
BroadcastReceiver wiredHeadsetReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
JitsiMeetLogger.d(TAG + " Wired headset added / removed");
onHeadsetDeviceChange();
}
};
context.registerReceiver(wiredHeadsetReceiver, wiredHeadSetFilter);
// Detect Bluetooth device changes.
bluetoothHeadsetMonitor = new BluetoothHeadsetMonitor(context, this);
// On Android < M, detect if we have an earpiece.
PackageManager pm = context.getPackageManager();
if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
module.addDevice(AudioModeModule.DEVICE_EARPIECE);
}
// Always assume there is a speaker.
module.addDevice(AudioModeModule.DEVICE_SPEAKER);
}
@Override
public void stop() {
bluetoothHeadsetMonitor.stop();
bluetoothHeadsetMonitor = null;
}
@Override
public void setAudioRoute(String device) {
// Turn speaker on / off
audioManager.setSpeakerphoneOn(device.equals(AudioModeModule.DEVICE_SPEAKER));
// Turn bluetooth on / off
setBluetoothAudioRoute(device.equals(AudioModeModule.DEVICE_BLUETOOTH));
}
@Override
public boolean setMode(int mode) {
if (mode == AudioModeModule.DEFAULT) {
audioFocusLost = false;
audioManager.setMode(AudioManager.MODE_NORMAL);
audioManager.abandonAudioFocus(this);
audioManager.setSpeakerphoneOn(false);
setBluetoothAudioRoute(false);
return true;
}
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
audioManager.setMicrophoneMute(false);
if (audioManager.requestAudioFocus(this, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN)
== AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
JitsiMeetLogger.w(TAG + " Audio focus request failed");
return false;
}
return true;
}
}

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.
@@ -16,17 +16,8 @@
package org.jitsi.meet.sdk;
import android.annotation.TargetApi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.os.Build;
import android.util.Log;
import androidx.annotation.RequiresApi;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
@@ -37,6 +28,8 @@ import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.module.annotations.ReactModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -60,9 +53,7 @@ import java.util.concurrent.Executors;
* {@code AudioModeModule.DEFAULT} mode should be used.
*/
@ReactModule(name = AudioModeModule.NAME)
class AudioModeModule extends ReactContextBaseJavaModule
implements AudioManager.OnAudioFocusChangeListener {
class AudioModeModule extends ReactContextBaseJavaModule {
public static final String NAME = "AudioMode";
/**
@@ -74,174 +65,33 @@ class AudioModeModule extends ReactContextBaseJavaModule
* - VIDEO_CALL: Used for video calls. It will use the speaker by default,
* unless a wired or Bluetooth headset is connected.
*/
private static final int DEFAULT = 0;
private static final int AUDIO_CALL = 1;
private static final int VIDEO_CALL = 2;
/**
* Constant defining the action for plugging in a headset. This is used on
* our device detection system for API < 23.
*/
private static final String ACTION_HEADSET_PLUG
= (Build.VERSION.SDK_INT >= 21)
? AudioManager.ACTION_HEADSET_PLUG
: Intent.ACTION_HEADSET_PLUG;
/**
* Constant defining a USB headset. Only available on API level >= 26.
* The value of: AudioDeviceInfo.TYPE_USB_HEADSET
*/
private static final int TYPE_USB_HEADSET = 22;
static final int DEFAULT = 0;
static final int AUDIO_CALL = 1;
static final int VIDEO_CALL = 2;
/**
* The {@code Log} tag {@code AudioModeModule} is to log messages with.
*/
static final String TAG = NAME;
/**
* Converts any of the "DEVICE_" constants into the corresponding
* {@link android.telecom.CallAudioState} "ROUTE_" number.
*
* @param audioDevice one of the "DEVICE_" constants.
* @return a route number {@link android.telecom.CallAudioState#ROUTE_EARPIECE} if
* no match is found.
*/
@RequiresApi(api = Build.VERSION_CODES.M)
private static int audioDeviceToRouteInt(String audioDevice) {
if (audioDevice == null) {
return android.telecom.CallAudioState.ROUTE_EARPIECE;
}
switch (audioDevice) {
case DEVICE_BLUETOOTH:
return android.telecom.CallAudioState.ROUTE_BLUETOOTH;
case DEVICE_EARPIECE:
return android.telecom.CallAudioState.ROUTE_EARPIECE;
case DEVICE_HEADPHONES:
return android.telecom.CallAudioState.ROUTE_WIRED_HEADSET;
case DEVICE_SPEAKER:
return android.telecom.CallAudioState.ROUTE_SPEAKER;
default:
Log.e(TAG, "Unsupported device name: " + audioDevice);
return android.telecom.CallAudioState.ROUTE_EARPIECE;
}
}
/**
* Populates given route mask into the "DEVICE_" list.
*
* @param supportedRouteMask an integer coming from
* {@link android.telecom.CallAudioState#getSupportedRouteMask()}.
* @return a list of device names.
*/
@RequiresApi(api = Build.VERSION_CODES.M)
private static Set<String> routesToDeviceNames(int supportedRouteMask) {
Set<String> devices = new HashSet<>();
if ((supportedRouteMask & android.telecom.CallAudioState.ROUTE_EARPIECE)
== android.telecom.CallAudioState.ROUTE_EARPIECE) {
devices.add(DEVICE_EARPIECE);
}
if ((supportedRouteMask & android.telecom.CallAudioState.ROUTE_BLUETOOTH)
== android.telecom.CallAudioState.ROUTE_BLUETOOTH) {
devices.add(DEVICE_BLUETOOTH);
}
if ((supportedRouteMask & android.telecom.CallAudioState.ROUTE_SPEAKER)
== android.telecom.CallAudioState.ROUTE_SPEAKER) {
devices.add(DEVICE_SPEAKER);
}
if ((supportedRouteMask & android.telecom.CallAudioState.ROUTE_WIRED_HEADSET)
== android.telecom.CallAudioState.ROUTE_WIRED_HEADSET) {
devices.add(DEVICE_HEADPHONES);
}
return devices;
}
/**
* Whether or not the ConnectionService is used for selecting audio devices.
*/
private static final boolean supportsConnectionService = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
private static boolean useConnectionService_ = supportsConnectionService;
static boolean useConnectionService() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
return supportsConnectionService && useConnectionService_;
}
/**
* Indicator that we have lost audio focus.
*/
private boolean audioFocusLost = false;
/**
* {@link AudioManager} instance used to interact with the Android audio
* subsystem.
*/
private final AudioManager audioManager;
/**
* {@link BluetoothHeadsetMonitor} for detecting Bluetooth device changes in
* old (< M) Android versions.
*/
private BluetoothHeadsetMonitor bluetoothHeadsetMonitor;
private AudioDeviceHandlerInterface audioDeviceHandler;
/**
* {@link ExecutorService} for running all audio operations on a dedicated
* thread.
*/
private static final ExecutorService executor
= Executors.newSingleThreadExecutor();
/**
* {@link Runnable} for running audio device detection the main thread.
* This is only used on Android >= M.
*/
private final Runnable onAudioDeviceChangeRunner = new Runnable() {
@TargetApi(Build.VERSION_CODES.M)
@Override
public void run() {
Set<String> devices = new HashSet<>();
AudioDeviceInfo[] deviceInfos
= audioManager.getDevices(AudioManager.GET_DEVICES_ALL);
for (AudioDeviceInfo info: deviceInfos) {
switch (info.getType()) {
case AudioDeviceInfo.TYPE_BLUETOOTH_SCO:
devices.add(DEVICE_BLUETOOTH);
break;
case AudioDeviceInfo.TYPE_BUILTIN_EARPIECE:
devices.add(DEVICE_EARPIECE);
break;
case AudioDeviceInfo.TYPE_BUILTIN_SPEAKER:
devices.add(DEVICE_SPEAKER);
break;
case AudioDeviceInfo.TYPE_WIRED_HEADPHONES:
case AudioDeviceInfo.TYPE_WIRED_HEADSET:
case TYPE_USB_HEADSET:
devices.add(DEVICE_HEADPHONES);
break;
}
}
availableDevices = devices;
Log.d(TAG, "Available audio devices: " +
availableDevices.toString());
// Reset user selection
userSelectedDevice = null;
if (mode != -1) {
updateAudioRoute(mode);
}
}
};
/**
* {@link Runnable} for running update operation on the main thread.
*/
private final Runnable updateAudioRouteRunner
= new Runnable() {
@Override
public void run() {
if (mode != -1) {
updateAudioRoute(mode);
}
}
};
private static final ExecutorService executor = Executors.newSingleThreadExecutor();
/**
* Audio mode currently in use.
@@ -251,10 +101,10 @@ class AudioModeModule extends ReactContextBaseJavaModule
/**
* Audio device types.
*/
private static final String DEVICE_BLUETOOTH = "BLUETOOTH";
private static final String DEVICE_EARPIECE = "EARPIECE";
private static final String DEVICE_HEADPHONES = "HEADPHONES";
private static final String DEVICE_SPEAKER = "SPEAKER";
static final String DEVICE_BLUETOOTH = "BLUETOOTH";
static final String DEVICE_EARPIECE = "EARPIECE";
static final String DEVICE_HEADPHONES = "HEADPHONES";
static final String DEVICE_SPEAKER = "SPEAKER";
/**
* Device change event.
@@ -271,15 +121,6 @@ class AudioModeModule extends ReactContextBaseJavaModule
*/
private String selectedDevice;
/**
* Used on API >= 26 to store the most recently reported audio devices.
* Makes it easier to compare for a change, because the devices are stored
* as a mask in the {@link android.telecom.CallAudioState}. The mask is populated into
* the {@link #availableDevices} on each update.
*/
@RequiresApi(api = Build.VERSION_CODES.O)
private int supportedRouteMask;
/**
* User selected device. When null the default is used depending on the
* mode.
@@ -295,31 +136,6 @@ class AudioModeModule extends ReactContextBaseJavaModule
*/
public AudioModeModule(ReactApplicationContext reactContext) {
super(reactContext);
audioManager
= (AudioManager)
reactContext.getSystemService(Context.AUDIO_SERVICE);
// Starting Oreo the ConnectionImpl from ConnectionService is used to
// detect the available devices.
if (!useConnectionService()) {
// Setup runtime device change detection.
setupAudioRouteChangeDetection();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Do an initial detection on Android >= M.
onAudioDeviceChange();
} else {
// On Android < M, detect if we have an earpiece.
PackageManager pm = reactContext.getPackageManager();
if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
availableDevices.add(DEVICE_EARPIECE);
}
// Always assume there is a speaker.
availableDevices.add(DEVICE_SPEAKER);
}
}
}
/**
@@ -360,7 +176,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
data.pushMap(deviceInfo);
}
ReactInstanceManagerHolder.emitEvent(DEVICE_CHANGE_EVENT, data);
Log.i(TAG, "Updating audio device list");
JitsiMeetLogger.i(TAG + " Updating audio device list");
}
});
}
@@ -376,133 +192,36 @@ class AudioModeModule extends ReactContextBaseJavaModule
}
/**
* Helper method to trigger an audio route update when devices change. It
* makes sure the operation is performed on the main thread.
*
* Only used on Android >= M.
*/
void onAudioDeviceChange() {
runInAudioThread(onAudioDeviceChangeRunner);
}
/**
* Helper method to trigger an audio route update when Bluetooth devices are
* connected / disconnected.
*
* Only used on Android < M. Runs on the main thread.
*/
void onBluetoothDeviceChange() {
if (bluetoothHeadsetMonitor != null && bluetoothHeadsetMonitor.isHeadsetAvailable()) {
availableDevices.add(DEVICE_BLUETOOTH);
} else {
availableDevices.remove(DEVICE_BLUETOOTH);
}
if (mode != -1) {
updateAudioRoute(mode);
}
}
/**
* Helper method to trigger an audio route update when a headset is plugged
* or unplugged.
*
* Only used on Android < M.
*/
void onHeadsetDeviceChange() {
runInAudioThread(new Runnable() {
@Override
public void run() {
// XXX: isWiredHeadsetOn is not deprecated when used just for
// knowing if there is a wired headset connected, regardless of
// audio being routed to it.
//noinspection deprecation
if (audioManager.isWiredHeadsetOn()) {
availableDevices.add(DEVICE_HEADPHONES);
} else {
availableDevices.remove(DEVICE_HEADPHONES);
}
if (mode != -1) {
updateAudioRoute(mode);
}
}
});
}
@RequiresApi(api = Build.VERSION_CODES.O)
void onCallAudioStateChange(Object callAudioState_) {
final android.telecom.CallAudioState callAudioState
= (android.telecom.CallAudioState)callAudioState_;
runInAudioThread(new Runnable() {
@Override
public void run() {
int newSupportedRoutes = callAudioState.getSupportedRouteMask();
boolean audioDevicesChanged
= supportedRouteMask != newSupportedRoutes;
if (audioDevicesChanged) {
supportedRouteMask = newSupportedRoutes;
availableDevices = routesToDeviceNames(supportedRouteMask);
Log.d(TAG,
"Available audio devices: "
+ availableDevices.toString());
}
boolean audioRouteChanged
= audioDeviceToRouteInt(selectedDevice)
!= callAudioState.getRoute();
if (audioRouteChanged || audioDevicesChanged) {
// Reset user selection
userSelectedDevice = null;
// If the OS changes the Audio Route or Devices we could have lost
// the selected audio device
selectedDevice = null;
if (mode != -1) {
updateAudioRoute(mode);
}
}
}
});
}
/**
* {@link AudioManager.OnAudioFocusChangeListener} interface method. Called
* when the audio focus of the system is updated.
*
* @param focusChange - The type of focus change.
* Initializes the audio device handler module. This function is called *after* all Catalyst
* modules have been created, and that's why we use it, because {@link AudioDeviceHandlerConnectionService}
* needs access to another Catalyst module, so doing this in the constructor would be too early.
*/
@Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN: {
Log.d(TAG, "Audio focus gained");
// Some other application potentially stole our audio focus
// temporarily. Restore our mode.
if (audioFocusLost) {
updateAudioRoute(mode);
}
audioFocusLost = false;
break;
}
case AudioManager.AUDIOFOCUS_LOSS:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: {
Log.d(TAG, "Audio focus lost");
audioFocusLost = true;
break;
public void initialize() {
setAudioDeviceHandler();
}
private void setAudioDeviceHandler() {
if (audioDeviceHandler != null) {
audioDeviceHandler.stop();
}
if (useConnectionService()) {
audioDeviceHandler = new AudioDeviceHandlerConnectionService();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
audioDeviceHandler = new AudioDeviceHandlerGeneric();
} else {
audioDeviceHandler = new AudioDeviceHandlerLegacy();
}
audioDeviceHandler.start(getReactApplicationContext(), this);
}
/**
* Helper function to run operations on a dedicated thread.
* @param runnable
*/
public void runInAudioThread(Runnable runnable) {
void runInAudioThread(Runnable runnable) {
executor.execute(runnable);
}
@@ -517,13 +236,13 @@ class AudioModeModule extends ReactContextBaseJavaModule
@Override
public void run() {
if (!availableDevices.contains(device)) {
Log.d(TAG, "Audio device not available: " + device);
JitsiMeetLogger.w(TAG + " Audio device not available: " + device);
userSelectedDevice = null;
return;
}
if (mode != -1) {
Log.d(TAG, "User selected device set to: " + device);
JitsiMeetLogger.i(TAG + " User selected device set to: " + device);
userSelectedDevice = device;
updateAudioRoute(mode);
}
@@ -531,46 +250,6 @@ class AudioModeModule extends ReactContextBaseJavaModule
});
}
/**
* The API >= 26 way of adjusting the audio route.
*
* @param audioDevice one of the "DEVICE_" names to set as the audio route.
*/
@RequiresApi(api = Build.VERSION_CODES.O)
private void setAudioRoute(String audioDevice) {
int newAudioRoute = audioDeviceToRouteInt(audioDevice);
RNConnectionService.setAudioRoute(newAudioRoute);
}
/**
* The API < 26 way of adjusting the audio route.
*
* @param audioDevice one of the "DEVICE_" names to set as the audio route.
*/
private void setAudioRoutePreO(String audioDevice) {
// Turn bluetooth on / off
setBluetoothAudioRoute(audioDevice.equals(DEVICE_BLUETOOTH));
// Turn speaker on / off
audioManager.setSpeakerphoneOn(audioDevice.equals(DEVICE_SPEAKER));
}
/**
* Helper method to set the output route to a Bluetooth device.
*
* @param enabled true if Bluetooth should use used, false otherwise.
*/
private void setBluetoothAudioRoute(boolean enabled) {
if (enabled) {
audioManager.startBluetoothSco();
audioManager.setBluetoothScoOn(true);
} else {
audioManager.setBluetoothScoOn(false);
audioManager.stopBluetoothSco();
}
}
/**
* Public method to set the current audio mode.
*
@@ -594,79 +273,28 @@ class AudioModeModule extends ReactContextBaseJavaModule
success = updateAudioRoute(mode);
} catch (Throwable e) {
success = false;
Log.e(
TAG,
"Failed to update audio route for mode: " + mode,
e);
JitsiMeetLogger.e(e, TAG + " Failed to update audio route for mode: " + mode);
}
if (success) {
AudioModeModule.this.mode = mode;
promise.resolve(null);
} else {
promise.reject(
"setMode",
"Failed to set audio mode to " + mode);
promise.reject("setMode", "Failed to set audio mode to " + mode);
}
}
});
}
/**
* Setup the audio route change detection mechanism. We use the
* {@link android.media.AudioDeviceCallback} on 23 >= Android API < 26.
* Sets whether ConnectionService should be used (if available) for setting the audio mode
* or not.
*
* @param use Boolean indicator of where it should be used or not.
*/
private void setupAudioRouteChangeDetection() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setupAudioRouteChangeDetectionM();
} else {
setupAudioRouteChangeDetectionPreM();
}
}
/**
* Audio route change detection mechanism for 23 >= Android API < 26.
*/
@TargetApi(Build.VERSION_CODES.M)
private void setupAudioRouteChangeDetectionM() {
android.media.AudioDeviceCallback audioDeviceCallback =
new android.media.AudioDeviceCallback() {
@Override
public void onAudioDevicesAdded(
AudioDeviceInfo[] addedDevices) {
Log.d(TAG, "Audio devices added");
onAudioDeviceChange();
}
@Override
public void onAudioDevicesRemoved(
AudioDeviceInfo[] removedDevices) {
Log.d(TAG, "Audio devices removed");
onAudioDeviceChange();
}
};
audioManager.registerAudioDeviceCallback(audioDeviceCallback, null);
}
/**
* Audio route change detection mechanism for Android API < 23.
*/
private void setupAudioRouteChangeDetectionPreM() {
Context context = getReactApplicationContext();
// Detect changes in wired headset connections.
IntentFilter wiredHeadSetFilter = new IntentFilter(ACTION_HEADSET_PLUG);
BroadcastReceiver wiredHeadsetReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Wired headset added / removed");
onHeadsetDeviceChange();
}
};
context.registerReceiver(wiredHeadsetReceiver, wiredHeadSetFilter);
// Detect Bluetooth device changes.
bluetoothHeadsetMonitor = new BluetoothHeadsetMonitor(this, context);
@ReactMethod
public void setUseConnectionService(boolean use) {
useConnectionService_ = use;
setAudioDeviceHandler();
}
/**
@@ -677,16 +305,13 @@ class AudioModeModule extends ReactContextBaseJavaModule
* {@code false}, otherwise.
*/
private boolean updateAudioRoute(int mode) {
Log.d(TAG, "Update audio route for mode: " + mode);
JitsiMeetLogger.i(TAG + " Update audio route for mode: " + mode);
if (!audioDeviceHandler.setMode(mode)) {
return false;
}
if (mode == DEFAULT) {
if (!useConnectionService()) {
audioFocusLost = false;
audioManager.setMode(AudioManager.MODE_NORMAL);
audioManager.abandonAudioFocus(this);
audioManager.setSpeakerphoneOn(false);
setBluetoothAudioRoute(false);
}
selectedDevice = null;
userSelectedDevice = null;
@@ -694,20 +319,6 @@ class AudioModeModule extends ReactContextBaseJavaModule
return true;
}
if (!useConnectionService()) {
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
audioManager.setMicrophoneMute(false);
if (audioManager.requestAudioFocus(
this,
AudioManager.STREAM_VOICE_CALL,
AudioManager.AUDIOFOCUS_GAIN)
== AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
Log.d(TAG, "Audio focus request failed");
return false;
}
}
boolean bluetoothAvailable = availableDevices.contains(DEVICE_BLUETOOTH);
boolean headsetAvailable = availableDevices.contains(DEVICE_HEADPHONES);
@@ -722,8 +333,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
}
// Consider the user's selection
if (userSelectedDevice != null
&& availableDevices.contains(userSelectedDevice)) {
if (userSelectedDevice != null && availableDevices.contains(userSelectedDevice)) {
audioDevice = userSelectedDevice;
}
@@ -734,15 +344,99 @@ class AudioModeModule extends ReactContextBaseJavaModule
}
selectedDevice = audioDevice;
Log.d(TAG, "Selected audio device: " + audioDevice);
JitsiMeetLogger.i(TAG + " Selected audio device: " + audioDevice);
if (useConnectionService()) {
setAudioRoute(audioDevice);
} else {
setAudioRoutePreO(audioDevice);
}
audioDeviceHandler.setAudioRoute(audioDevice);
notifyDevicesChanged();
return true;
}
/**
* Gets the currently selected audio device.
*
* @return The selected audio device.
*/
String getSelectedDevice() {
return selectedDevice;
}
/**
* Resets the current device selection.
*/
void resetSelectedDevice() {
selectedDevice = null;
userSelectedDevice = null;
}
/**
* Adds a new device to the list of available devices.
*
* @param device The new device.
*/
void addDevice(String device) {
availableDevices.add(device);
resetSelectedDevice();
}
/**
* Removes a device from the list of available devices.
*
* @param device The old device to the removed.
*/
void removeDevice(String device) {
availableDevices.remove(device);
resetSelectedDevice();
}
/**
* Replaces the current list of available devices with a new one.
*
* @param devices The new devices list.
*/
void replaceDevices(Set<String> devices) {
availableDevices = devices;
resetSelectedDevice();
}
/**
* Re-sets the current audio route. Needed when devices changes have happened.
*/
void updateAudioRoute() {
if (mode != -1) {
updateAudioRoute(mode);
}
}
/**
* Interface for the modules implementing the actual audio device management.
*/
interface AudioDeviceHandlerInterface {
/**
* Start detecting audio device changes.
* @param context Android {@link Context} where detection should take place.
* @param audioModeModule Reference to the main {@link AudioModeModule}.
*/
void start(Context context, AudioModeModule audioModeModule);
/**
* Stop audio device detection.
*/
void stop();
/**
* Set the appropriate route for the given audio device.
*
* @param device Audio device for which the route must be set.
*/
void setAudioRoute(String device);
/**
* Set the given audio mode.
*
* @param mode The new audio mode to be used.
* @return Whether the operation was successful or not.
*/
boolean setMode(int mode);
}
}

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,7 +24,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.util.Log;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
/**
* Helper class to detect and handle Bluetooth device changes. It monitors
@@ -32,68 +33,43 @@ import android.util.Log;
* about device changes when this occurs.
*/
class BluetoothHeadsetMonitor {
/**
* {@link AudioModeModule} where this monitor reports.
*/
private final AudioModeModule audioModeModule;
private final static String TAG = BluetoothHeadsetMonitor.class.getSimpleName();
/**
* The {@link Context} in which {@link #audioModeModule} executes.
* The {@link Context} in which this module executes.
*/
private final Context context;
/**
* Reference to the {@link BluetoothAdapter} object, used to access Bluetooth functionality.
*/
private BluetoothAdapter adapter;
/**
* Reference to a proxy object which allows us to query connected devices.
*/
private BluetoothHeadset headset;
/**
* Flag indicating if there are any Bluetooth headset devices currently
* available.
* receiver registered for receiving Bluetooth connection state changes.
*/
private boolean headsetAvailable = false;
private BroadcastReceiver receiver;
/**
* Helper for running Bluetooth operations on the main thread.
* Listener for receiving Bluetooth device change events.
*/
private final Runnable updateDevicesRunnable
= new Runnable() {
@Override
public void run() {
headsetAvailable
= (headset != null)
&& !headset.getConnectedDevices().isEmpty();
audioModeModule.onBluetoothDeviceChange();
}
};
private Listener listener;
public BluetoothHeadsetMonitor(
AudioModeModule audioModeModule,
Context context) {
this.audioModeModule = audioModeModule;
public BluetoothHeadsetMonitor(Context context, Listener listener) {
this.context = context;
AudioManager audioManager
= (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
if (!audioManager.isBluetoothScoAvailableOffCall()) {
Log.w(AudioModeModule.TAG, "Bluetooth SCO is not available");
return;
}
if (getBluetoothHeadsetProfileProxy()) {
registerBluetoothReceiver();
// Initial detection.
updateDevices();
}
this.listener = listener;
}
private boolean getBluetoothHeadsetProfileProxy() {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter == null) {
Log.w(AudioModeModule.TAG, "Device doesn't support Bluetooth");
JitsiMeetLogger.w(TAG + " Device doesn't support Bluetooth");
return false;
}
@@ -103,9 +79,7 @@ class BluetoothHeadsetMonitor {
BluetoothProfile.ServiceListener listener
= new BluetoothProfile.ServiceListener() {
@Override
public void onServiceConnected(
int profile,
BluetoothProfile proxy) {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (profile == BluetoothProfile.HEADSET) {
headset = (BluetoothHeadset) proxy;
updateDevices();
@@ -119,21 +93,7 @@ class BluetoothHeadsetMonitor {
}
};
return
adapter.getProfileProxy(
context,
listener,
BluetoothProfile.HEADSET);
}
/**
* Returns the current headset availability.
*
* @return {@code true} if there is a Bluetooth headset connected;
* {@code false}, otherwise.
*/
public boolean isHeadsetAvailable() {
return headsetAvailable;
return adapter.getProfileProxy(context, listener, BluetoothProfile.HEADSET);
}
private void onBluetoothReceiverReceive(Context context, Intent intent) {
@@ -148,9 +108,7 @@ class BluetoothHeadsetMonitor {
switch (state) {
case BluetoothHeadset.STATE_CONNECTED:
case BluetoothHeadset.STATE_DISCONNECTED:
Log.d(
AudioModeModule.TAG,
"BT headset connection state changed: " + state);
JitsiMeetLogger.d(TAG + " BT headset connection state changed: " + state);
updateDevices();
break;
}
@@ -158,15 +116,12 @@ class BluetoothHeadsetMonitor {
// XXX: This action will be fired when the connection established
// with a Bluetooth headset (called a SCO connection) changes state.
// When the SCO connection is active we route audio to it.
int state
= intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -99);
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -99);
switch (state) {
case AudioManager.SCO_AUDIO_STATE_CONNECTED:
case AudioManager.SCO_AUDIO_STATE_DISCONNECTED:
Log.d(
AudioModeModule.TAG,
"BT SCO connection state changed: " + state);
JitsiMeetLogger.d(TAG + " BT SCO connection state changed: " + state);
updateDevices();
break;
}
@@ -174,24 +129,63 @@ class BluetoothHeadsetMonitor {
}
private void registerBluetoothReceiver() {
BroadcastReceiver receiver = new BroadcastReceiver() {
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
onBluetoothReceiverReceive(context, intent);
}
};
IntentFilter filter = new IntentFilter();
IntentFilter filter = new IntentFilter();
filter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
context.registerReceiver(receiver, filter);
}
/**
* Detects if there are new devices connected / disconnected and fires the
* {@link AudioModeModule#onAudioDeviceChange()} callback.
* {@link Listener} registered event.
*/
private void updateDevices() {
audioModeModule.runInAudioThread(updateDevicesRunnable);
boolean headsetAvailable = (headset != null) && !headset.getConnectedDevices().isEmpty();
listener.onBluetoothDeviceChange(headsetAvailable);
}
public void start() {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
if (!audioManager.isBluetoothScoAvailableOffCall()) {
JitsiMeetLogger.w(TAG + " Bluetooth SCO is not available");
return;
}
if (!getBluetoothHeadsetProfileProxy()) {
JitsiMeetLogger.w(TAG + " Couldn't get BT profile proxy");
return;
}
registerBluetoothReceiver();
// Initial detection.
updateDevices();
}
public void stop() {
if (receiver != null) {
context.unregisterReceiver(receiver);
}
if (adapter != null && headset != null) {
adapter.closeProfileProxy(BluetoothProfile.HEADSET, headset);
}
receiver = null;
headset = null;
adapter = null;
}
interface Listener {
void onBluetoothDeviceChange(boolean deviceAvailable);
}
}

View File

@@ -13,13 +13,14 @@ import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.util.Log;
import androidx.annotation.RequiresApi;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableNativeMap;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -129,9 +130,7 @@ public class ConnectionService extends android.telecom.ConnectionService {
if (connection != null) {
connection.setActive();
} else {
Log.e(TAG, String.format(
"setConnectionActive - no connection for UUID: %s",
callUUID));
JitsiMeetLogger.e("%s setConnectionActive - no connection for UUID: %s", TAG, callUUID);
}
}
@@ -162,7 +161,7 @@ public class ConnectionService extends android.telecom.ConnectionService {
connection.setDisconnected(cause);
connection.destroy();
} else {
Log.e(TAG, "endCall no connection for UUID: " + callUUID);
JitsiMeetLogger.e(TAG + " endCall no connection for UUID: " + callUUID);
}
}
@@ -194,15 +193,14 @@ public class ConnectionService extends android.telecom.ConnectionService {
boolean hasVideo
= callState.getBoolean(ConnectionImpl.KEY_HAS_VIDEO);
Log.d(TAG, String.format(
"updateCall: %s hasVideo: %s", callUUID, hasVideo));
JitsiMeetLogger.i(" %s updateCall: %s hasVideo: %s", TAG, callUUID, hasVideo);
connection.setVideoState(
hasVideo
? VideoProfile.STATE_BIDIRECTIONAL
: VideoProfile.STATE_AUDIO_ONLY);
}
} else {
Log.e(TAG, "updateCall no connection for UUID: " + callUUID);
JitsiMeetLogger.e(TAG + " updateCall no connection for UUID: " + callUUID);
}
}
@@ -238,13 +236,11 @@ public class ConnectionService extends android.telecom.ConnectionService {
= unregisterStartCallPromise(connection.getCallUUID());
if (startCallPromise != null) {
Log.d(TAG,
"onCreateOutgoingConnection " + connection.getCallUUID());
JitsiMeetLogger.d(TAG + " onCreateOutgoingConnection " + connection.getCallUUID());
startCallPromise.resolve(null);
} else {
Log.e(TAG, String.format(
"onCreateOutgoingConnection: no start call Promise for %s",
connection.getCallUUID()));
JitsiMeetLogger.e(
TAG + " onCreateOutgoingConnection: no start call Promise for " + connection.getCallUUID());
}
return connection;
@@ -268,7 +264,7 @@ public class ConnectionService extends android.telecom.ConnectionService {
PhoneAccountHandle theAccountHandle = request.getAccountHandle();
String callUUID = theAccountHandle.getId();
Log.e(TAG, "onCreateOutgoingConnectionFailed " + callUUID);
JitsiMeetLogger.e(TAG + " onCreateOutgoingConnectionFailed " + callUUID);
if (callUUID != null) {
Promise startCallPromise = unregisterStartCallPromise(callUUID);
@@ -278,12 +274,10 @@ public class ConnectionService extends android.telecom.ConnectionService {
"CREATE_OUTGOING_CALL_FAILED",
"The request has been denied by the system");
} else {
Log.e(TAG, String.format(
"startCallFailed - no start call Promise for UUID: %s",
callUUID));
JitsiMeetLogger.e(TAG + " startCallFailed - no start call Promise for UUID: " + callUUID);
}
} else {
Log.e(TAG, "onCreateOutgoingConnectionFailed - no call UUID");
JitsiMeetLogger.e(TAG + " onCreateOutgoingConnectionFailed - no call UUID");
}
unregisterPhoneAccount(theAccountHandle);
@@ -295,10 +289,10 @@ public class ConnectionService extends android.telecom.ConnectionService {
if (phoneAccountHandle != null) {
telecom.unregisterPhoneAccount(phoneAccountHandle);
} else {
Log.e(TAG, "unregisterPhoneAccount - account handle is null");
JitsiMeetLogger.e(TAG + " unregisterPhoneAccount - account handle is null");
}
} else {
Log.e(TAG, "unregisterPhoneAccount - telecom is null");
JitsiMeetLogger.e(TAG + " unregisterPhoneAccount - telecom is null");
}
}
@@ -357,7 +351,7 @@ public class ConnectionService extends android.telecom.ConnectionService {
*/
@Override
public void onDisconnect() {
Log.d(TAG, "onDisconnect " + getCallUUID());
JitsiMeetLogger.i(TAG + " onDisconnect " + getCallUUID());
WritableNativeMap data = new WritableNativeMap();
data.putString("callUUID", getCallUUID());
ReactInstanceManagerHolder.emitEvent(
@@ -377,7 +371,7 @@ public class ConnectionService extends android.telecom.ConnectionService {
*/
@Override
public void onAbort() {
Log.d(TAG, "onAbort " + getCallUUID());
JitsiMeetLogger.i(TAG + " onAbort " + getCallUUID());
WritableNativeMap data = new WritableNativeMap();
data.putString("callUUID", getCallUUID());
ReactInstanceManagerHolder.emitEvent(
@@ -395,9 +389,7 @@ public class ConnectionService extends android.telecom.ConnectionService {
// What ?! Android will still call this method even if we do not add
// the HOLD capability, so do the same thing as on abort.
// TODO implement HOLD
Log.d(TAG, String.format(
"onHold %s - HOLD is not supported, aborting the call...",
getCallUUID()));
JitsiMeetLogger.w(TAG + " onHold %s - HOLD is not supported, aborting the call...", getCallUUID());
this.onAbort();
}
@@ -410,12 +402,10 @@ public class ConnectionService extends android.telecom.ConnectionService {
*/
@Override
public void onCallAudioStateChanged(CallAudioState state) {
Log.d(TAG, "onCallAudioStateChanged: " + state);
AudioModeModule audioModeModule
= ReactInstanceManagerHolder
.getNativeModule(AudioModeModule.class);
if (audioModeModule != null) {
audioModeModule.onCallAudioStateChange(state);
JitsiMeetLogger.d(TAG + " onCallAudioStateChanged: " + state);
RNConnectionService module = ReactInstanceManagerHolder.getNativeModule(RNConnectionService.class);
if (module != null) {
module.onCallAudioStateChange(state);
}
}
@@ -426,10 +416,8 @@ public class ConnectionService extends android.telecom.ConnectionService {
*/
@Override
public void onStateChanged(int state) {
Log.d(TAG,
String.format("onStateChanged: %s %s",
Connection.stateToString(state),
getCallUUID()));
JitsiMeetLogger.d(
"%s onStateChanged: %s %s", TAG, Connection.stateToString(state), getCallUUID());
if (state == STATE_DISCONNECTED) {
removeConnection(this);

View File

@@ -16,14 +16,14 @@
package org.jitsi.meet.sdk;
import android.util.Log;
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.facebook.react.module.annotations.ReactModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
/**
* Module implementing an API for sending events from JavaScript to native code.
*/
@@ -76,11 +76,11 @@ class ExternalAPIModule
BaseReactView view = BaseReactView.findViewByExternalAPIScope(scope);
if (view != null) {
Log.d(TAG, "Sending event: " + name + " with data: " + data);
JitsiMeetLogger.d(TAG + " Sending event: " + name + " with data: " + data);
try {
view.onExternalAPIEvent(name, data);
} catch(Exception e) {
Log.e(TAG, "onExternalAPIEvent: error sending event", e);
JitsiMeetLogger.e(e, TAG + " onExternalAPIEvent: error sending event");
}
}
}

View File

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

View File

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

View File

@@ -20,12 +20,13 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import com.facebook.react.modules.core.PermissionListener;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.Map;
@@ -208,19 +209,19 @@ public class JitsiMeetActivity extends FragmentActivity
@Override
public void onConferenceJoined(Map<String, Object> data) {
Log.d(TAG, "Conference joined: " + data);
JitsiMeetLogger.i("Conference joined: " + data);
// Launch the service for the ongoing notification.
JitsiMeetOngoingConferenceService.launch(this);
}
@Override
public void onConferenceTerminated(Map<String, Object> data) {
Log.d(TAG, "Conference terminated: " + data);
JitsiMeetLogger.i("Conference terminated: " + data);
finish();
}
@Override
public void onConferenceWillJoin(Map<String, Object> data) {
Log.d(TAG, "Conference will join: " + data);
JitsiMeetLogger.i("Conference will join: " + data);
}
}

View File

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

View File

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

View File

@@ -23,7 +23,8 @@ import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
/**
@@ -55,7 +56,7 @@ public class JitsiMeetOngoingConferenceService extends Service
componentName = context.startService(intent);
}
if (componentName == null) {
Log.w(TAG, "Ongoing conference service not started");
JitsiMeetLogger.w(TAG + " Ongoing conference service not started");
}
}
@@ -86,24 +87,24 @@ public class JitsiMeetOngoingConferenceService extends Service
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
final String action = intent.getAction();
if (action.equals(Actions.START)) {
if (Actions.START.equals(action)) {
Notification notification = OngoingNotification.buildOngoingConferenceNotification();
if (notification == null) {
stopSelf();
Log.w(TAG, "Couldn't start service, notification is null");
JitsiMeetLogger.w(TAG + " Couldn't start service, notification is null");
} else {
startForeground(OngoingNotification.NOTIFICATION_ID, notification);
Log.i(TAG, "Service started");
JitsiMeetLogger.i(TAG + " Service started");
}
} else if (action.equals(Actions.HANGUP)) {
Log.i(TAG, "Hangup requested");
} else if (Actions.HANGUP.equals(action)) {
JitsiMeetLogger.i(TAG + " Hangup requested");
// Abort all ongoing calls
if (AudioModeModule.useConnectionService()) {
ConnectionService.abortConnections();
}
stopSelf();
} else {
Log.w(TAG, "Unknown action received: " + action);
JitsiMeetLogger.w(TAG + " Unknown action received: " + action);
stopSelf();
}
@@ -114,7 +115,7 @@ public class JitsiMeetOngoingConferenceService extends Service
public void onCurrentConferenceChanged(String conferenceUrl) {
if (conferenceUrl == null) {
stopSelf();
Log.i(TAG, "Service stopped");
JitsiMeetLogger.i(TAG + "Service stopped");
}
}
}

View File

@@ -17,7 +17,7 @@
package org.jitsi.meet.sdk;
import android.util.Log;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
class JitsiMeetUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
private final Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler;
@@ -37,7 +37,7 @@ class JitsiMeetUncaughtExceptionHandler implements Thread.UncaughtExceptionHandl
@Override
public void uncaughtException(Thread t, Throwable e) {
Log.e(this.getClass().getSimpleName(), "FATAL ERROR", e);
JitsiMeetLogger.e(e, this.getClass().getSimpleName() + " FATAL ERROR");
// Abort all ConnectionService ongoing calls
if (AudioModeModule.useConnectionService()) {

View File

@@ -19,12 +19,13 @@ package org.jitsi.meet.sdk;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReadableMap;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.lang.reflect.Method;
import java.util.Map;
@@ -39,12 +40,6 @@ public class JitsiMeetView extends BaseReactView<JitsiMeetViewListener>
private static final Map<String, Method> LISTENER_METHODS
= ListenerUtils.mapListenerMethods(JitsiMeetViewListener.class);
/**
* The {@link Log} tag which identifies the source of the log messages of
* {@code JitsiMeetView}.
*/
private static final String TAG = JitsiMeetView.class.getSimpleName();
/**
* The URL of the current conference.
*/
@@ -137,7 +132,7 @@ public class JitsiMeetView extends BaseReactView<JitsiMeetViewListener>
try {
pipModule.enterPictureInPicture();
} catch (RuntimeException re) {
Log.e(TAG, "failed to enter PiP mode", re);
JitsiMeetLogger.e(re, "Failed to enter PiP mode");
}
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jitsi.meet.sdk;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.module.annotations.ReactModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import javax.annotation.Nonnull;
/**
* Module implementing a "bridge" between the JS loggers and the native one.
*/
@ReactModule(name = LogBridgeModule.NAME)
class LogBridgeModule extends ReactContextBaseJavaModule {
public static final String NAME = "LogBridge";
public LogBridgeModule(@Nonnull ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return NAME;
}
@ReactMethod
public void trace(final String message) {
JitsiMeetLogger.v(message);
}
@ReactMethod
public void debug(final String message) {
JitsiMeetLogger.d(message);
}
@ReactMethod
public void info(final String message) {
JitsiMeetLogger.i(message);
}
@ReactMethod
public void log(final String message) {
JitsiMeetLogger.i(message);
}
@ReactMethod
public void warn(final String message) {
JitsiMeetLogger.w(message);
}
@ReactMethod
public void error(final String message) {
JitsiMeetLogger.e(message);
}
}

View File

@@ -24,7 +24,8 @@ import android.content.Context;
import android.content.Intent;
import android.os.Build;
import androidx.core.app.NotificationCompat;
import android.util.Log;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.Random;
@@ -50,7 +51,7 @@ class OngoingNotification {
Context context = ReactInstanceManagerHolder.getCurrentActivity();
if (context == null) {
Log.w(TAG, "Cannot create notification channel: no current context");
JitsiMeetLogger.w(TAG + " Cannot create notification channel: no current context");
return;
}
@@ -75,7 +76,7 @@ class OngoingNotification {
static Notification buildOngoingConferenceNotification() {
Context context = ReactInstanceManagerHolder.getCurrentActivity();
if (context == null) {
Log.w(TAG, "Cannot create notification: no current context");
JitsiMeetLogger.w(TAG + " Cannot create notification: no current context");
return null;
}

View File

@@ -20,7 +20,6 @@ import android.annotation.TargetApi;
import android.app.Activity;
import android.app.PictureInPictureParams;
import android.os.Build;
import android.util.Log;
import android.util.Rational;
import com.facebook.react.bridge.Promise;
@@ -29,6 +28,8 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.module.annotations.ReactModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
@ReactModule(name = PictureInPictureModule.NAME)
class PictureInPictureModule
extends ReactContextBaseJavaModule {
@@ -70,7 +71,7 @@ class PictureInPictureModule
throw new IllegalStateException("No current Activity!");
}
Log.d(TAG, "Entering Picture-in-Picture");
JitsiMeetLogger.i(TAG + " Entering Picture-in-Picture");
PictureInPictureParams.Builder builder
= new PictureInPictureParams.Builder()

View File

@@ -10,7 +10,6 @@ import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.util.Log;
import androidx.annotation.RequiresApi;
import com.facebook.react.bridge.Promise;
@@ -20,6 +19,8 @@ import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.module.annotations.ReactModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
/**
* The react-native side of Jitsi Meet's {@link ConnectionService}. Exposes
* the Java Script API.
@@ -28,13 +29,18 @@ import com.facebook.react.module.annotations.ReactModule;
*/
@RequiresApi(api = Build.VERSION_CODES.O)
@ReactModule(name = RNConnectionService.NAME)
class RNConnectionService
extends ReactContextBaseJavaModule {
class RNConnectionService extends ReactContextBaseJavaModule {
public static final String NAME = "ConnectionService";
private static final String TAG = ConnectionService.TAG;
/**
* Handler for dealing with call state changes. We are acting as a proxy between ConnectionService
* and other modules such as {@link AudioModeModule}.
*/
private CallAudioStateListener callAudioStateListener;
/**
* Sets the audio route on all existing {@link android.telecom.Connection}s
*
@@ -74,11 +80,11 @@ class RNConnectionService
String handle,
boolean hasVideo,
Promise promise) {
Log.d(TAG,
String.format("startCall UUID=%s, h=%s, v=%s",
JitsiMeetLogger.d("%s startCall UUID=%s, h=%s, v=%s",
TAG,
callUUID,
handle,
hasVideo));
hasVideo);
ReactApplicationContext ctx = getReactApplicationContext();
@@ -118,7 +124,7 @@ class RNConnectionService
*/
@ReactMethod
public void reportCallFailed(String callUUID) {
Log.d(TAG, "reportCallFailed " + callUUID);
JitsiMeetLogger.d(TAG + " reportCallFailed " + callUUID);
ConnectionService.setConnectionDisconnected(
callUUID,
new DisconnectCause(DisconnectCause.ERROR));
@@ -131,7 +137,7 @@ class RNConnectionService
*/
@ReactMethod
public void endCall(String callUUID) {
Log.d(TAG, "endCall " + callUUID);
JitsiMeetLogger.d(TAG + " endCall " + callUUID);
ConnectionService.setConnectionDisconnected(
callUUID,
new DisconnectCause(DisconnectCause.LOCAL));
@@ -143,9 +149,10 @@ class RNConnectionService
* @param callUUID - the call's UUID.
*/
@ReactMethod
public void reportConnectedOutgoingCall(String callUUID) {
Log.d(TAG, "reportConnectedOutgoingCall " + callUUID);
public void reportConnectedOutgoingCall(String callUUID, Promise promise) {
JitsiMeetLogger.d(TAG + " reportConnectedOutgoingCall " + callUUID);
ConnectionService.setConnectionActive(callUUID);
promise.resolve(null);
}
@Override
@@ -166,4 +173,28 @@ class RNConnectionService
public void updateCall(String callUUID, ReadableMap callState) {
ConnectionService.updateCall(callUUID, callState);
}
public CallAudioStateListener getCallAudioStateListener() {
return callAudioStateListener;
}
public void setCallAudioStateListener(CallAudioStateListener callAudioStateListener) {
this.callAudioStateListener = callAudioStateListener;
}
/**
* Handler for call state changes. {@code ConnectionServiceImpl} will call this handler when the
* call audio state changes.
*
* @param callAudioState The current call's audio state.
*/
void onCallAudioStateChange(android.telecom.CallAudioState callAudioState) {
if (callAudioStateListener != null) {
callAudioStateListener.onCallAudioStateChange(callAudioState);
}
}
interface CallAudioStateListener {
void onCallAudioStateChange(android.telecom.CallAudioState callAudioState);
}
}

View File

@@ -34,6 +34,7 @@ import com.facebook.soloader.SoLoader;
import com.oney.WebRTCModule.RTCVideoViewManager;
import com.oney.WebRTCModule.WebRTCModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import org.webrtc.SoftwareVideoDecoderFactory;
import org.webrtc.SoftwareVideoEncoderFactory;
import org.webrtc.VideoDecoderFactory;
@@ -66,7 +67,9 @@ class ReactInstanceManagerHolder {
new AudioModeModule(reactContext),
new DropboxModule(reactContext),
new ExternalAPIModule(reactContext),
new JavaScriptSandboxModule(reactContext),
new LocaleDetector(reactContext),
new LogBridgeModule(reactContext),
new PictureInPictureModule(reactContext),
new ProximityModule(reactContext),
new WiFiStatsModule(reactContext),
@@ -190,7 +193,7 @@ class ReactInstanceManagerHolder {
new com.calendarevents.CalendarEventsPackage(),
new com.corbt.keepawake.KCKeepAwakePackage(),
new com.facebook.react.shell.MainReactPackage(),
new com.oblador.vectoricons.VectorIconsPackage(),
new com.horcrux.svg.SvgPackage(),
new com.ocetnik.timer.BackgroundTimerPackage(),
new com.reactnativecommunity.asyncstorage.AsyncStoragePackage(),
new com.reactnativecommunity.netinfo.NetInfoPackage(),

View File

@@ -19,7 +19,6 @@ package org.jitsi.meet.sdk;
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.util.Log;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
@@ -27,6 +26,7 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.module.annotations.ReactModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import org.json.JSONArray;
import org.json.JSONObject;
@@ -184,17 +184,15 @@ class WiFiStatsModule
}
} catch (SocketException e) {
Log.wtf(TAG,
"Unable to NetworkInterface.getNetworkInterfaces()"
);
JitsiMeetLogger.e(e, TAG + " Unable to NetworkInterface.getNetworkInterfaces()");
}
result.put("addresses", addresses);
promise.resolve(result.toString());
Log.d(TAG, "WiFi stats: " + result.toString());
JitsiMeetLogger.d(TAG + " WiFi stats: " + result.toString());
} catch (Throwable e) {
Log.e(TAG, "Failed to obtain wifi stats", e);
JitsiMeetLogger.e(e, TAG + " Failed to obtain wifi stats");
promise.reject(
new Exception("Failed to obtain wifi stats"));
}

View File

@@ -0,0 +1,49 @@
/*
* 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.log;
import android.util.Log;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.text.MessageFormat;
import timber.log.Timber;
/**
* Base class for all custom log handlers. Implementations must inherit from this class and
* implement a `doLog` method which does the actual logging, in addition with a `getTag` method
* with which to tag all logs coming into this logger.
*
* See {@link JitsiMeetDefaultLogHandler} for an example.
*/
public abstract class JitsiMeetBaseLogHandler extends Timber.Tree {
@Override
protected void log(int priority, @Nullable String tag, @NotNull String msg, @Nullable Throwable t) {
String errmsg = Log.getStackTraceString(t);
if (errmsg.isEmpty()) {
doLog(priority, getDefaultTag(), msg);
} else {
doLog(priority, getDefaultTag(), MessageFormat.format("{0}\n{1}", msg, errmsg));
}
}
protected abstract void doLog(int priority, @NotNull String tag, @NotNull String msg);
protected abstract String getDefaultTag();
}

View File

@@ -0,0 +1,39 @@
/*
* 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.log;
import android.util.Log;
import org.jetbrains.annotations.NotNull;
/**
* Default implementation of a {@link JitsiMeetBaseLogHandler}. This is the main SDK logger, which
* logs using the Android util.Log module.
*/
public class JitsiMeetDefaultLogHandler extends JitsiMeetBaseLogHandler {
private static final String TAG = "JitsiMeetSDK";
@Override
protected void doLog(int priority, @NotNull String tag, @NotNull String msg) {
Log.println(priority, tag, msg);
}
@Override
protected String getDefaultTag() {
return TAG;
}
}

View File

@@ -0,0 +1,94 @@
/*
* 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.log;
import timber.log.Timber;
public class JitsiMeetLogger {
static {
addHandler(new JitsiMeetDefaultLogHandler());
}
public static void addHandler(JitsiMeetBaseLogHandler handler) {
Timber.plant(handler);
}
public static void removeHandler(JitsiMeetBaseLogHandler handler) {
Timber.uproot(handler);
}
public static void v(String message, Object... args) {
Timber.v(message, args);
}
public static void v(Throwable t, String message, Object... args) {
Timber.v(t, message, args);
}
public static void v(Throwable t) {
Timber.v(t);
}
public static void d(String message, Object... args) {
Timber.d(message, args);
}
public static void d(Throwable t, String message, Object... args) {
Timber.d(t, message, args);
}
public static void d(Throwable t) {
Timber.d(t);
}
public static void i(String message, Object... args) {
Timber.i(message, args);
}
public static void i(Throwable t, String message, Object... args) {
Timber.i(t, message, args);
}
public static void i(Throwable t) {
Timber.i(t);
}
public static void w(String message, Object... args) {
Timber.w(message, args);
}
public static void w(Throwable t, String message, Object... args) {
Timber.w(t, message, args);
}
public static void w(Throwable t) {
Timber.w(t);
}
public static void e(String message, Object... args) {
Timber.e(message, args);
}
public static void e(Throwable t, String message, Object... args) {
Timber.e(t, message, args);
}
public static void e(Throwable t) {
Timber.e(t);
}
}

View File

@@ -15,14 +15,14 @@
*/
package org.jitsi.meet.sdk.net;
import android.util.Log;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.module.annotations.ReactModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.net.UnknownHostException;
/**
@@ -43,7 +43,7 @@ public class NAT64AddrInfoModule
* The host for which the module wil try to resolve both IPv4 and IPv6
* addresses in order to figure out the NAT64 prefix.
*/
private final static String HOST = "nat64.jitsi.net";
private final static String HOST = "ipv4only.arpa";
/**
* How long is the {@link NAT64AddrInfo} instance valid.
@@ -97,7 +97,7 @@ public class NAT64AddrInfoModule
try {
info = NAT64AddrInfo.discover(host);
} catch (UnknownHostException e) {
Log.e(TAG, "NAT64AddrInfo.discover: " + host, e);
JitsiMeetLogger.e(e, TAG + " NAT64AddrInfo.discover: " + host);
}
infoTimestamp = System.currentTimeMillis();
}
@@ -107,7 +107,7 @@ public class NAT64AddrInfoModule
try {
result = info == null ? null : info.getIPv6Address(ipv4Address);
} catch (IllegalArgumentException exc) {
Log.e(TAG, "Failed to get IPv6 address for: " + ipv4Address, exc);
JitsiMeetLogger.e(exc, TAG + " Failed to get IPv6 address for: " + ipv4Address);
// We don't want to reject. It's not a big deal if there's no IPv6
// address resolved.

View File

@@ -10,7 +10,7 @@ project(':react-native-community-async-storage').projectDir = new File(rootProje
include ':react-native-community_netinfo'
project(':react-native-community_netinfo').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/netinfo/android')
include ':react-native-google-signin'
project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-google-signin/android')
project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/google-signin/android')
include ':react-native-immersive'
project(':react-native-immersive').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-immersive/android')
include ':react-native-keep-awake'
@@ -19,8 +19,8 @@ include ':react-native-linear-gradient'
project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android')
include ':react-native-sound'
project(':react-native-sound').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-sound/android')
include ':react-native-vector-icons'
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')
include ':react-native-svg'
project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-svg/android')
include ':react-native-webrtc'
project(':react-native-webrtc').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webrtc/android')
include ':react-native-webview'

View File

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

View File

@@ -1,16 +1,6 @@
/* eslint-disable no-unused-vars, no-var */
var config = {
// Configuration
//
// Alternative location for the configuration.
// configLocation: './config.json',
// Custom function which given the URL path should return a room name.
// getroomnode: function (path) { return 'someprefixpossiblybasedonpath'; },
// Connection
//
@@ -60,6 +50,10 @@ var config = {
// Enables the test specific features consumed by jitsi-meet-torture
// testMode: false
// Disables the auto-play behavior of *all* newly created video element.
// This is useful when the client runs on a host with limited resources.
// noAutoPlayVideo: false
},
// Disables ICE/UDP by filtering out local and remote UDP candidates in
@@ -123,10 +117,6 @@ var config = {
// are requested again.
// enableLayerSuspension: false,
// Suspend sending video if bandwidth estimation is too low. This may cause
// problems with audio playback. Disabled until these are fixed.
disableSuspendVideo: true,
// Every participant after the Nth will start video muted.
// startVideoMuted: 10,
@@ -429,6 +419,16 @@ var config = {
// the menu has option to flip the locally seen video for local presentations
// disableLocalVideoFlip: false
// Deployment specific URLs.
// deploymentUrls: {
// // If specified a 'Help' button will be displayed in the overflow menu with a link to the specified URL for
// // user documentation.
// userDocumentationURL: 'https://docs.example.com/video-meetings.html',
// // If specified a 'Download our apps' button will be displayed in the overflow menu with a link
// // to the specified URL for an app download page.
// downloadAppsUrl: 'https://docs.example.com/our-apps.html'
// }
// List of undocumented settings used in jitsi-meet
/**
_immediateReloadThreshold

View File

@@ -33,6 +33,10 @@ body {
}
}
.jitsi-icon svg {
fill: white;
}
/**
* AtlasKitThemeProvider sets a background color on an app-wrapping div, thereby
* preventing transparency in filmstrip-only mode. The selector chosen to

View File

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

View File

@@ -1,235 +0,0 @@
@font-face {
font-family: 'jitsi';
src: url('../fonts/jitsi.eot?icrce1');
src: url('../fonts/jitsi.eot?icrce1#iefix') format('embedded-opentype'),
url('../fonts/jitsi.ttf?icrce1') format('truetype'),
url('../fonts/jitsi.woff?icrce1') format('woff'),
url('../fonts/jitsi.svg?icrce1#jitsi') format('svg');
font-weight: normal;
font-style: normal;
}
[class^="icon-"], [class*=" icon-"] {
font-family: 'jitsi';
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1.22em;
font-size: 1.22em;
cursor: default;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-cancel:before {
content: "\e91c";
}
.icon-check:before {
content: "\e91b";
}
.icon-send:before {
content: "\e911";
}
.icon-blur-background:before {
content: "\e90f";
color: #a4b8d1;
}
.icon-speaker:before {
content: "\e92d";
}
.icon-rec:before {
content: "\e92b";
}
.icon-camera-take-picture:before {
content: "\e92a";
}
.icon-AUD:before {
content: "\e900";
}
.icon-HD:before {
content: "\e927";
}
.icon-LD:before {
content: "\e928";
}
.icon-SD:before {
content: "\e929";
}
.icon-gsm-bars:before {
content: "\e926";
}
.icon-info:before {
content: "\e922";
}
.icon-mic-camera-combined:before {
content: "\e903";
}
.icon-feedback:before {
content: "\e91d";
}
.icon-hangup:before {
content: "\e905";
}
.icon-chat:before {
content: "\e906";
}
.icon-share-doc:before {
content: "\e908";
}
.icon-kick:before {
content: "\e904";
}
.icon-menu-up:before {
content: "\e91f";
}
.icon-menu-down:before {
content: "\e920";
}
.icon-full-screen:before {
content: "\e90b";
}
.icon-exit-full-screen:before {
content: "\e90c";
}
.icon-security:before {
content: "\e90d";
}
.icon-security-locked:before {
content: "\e90e";
}
.icon-microphone:before {
content: "\e910";
}
.icon-mic-disabled:before {
content: "\e912";
}
.icon-raised-hand:before {
content: "\e91e";
}
.icon-link:before {
content: "\e913";
}
.icon-shared-video:before {
content: "\e914";
}
.icon-settings:before {
content: "\e915";
}
.icon-star:before {
content: "\e916";
}
.icon-switch-camera:before {
content: "\e921";
}
.icon-share-desktop:before {
content: "\e917";
}
.icon-camera:before {
content: "\e918";
}
.icon-camera-disabled:before {
content: "\e919";
}
.icon-volume:before {
content: "\e91a";
}
.icon-presentation:before {
content: "\e603";
}
.icon-visibility:before {
content: "\e923";
}
.icon-visibility-off:before {
content: "\e924";
}
.icon-enlarge:before {
content: "\e90a";
}
.icon-signal_cellular_0:before {
content: "\e901";
}
.icon-signal_cellular_1:before {
content: "\e902";
}
.icon-signal_cellular_2:before {
content: "\e907";
}
.icon-phone:before {
content: "\e0cd";
}
.icon-radio_button_unchecked:before {
content: "\e836";
}
.icon-radio_button_checked:before {
content: "\e837";
}
.icon-search:before {
content: "\e8b6";
}
.icon-chat-unread:before {
content: "\e0b7";
}
.icon-closed_caption:before {
content: "\e930";
}
.icon-tiles-many:before {
content: "\e92e";
}
.icon-close:before {
content: "\e5cd";
}
.icon-open_in_new:before {
content: "\e89e";
}
.icon-restore:before {
content: "\e8b3";
}
.icon-navigate_next:before {
content: "\e409";
}
.icon-menu:before {
content: "\e5d2";
}
.icon-arrow_back:before {
content: "\e5c4";
}
.icon-public:before {
content: "\e80b";
}
.icon-event_note:before {
content: "\e616";
}
.icon-bluetooth:before {
content: "\e1aa";
}
.icon-headset:before {
content: "\e310";
}
.icon-phone-talk:before {
content: "\e61d";
}
.icon-thumb-menu:before {
content: "\e5d4";
}
.icon-ninja:before {
content: "\e909";
}
.icon-invite:before {
content: "\e145";
}
.icon-add:before {
content: "\e146";
}
.icon-play:before {
content: "\f04b";
}
.icon-stop:before {
content: "\f04d";
}
.icon-dominant-speaker:before {
content: "\f0a1";
}

66
css/_mini_toolbox.scss Normal file
View File

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

View File

@@ -0,0 +1,26 @@
.participants-count {
background: #fff;
border-radius: 4px;
color: #5e6d7a;
cursor: pointer;
display: inline-block;
font-size: 13px;
line-height: 20px;
margin-left: 16px;
padding: 4px 8px;
pointer-events: auto;
&-number {
margin-right: 8px;
vertical-align: middle;
}
&-icon {
background: url('../images/user-groups.svg');
background-repeat: no-repeat;
display: inline-block;
height: 16px;
width: 16px;
vertical-align: middle;
}
}

View File

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

View File

@@ -0,0 +1 @@
/** Insert custom CSS for any additional content in the promotional footer **/

View File

@@ -9,7 +9,7 @@
text-align: center;
font-size: 17px;
color: #fff;
z-index: $toolbarBackgroundZ;
z-index: $zindex10;
overflow: hidden;
text-overflow: ellipsis;
box-sizing: border-box;
@@ -19,4 +19,8 @@
&.visible {
top: 0px;
}
&-text {
vertical-align: middle;
}
}

View File

@@ -73,8 +73,62 @@
.button-group-center {
justify-content: center;
.toolbox-icon {
margin: 0px 4px;
.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;
}
}
}
}
}
@@ -82,75 +136,6 @@
justify-content: flex-end;
}
i {
border-radius: 5px;
cursor: pointer;
display: block;
font-size: inherit;
height: 100%;
line-height: inherit;
width: 100%;
}
i:hover {
background: $newToolbarButtonHoverColor;
}
i.toggled {
background: $newToolbarButtonToggleColor;
}
i.toggled:hover {
background: $newToolbarButtonHoverColor;
}
.icon-hangup {
background-color: #e12d2d;
color: #fff;
border-radius: 50%;
width: 40px;
height: 40px;
&:hover {
background-color: #e54b4b;
}
}
i.disabled, .disabled i {
cursor: initial !important;
color: #fff !important;
background-color: #a4b8d1 !important;
}
.icon-mic-disabled, .icon-microphone, .icon-camera-disabled, .icon-camera {
background-color: #fff;
color: #5e6d7a;
border-radius: 50%;
border: 1px solid #d1dbe8;
width: 38px;
height: 38px;
&:hover {
background-color: #daebfa;
border: 1px solid #daebfa;
}
&.toggled {
background: #2a3a4b;
color: #fff;
border: 1px solid #5e6d7a;
&:hover {
background-color: #5e6d7a;
}
}
&.disabled, .disabled & {
cursor: initial;
color: #fff;
background-color: #a4b8d1;
}
}
.overflow-menu {
font-size: 1.2em;
list-style-type: none;
@@ -191,14 +176,6 @@
cursor: initial;
color: #3b475c;
}
i.toggled {
background: inherit;
}
i.toggled:hover {
background: inherit;
}
}
.beta-tag {
@@ -227,6 +204,10 @@
max-width: 24px;
max-height: 24px;
}
svg {
fill: #B8C7E0 !important;
}
}
.profile-text {
@@ -265,104 +246,30 @@
}
.toolbox-icon {
height: $newToolbarSize;
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;
}
}
}
}
}
.always-on-top-toolbox,
.filmstrip-toolbox {
background-color: $newToolbarBackgroundColor;
box-sizing: border-box;
display: flex;
flex-direction: column;
z-index: $toolbarZ;
i {
cursor: pointer;
display: block;
}
i:hover {
background-color: $AOTToolbarButtonHoverColor;
}
i.toggled {
background: $AOTToolbarButtonToggleColor;
}
i.toggled:hover:not(.disabled) {
background-color: $AOTToolbarButtonHoverColor;
}
.icon-hangup {
color: $hangupColor;
}
.toolbox-button {
color: $toolbarButtonColor;
cursor: pointer;
text-align: center;
}
border-radius: 3px;
}
.always-on-top-toolbox {
flex-direction: row;
left: 50%;
position: absolute;
top: 10px;
transform: translateX(-50%);
z-index: $toolbarZ;
i {
font-size: $newToolbarFontSize;
height: $newToolbarSize;
line-height: $newToolbarSize;
width: $newToolbarSize;
}
.icon-hangup {
font-size: $newToolbarHangupFontSize;
}
.disabled {
cursor: initial;
}
.toolbox-button:first-child i {
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}
.toolbox-button:last-child i {
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
}
.filmstrip-toolbox {
i {
font-size: 1.9em;
height: 37px;
line-height: 37px;
width: 37px;
}
.toolbox-button:first-child i {
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
.toolbox-button:last-child i {
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
}
}
/**
* START of fade in animation for main toolbar
*/

View File

@@ -28,6 +28,7 @@ $defaultColor: #F1F1F1;
$defaultSideBarFontColor: #44A5FF;
$defaultSemiDarkColor: #ACACAC;
$defaultDarkColor: #2b3d5c;
$defaultWarningColor: rgb(215, 121, 118);
/**
* Toolbar
@@ -85,10 +86,12 @@ $modalTextColor: #333;
/**
* Chat
*/
$chatActionsSeparatorColor: rgb(173, 105, 112);
$chatHeaderBackgroundColor: rgba(42, 58, 75, 0.9);
$chatInputSeparatorColor: #A4B8D1;
$chatLocalMessageBackgroundColor: rgba(26, 108, 180, 1);
$chatRemoteMessageBackgroundColor: rgba(240, 243, 247, 0.15);
$chatLocalMessageBackgroundColor: rgb(4, 98, 178);
$chatPrivateMessageBackgroundColor: rgb(153, 69, 77);
$chatRemoteMessageBackgroundColor: rgb(86, 101, 114);
$sidebarWidth: 375px;
/**
@@ -163,11 +166,93 @@ $watermarkHeight: 74px;
*/
$welcomePageDescriptionColor: #fff;
$welcomePageFontFamily: inherit;
$welcomePageHeaderBackground: linear-gradient(-90deg, #1251AE 0%, #0074FF 50%, #1251AE 100%);
$welcomePageBackground: linear-gradient(-90deg, #1251AE 0%, #0074FF 50%, #1251AE 100%);
$welcomePageTitleColor: #fff;
$welcomePageHeaderBackground: none;
$welcomePageHeaderBackgroundSmall: none;
$welcomePageHeaderBackgroundPosition: none;
$welcomePageHeaderBackgroundRepeat: none;
$welcomePageHeaderBackgroundSize: none;
$welcomePageHeaderPaddingBottom: 0px;
$welcomePageHeaderTextMarginTop: 35px;
$welcomePageHeaderTextMarginBottom: 35px;
$welcomePageHeaderTextTitleMarginBottom: 16px;
$welcomePageHeaderTextTitleFontSize: 2.5rem;
$welcomePageHeaderTextTitleFontWeight: 500;
$welcomePageHeaderTextTitleLineHeight: 1.18;
$welcomePageHeaderTextTitleOpacity: 1;
$welcomePageHeaderTextDescriptionDisplay: inherit;
$welcomePageHeaderTextDescriptionFontSize: 1rem;
$welcomePageHeaderTextDescriptionFontWeight: 400;
$welcomePageHeaderTextDescriptionLineHeight: 24px;
$welcomePageHeaderTextDescriptionMarginBottom: 20px;
$welcomePageHeaderTextDescriptionAlignSelf: inherit;
$welcomePageEnterRoomWidth: 680px;
$welcomePageEnterRoomPadding: 25px 30px;
$welcomePageEnterRoomBorderRadius: 0px;
$welcomePageEnterRoomInputContainerPadding: 0 8px 5px 0px;
$welcomePageEnterRoomInputContainerBorderWidth: 0px 0px 2px 0px;
$welcomePageEnterRoomInputContainerBorderStyle: solid;
$welcomePageEnterRoomInputContainerBorderImage: linear-gradient(to right, #dee1e6, #fff) 1;
$welcomePageEnterRoomTitleDisplay: inherit;
$welcomePageTabContainerDisplay: flex;
$welcomePageTabContentDisplay: inherit;
$welcomePageTabButtonsDisplay: flex;
$welcomePageTabDisplay: block;
$welcomePageButtonWidth: 51px;
$welcomePageButtonMinWidth: inherit;
$welcomePageButtonFontSize: 14px;
$welcomePageButtonHeight: 35px;
$welcomePageButtonFontWeight: inherit;
$welcomePageButtonBorderRadius: 4px;
$welcomePageButtonLineHeight: 35px;
/**
* Deep-linking page variables.
*/
$deepLinkingMobileLogoHeight: 40px;
$deepLinkingMobileHeaderBackground: #f1f2f5;
$deepLinkingMobileLinkColor: inherit;
$deepLinkingMobileTextFontSize: inherit;
$deepLinkingMobileTextLineHeight: inherit;
$deepLinkingDialInConferenceIdMargin: 10px 0 10px 0;
$deepLinkingDialInConferenceIdPadding: inherit;
$deepLinkingDialInConferenceIdBackgroundColor: inherit;
$deepLinkingDialInConferenceIdBorderRadius: inherit;
$deepLinkingDialInConferenceNameFontSize: inherit;
$deepLinkingDialInConferenceNameLineHeight: inherit;
$deepLinkingDialInConferenceNameMarginBottom: none;
$deepLinkingDialInConferenceNameFontWeight: inherit;
$deepLinkingDialInConferenceDescriptionFontSize: 0.8em;
$deepLinkingDialInConferenceDescriptionLineHeight: inherit;
$deepLinkingDialInConferenceDescriptionMarginBottom: none;
$deepLinkingDialInConferencePinFontSize: inherit;
$deepLinkingDialInConferencePinLineHeight: inherit;
$depLinkingMobileHrefLineHeight: 2.2857142857142856em;
$deepLinkingMobileHrefFontWeight: bolder;
$deepLinkingMobileHrefFontSize: inherit;
$deepLinkingMobileButtonHeight: 2.2857142857142856em;
$deepLinkingMobileButtonLineHeight: 2.2857142857142856em;
$deepLinkingMobileButtonMargin: 18px auto 10px;
$deepLinkingMobileButtonWidth: auto;
$deepLinkingMobileButtonFontWeight: bold;
$deepLinkingMobileButtonFontSize: inherit;
$primaryDeepLinkingMobileButtonBorderRadius: inherit;

View File

@@ -344,8 +344,11 @@
/**
* Toolbar icon internal i elements (font icons).
*/
.toolbar-icon>i {
line-height: $thumbnailToolbarHeight;
.toolbar-icon>div {
height: $thumbnailToolbarHeight;
display: flex;
flex-direction: column;
justify-content: center;
}
/**

View File

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

View File

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

View File

@@ -19,7 +19,8 @@
}
a {
text-decoration: none
text-decoration: none;
color: $deepLinkingMobileLinkColor;
}
&__body {
@@ -41,6 +42,8 @@
&__text {
font-weight: bolder;
font-size: $deepLinkingMobileTextFontSize;
line-height: $deepLinkingMobileTextLineHeight;
padding: 10px 10px 0px 10px;
}
@@ -65,11 +68,28 @@
}
.dial-in-conference-id {
margin: 10px 0 10px 0;
margin: $deepLinkingDialInConferenceIdMargin;
padding: $deepLinkingDialInConferenceIdPadding;
background-color: $deepLinkingDialInConferenceIdBackgroundColor;
border-radius: $deepLinkingDialInConferenceIdBorderRadius;
}
.dial-in-conference-name {
font-size: $deepLinkingDialInConferenceNameFontSize;
line-height: $deepLinkingDialInConferenceNameLineHeight;
margin-bottom: $deepLinkingDialInConferenceNameMarginBottom;
font-weight: $deepLinkingDialInConferenceNameFontWeight;
}
.dial-in-conference-description {
font-size: 0.8em;
font-size: $deepLinkingDialInConferenceDescriptionFontSize;
line-height: $deepLinkingDialInConferenceDescriptionLineHeight;
margin-bottom: $deepLinkingDialInConferenceDescriptionMarginBottom;
}
.dial-in-conference-pin {
font-size: $deepLinkingDialInConferencePinFontSize;
line-height: $deepLinkingDialInConferencePinLineHeight;
}
.toll-free-list {
@@ -88,25 +108,27 @@
&__href {
height: 2.2857142857142856em;
line-height: 2.2857142857142856em;
line-height: $depLinkingMobileHrefLineHeight;
margin: 18px auto 20px;
max-width: 300px;
width: auto;
font-weight: bolder;
font-weight: $deepLinkingMobileHrefFontWeight;
font-size: $deepLinkingMobileHrefFontSize;
}
&__button {
border: 0;
height: 2.2857142857142856em;
line-height: 2.2857142857142856em;
margin: 18px auto 10px;
height: $deepLinkingMobileButtonHeight;
line-height: $deepLinkingMobileButtonLineHeight;
margin: $deepLinkingMobileButtonMargin;
padding: 0px 10px 0px 10px;
max-width: 300px;
width: auto;
width: $deepLinkingMobileButtonWidth;
@include border-radius(3px);
background-color: $unsupportedBrowserButtonBgColor;
color: #505F79;
font-weight: bold;
font-weight: $deepLinkingMobileButtonFontWeight;
font-size: $deepLinkingMobileButtonFontSize;
&:active {
background-color: $unsupportedBrowserButtonBgColor;
@@ -115,7 +137,7 @@
&_primary {
background-color: $primaryUnsupportedBrowserButtonBgColor;
color: #FFFFFF;
border-radius: $primaryDeepLinkingMobileButtonBorderRadius;
&:active {
background-color: $primaryUnsupportedBrowserButtonBgColor;
}

View File

@@ -23,12 +23,6 @@ $flagsImagePath: "../images/";
@import "../node_modules/bc-css-flags/dist/css/bc-css-flags.scss";
/* Flags END */
/* Fonts BEGIN */
@import 'font';
/* Fonts END */
/* Modules BEGIN */
@import 'aui_reset';
@@ -38,6 +32,7 @@ $flagsImagePath: "../images/";
@import 'overlay/overlay';
@import 'inlay';
@import 'reload_overlay/reload_overlay';
@import 'mini_toolbox';
@import 'modals/desktop-picker/desktop-picker';
@import 'modals/device-selection/device-selection';
@import 'modals/dialog';
@@ -50,6 +45,7 @@ $flagsImagePath: "../images/";
@import 'videolayout_default';
@import 'notice';
@import 'subject';
@import 'participants-count';
@import 'popup_menu';
@import 'recording';
@import 'login_menu';
@@ -57,6 +53,7 @@ $flagsImagePath: "../images/";
@import 'ringing/ringing';
@import 'welcome_page';
@import 'welcome_page_content';
@import 'welcome_page_settings_toolbar';
@import 'toolbars';
@import 'jquery.contextMenu';
@import 'keyboard-shortcuts';
@@ -87,5 +84,6 @@ $flagsImagePath: "../images/";
@import 'third-party-branding/google';
@import 'third-party-branding/microsoft';
@import 'avatar';
@import 'promotional-footer';
/* Modules END */

View File

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

View File

@@ -1,12 +0,0 @@
### Adding an icon to the font file (e.g. for the floating menu)
1. Go to https://icomoon.io/app/
2. Go to "Manage Projects" from the menu on the top left.
3. Use "Import project" and select <code>fonts/selection.json</code> from Jitsi Meet.
4. Click "load".
5. Add the new icons using the "Add icons from library" button...
6. Go to "generate font" and make sure the identifiers for the new icons are correct.
7. Download the result in a zip file using the "download" button.
8. Copy <code>selection.json</code> and <code>fonts/jitsi.*</code> from the zip file to <code>fonts/</code> in Jitsi Meet
9. Copy the class for the new icon from <code>style.css</code> in the zip file to <code>css/_font.scss</code> in Jitsi Meet (do *not* copy the whole file)
Sample commit: https://github.com/jitsi/jitsi-meet/commit/68bc819b89aec12364fcf07b81efa83a1900eed6

View File

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

78
doc/development.md Normal file
View File

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

View File

@@ -0,0 +1,14 @@
var subdomain = "<!--# echo var="subdomain" default="" -->";
if (subdomain) {
subdomain = subdomain.substr(0,subdomain.length-1).split('.').join('_').toLowerCase() + '.';
}
var config = {
hosts: {
domain: 'jitsi.example.com',
muc: 'conference.'+subdomain+'jitsi.example.com', // FIXME: use XEP-0030
focus: 'focus.jitsi.example.com',
},
useNicks: false,
bosh: '//jitsi.example.com/http-bind' // FIXME: use xep-0156 for that
};

View File

@@ -0,0 +1,67 @@
server {
listen 80;
server_name jitsi.example.com;
# set the root
root /srv/jitsi.example.com;
# ssi on with javascript for multidomain variables in config.js
ssi on;
ssi_types application/x-javascript application/javascript;
index index.html;
set $prefix "";
# BOSH
location /http-bind {
proxy_pass http://localhost:5280/http-bind;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
}
# xmpp websockets
location /xmpp-websocket {
proxy_pass http://localhost:5280/xmpp-websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
tcp_nodelay on;
}
location ~ ^/([^/?&:'"]+)$ {
try_files $uri @root_path;
}
location @root_path {
rewrite ^/(.*)$ / break;
}
location / {
ssi on;
}
location ~ ^/([^/?&:'"]+)/config.js$
{
set $subdomain "$1.";
set $subdir "$1/";
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 /
location ~ ^/([^/?&:'"]+)/(.*)$ {
set $subdomain "$1.";
set $subdir "$1/";
rewrite ^/([^/?&:'"]+)/(.*)$ /$2;
}
# BOSH for subdomains
location ~ ^/([^/?&:'"]+)/http-bind {
set $subdomain "$1.";
set $subdir "$1/";
set $prefix "$1";
rewrite ^/(.*)$ /http-bind;
}
}

View File

@@ -0,0 +1,220 @@
-- Prosody XMPP Server Configuration
--
-- Information on configuring Prosody can be found on our
-- website at http://prosody.im/doc/configure
--
-- Tip: You can check that the syntax of this file is correct
-- when you have finished by running: prosodyctl check config
-- If there are any errors, it will let you know what and where
-- they are, otherwise it will keep quiet.
--
-- Good luck, and happy Jabbering!
---------- Server-wide settings ----------
-- Settings in this section apply to the whole server and are the default settings
-- for any virtual hosts
-- This is a (by default, empty) list of accounts that are admins
-- for the server. Note that you must create the accounts separately
-- (see http://prosody.im/doc/creating_accounts for info)
-- Example: admins = { "user1@example.com", "user2@example.net" }
admins = { }
daemonize = true
cross_domain_bosh = true;
component_ports = { 5347 }
--component_interface = "192.168.0.10"
-- Enable use of libevent for better performance under high load
-- For more information see: http://prosody.im/doc/libevent
--use_libevent = true
-- This is the list of modules Prosody will load on startup.
-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too.
-- Documentation 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.
-- 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)
-- 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
-- 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";
-- include domain mapper as global level module
"muc_domain_mapper";
}
-- domain mapper options, must at least have domain base set to use the mapper
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
}
-- Disable account creation by default, for security
-- For more information see http://prosody.im/doc/creating_accounts
allow_registration = false
-- These are the SSL/TLS-related settings. If you don't want
-- to use SSL/TLS, you may comment or remove this
ssl = {
key = "/etc/prosody/certs/localhost.key";
certificate = "/etc/prosody/certs/localhost.crt";
}
-- Force clients to use encrypted connections? This option will
-- prevent clients from authenticating unless they are using encryption.
-- c2s_require_encryption = true
-- Force certificate authentication for server-to-server connections?
-- This provides ideal security, but requires servers you communicate
-- with to support encryption AND present valid, trusted certificates.
-- NOTE: Your version of LuaSec must support certificate verification!
-- For more information see http://prosody.im/doc/s2s#security
-- 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
-- authenticate using certificates. They will be authenticated using DNS.
--s2s_insecure_domains = { "gmail.com" }
-- Even if you leave s2s_secure_auth disabled, you can still require valid
-- certificates for some domains by specifying a list here.
--s2s_secure_domains = { "jabber.org" }
-- Required for init scripts and prosodyctl
pidfile = "/var/run/prosody/prosody.pid"
-- Select the authentication backend to use. The 'internal' providers
-- use Prosody's configured data storage to store the authentication data.
-- To allow Prosody to offer secure authentication mechanisms to clients, the
-- default provider stores passwords in plaintext. If you do not trust your
-- 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
-- in its configured data directory, but it also supports more backends
-- through modules. An "sql" backend is included by default, but requires
-- additional dependencies. See http://prosody.im/doc/storage for more info.
--storage = "sql" -- Default is "internal"
-- For the "sql" backend, you can uncomment *one* of the below to configure:
--sql = { driver = "SQLite3", database = "prosody.sqlite" } -- Default. 'database' is the filename.
--sql = { driver = "MySQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" }
--sql = { driver = "PostgreSQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" }
-- 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";
}
----------- Virtual hosts -----------
-- You need to add a VirtualHost entry for each domain you wish Prosody to serve.
-- Settings under each VirtualHost entry apply *only* to that host.
--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";
}
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"
------ Components ------
-- You can specify components to add hosts that provide special services,
-- like multi-user conferences, and transports.
-- For more information on components, see http://prosody.im/doc/components
---Set up a MUC (multi-user chat) room server on conference.example.com:
--Component "conference.example.com" "muc"
-- Set up a SOCKS5 bytestream proxy for server-proxied file transfers:
--Component "proxy.example.com" "proxy65"
---Set up an external component (default component port is 5347)
--
-- External components allow adding various services, such as gateways/
-- transports to other networks like ICQ, MSN and Yahoo. For more info
-- see: http://prosody.im/doc/components#adding_an_external_component
--
--Component "gateway.example.com"
-- component_secret = "password"
Component "conference.jitsi.example.com" "muc"
modules_enabled = { "muc_domain_mapper" }
Component "jitsi-videobridge.jitsi.example.com"
component_secret = "IfGaish6"

View File

@@ -210,6 +210,7 @@ Checkout and configure Jitsi Meet:
cd /srv
git clone https://github.com/jitsi/jitsi-meet.git
mv jitsi-meet/ jitsi.example.com
cd jitsi.example.com
npm install
make
```

Binary file not shown.

View File

@@ -1,79 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="jitsi" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="1024" descent="0" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" d="" />
<glyph unicode="&#xe0b7;" glyph-name="chat-unread" d="M768 682v86h-512v-86h512zM598 426v86h-342v-86h342zM256 640v-86h512v86h-512zM854 938c46 0 84-38 84-84v-512c0-46-38-86-84-86h-598l-170-170v768c0 46 38 84 84 84h684z" />
<glyph unicode="&#xe0cd;" glyph-name="phone" d="M282 564c62-120 162-220 282-282l94 94c12 12 30 16 44 10 48-16 100-24 152-24 24 0 42-18 42-42v-150c0-24-18-42-42-42-400 0-726 326-726 726 0 24 18 42 42 42h150c24 0 42-18 42-42 0-54 8-104 24-152 4-14 2-32-10-44z" />
<glyph unicode="&#xe145;" glyph-name="invite" d="M810 470h-256v-256h-84v256h-256v84h256v256h84v-256h256v-84z" />
<glyph unicode="&#xe146;" glyph-name="add" d="M810 470h-256v-256h-84v256h-256v84h256v256h84v-256h256v-84z" />
<glyph unicode="&#xe1aa;" glyph-name="bluetooth" d="M550 328l-80 82v-162zM470 776v-162l80 82zM670 696l-184-184 184-184-244-242h-42v324l-196-196-60 60 238 238-238 238 60 60 196-196v324h42zM834 738c40-64 62-142 62-222 0-84-24-160-66-226l-50 50c26 52 42 110 42 172s-16 120-42 172zM608 512l98 98c12-30 20-64 20-98s-8-70-20-100z" />
<glyph unicode="&#xe310;" glyph-name="headset" d="M512 982c212 0 384-172 384-384v-300c0-70-58-128-128-128h-128v342h170v86c0 166-132 298-298 298s-298-132-298-298v-86h170v-342h-128c-70 0-128 58-128 128v300c0 212 172 384 384 384z" />
<glyph unicode="&#xe409;" glyph-name="navigate_next" d="M426 768l256-256-256-256-60 60 196 196-196 196z" />
<glyph unicode="&#xe5c4;" glyph-name="arrow_back" d="M854 554v-84h-520l238-240-60-60-342 342 342 342 60-60-238-240h520z" />
<glyph unicode="&#xe5cd;" glyph-name="close" d="M810 750l-238-238 238-238-60-60-238 238-238-238-60 60 238 238-238 238 60 60 238-238 238 238z" />
<glyph unicode="&#xe5d2;" glyph-name="menu" d="M128 768h768v-86h-768v86zM128 470v84h768v-84h-768zM128 256v86h768v-86h-768z" />
<glyph unicode="&#xe5d4;" glyph-name="thumb-menu" d="M512 342c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM512 598c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM512 682c-46 0-86 40-86 86s40 86 86 86 86-40 86-86-40-86-86-86z" />
<glyph unicode="&#xe603;" glyph-name="presentation" horiz-adv-x="1088" d="M952.495 1019.065h-818.689c-72.81 0-132.183-60.63-132.183-135.162v-750.719c0-74.473 59.372-135.101 132.183-135.101h818.686c72.936 0 132.314 60.625 132.314 135.101v750.722c0.003 74.532-59.378 135.159-132.311 135.159zM946.346 139.651h-806.14v737.822h806.015l0.126-737.822zM685.753 738.544h216.911v-566.758h-216.911v566.758zM428.672 610.002h216.911v-438.216h-216.911v438.216zM172.339 481.46h216.161v-309.677h-216.161v309.677z" />
<glyph unicode="&#xe616;" glyph-name="event_note" d="M598 426v-84h-300v84h300zM810 214v468h-596v-468h596zM810 896c46 0 86-40 86-86v-596c0-46-40-86-86-86h-596c-48 0-86 40-86 86v596c0 46 38 86 86 86h42v86h86v-86h340v86h86v-86h42zM726 598v-86h-428v86h428z" />
<glyph unicode="&#xe61d;" glyph-name="phone-talk" d="M640 512c0 70-58 128-128 128v86c118 0 214-96 214-214h-86zM810 512c0 166-132 298-298 298v86c212 0 384-172 384-384h-86zM854 362c24 0 42-18 42-42v-150c0-24-18-42-42-42-400 0-726 326-726 726 0 24 18 42 42 42h150c24 0 42-18 42-42 0-54 8-104 24-152 4-14 2-32-10-44l-94-94c62-122 162-220 282-282l94 94c12 12 30 14 44 10 48-16 98-24 152-24z" />
<glyph unicode="&#xe80b;" glyph-name="public" d="M764 282c56 60 90 142 90 230 0 142-88 266-214 316v-18c0-46-40-84-86-84h-84v-86c0-24-20-42-44-42h-84v-86h256c24 0 42-18 42-42v-128h42c38 0 70-26 82-60zM470 174v82c-46 0-86 40-86 86v42l-204 204c-6-24-10-50-10-76 0-174 132-318 300-338zM512 938c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426z" />
<glyph unicode="&#xe836;" glyph-name="radio_button_unchecked" d="M512 170c188 0 342 154 342 342s-154 342-342 342-342-154-342-342 154-342 342-342zM512 938c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426z" />
<glyph unicode="&#xe837;" glyph-name="radio_button_checked" d="M512 170c188 0 342 154 342 342s-154 342-342 342-342-154-342-342 154-342 342-342zM512 938c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426zM512 726c118 0 214-96 214-214s-96-214-214-214-214 96-214 214 96 214 214 214z" />
<glyph unicode="&#xe89e;" glyph-name="open_in_new" d="M598 896h298v-298h-86v152l-418-418-60 60 418 418h-152v86zM810 214v298h86v-298c0-46-40-86-86-86h-596c-48 0-86 40-86 86v596c0 46 38 86 86 86h298v-86h-298v-596h596z" />
<glyph unicode="&#xe8b3;" glyph-name="restore" d="M512 682h64v-180l150-90-32-52-182 110v212zM554 896c212 0 384-172 384-384s-172-384-384-384c-106 0-200 42-270 112l60 62c54-54 128-88 210-88 166 0 300 132 300 298s-134 298-300 298-298-132-298-298h128l-172-172-4 6-166 166h128c0 212 172 384 384 384z" />
<glyph unicode="&#xe8b6;" glyph-name="search" d="M406 426c106 0 192 86 192 192s-86 192-192 192-192-86-192-192 86-192 192-192zM662 426l212-212-64-64-212 212v34l-12 12c-48-42-112-66-180-66-154 0-278 122-278 276s124 278 278 278 276-124 276-278c0-68-24-132-66-180l12-12h34z" />
<glyph unicode="&#xe900;" glyph-name="AUD" d="M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512c282.77 0 512-229.23 512-512s-229.23-512-512-512zM308.25 387.3h57.225l-87.675 252.525h-62.125l-87.675-252.525h53.025l19.425 60.2h88.725l19.075-60.2zM461.9 639.825h-52.85v-165.375c0-56 41.125-93.625 105.7-93.625 64.75 0 105.875 37.625 105.875 93.625v165.375h-52.85v-159.95c0-31.85-19.075-52.15-53.025-52.15-33.775 0-52.85 20.3-52.85 52.15v159.95zM682.225 640v-252.7h99.4c75.6 0 118.475 46.025 118.475 128.1 0 79.1-43.4 124.6-118.475 124.6h-99.4zM735.075 594.85v-162.4h38.15c46.725 0 72.975 28.7 72.975 82.075 0 51.1-27.125 80.325-72.975 80.325h-38.15zM243.5 587.325l-31.675-99.050h66.15l-31.325 99.050h-3.15z" />
<glyph unicode="&#xe901;" glyph-name="signal_cellular_0" d="M938 938v-852h-852zM854 732l-562-562h562v562z" />
<glyph unicode="&#xe902;" glyph-name="signal_cellular_1" d="M86 86l852 852v-256h-170v-596h-682zM854 86v84h84v-84h-84zM854 256v342h84v-342h-84z" />
<glyph unicode="&#xe903;" glyph-name="mic-camera-combined" d="M756.704 628.138l267.296 202.213v-635.075l-267.296 202.213v-191.923c0-12.085-11.296-21.863-25.216-21.863h-706.272c-13.92 0-25.216 9.777-25.216 21.863v612.25c0 12.085 11.296 21.863 25.216 21.863h706.272c13.92 0 25.216-9.777 25.216-21.863v-189.679zM371.338 376.228c47.817 0 86.529 40.232 86.529 89.811v184.835c0 49.651-38.713 89.883-86.529 89.883-47.788 0-86.515-40.232-86.515-89.883v-184.835c0-49.579 38.756-89.811 86.515-89.811v0zM356.754 314.070v-32.78h33.718v33.412c73.858 9.606 131.235 73.73 131.235 151.351v88.232h-30.636v-88.232c0-67.57-53.696-122.534-119.734-122.534-66.024 0-119.691 54.964-119.691 122.534v88.232h-30.636v-88.232c0-79.215 59.674-144.502 135.744-151.969v-0.014z" />
<glyph unicode="&#xe904;" glyph-name="kick" d="M512 810l284-426h-568zM214 298h596v-84h-596v84z" />
<glyph unicode="&#xe905;" glyph-name="hangup" d="M512 640c-68 0-134-10-196-30v-132c0-16-10-34-24-40-42-20-80-46-114-78-8-8-18-12-30-12s-22 4-30 12l-106 106c-8 8-12 18-12 30s4 22 12 30c130 124 306 200 500 200s370-76 500-200c8-8 12-18 12-30s-4-22-12-30l-106-106c-8-8-18-12-30-12s-22 4-30 12c-34 32-72 58-114 78-14 6-24 20-24 38v132c-62 20-128 32-196 32z" />
<glyph unicode="&#xe906;" glyph-name="chat" d="M854 342v512h-684v-598l86 86h598zM854 938c46 0 84-38 84-84v-512c0-46-38-86-84-86h-598l-170-170v768c0 46 38 84 84 84h684z" />
<glyph unicode="&#xe907;" glyph-name="signal_cellular_2" d="M86 86l852 852v-852h-852z" />
<glyph unicode="&#xe908;" glyph-name="share-doc" d="M554 640h236l-236 234v-234zM682 426v86h-340v-86h340zM682 256v86h-340v-86h340zM598 938l256-256v-512c0-46-40-84-86-84h-512c-46 0-86 38-86 84l2 684c0 46 38 84 84 84h342z" />
<glyph unicode="&#xe909;" glyph-name="ninja" d="M330.667 469.333c-0.427 14.933 6.4 29.44 17.92 39.253 32-6.827 61.867-20.053 88.747-39.253 0-29.013-23.893-52.907-53.333-52.907s-52.907 23.467-53.333 52.907zM586.667 469.333c26.88 18.773 56.747 32 88.747 38.827 11.52-9.813 18.347-24.32 17.92-38.827 0-29.867-23.893-53.76-53.333-53.76s-53.333 23.893-53.333 53.76v0zM512 640c-118.187 1.707-234.667-27.733-338.347-85.333l-2.987-42.667c0-52.48 12.373-104.107 35.84-151.040 101.12 15.36 203.093 23.040 305.493 23.040s204.373-7.68 305.493-23.040c23.467 46.933 35.84 98.56 35.84 151.040l-2.987 42.667c-103.68 57.6-220.16 87.040-338.347 85.333zM512 938.667c235.641 0 426.667-191.025 426.667-426.667s-191.025-426.667-426.667-426.667c-235.641 0-426.667 191.025-426.667 426.667s191.025 426.667 426.667 426.667z" />
<glyph unicode="&#xe90a;" glyph-name="enlarge" d="M896 212v600h-768v-600h768zM896 896q34 0 60-26t26-60v-596q0-34-26-60t-60-26h-768q-34 0-60 26t-26 60v596q0 34 26 60t60 26h768zM598 342l-86-108-86 108h172zM256 598v-172l-106 86zM768 598l106-86-106-86v172zM512 790l86-108h-172z" />
<glyph unicode="&#xe90b;" glyph-name="full-screen" d="M598 810h212v-212h-84v128h-128v84zM726 298v128h84v-212h-212v84h128zM214 598v212h212v-84h-128v-128h-84zM298 426v-128h128v-84h-212v212h84z" />
<glyph unicode="&#xe90c;" glyph-name="exit-full-screen" d="M682 682h128v-84h-212v212h84v-128zM598 214v212h212v-84h-128v-128h-84zM342 682v128h84v-212h-212v84h128zM214 342v84h212v-212h-84v128h-128z" />
<glyph unicode="&#xe90d;" glyph-name="security" d="M768 170v428h-512v-428h512zM768 682c46 0 86-38 86-84v-428c0-46-40-84-86-84h-512c-46 0-86 38-86 84v428c0 46 40 84 86 84h388v86c0 72-60 132-132 132s-132-60-132-132h-82c0 118 96 214 214 214s214-96 214-214v-86h42zM512 298c-46 0-86 40-86 86s40 86 86 86 86-40 86-86-40-86-86-86z" />
<glyph unicode="&#xe90e;" glyph-name="security-locked" d="M768 170v428h-512v-428h512zM380 768v-86h264v86c0 72-60 132-132 132s-132-60-132-132zM768 682c46 0 86-38 86-84v-428c0-46-40-84-86-84h-512c-46 0-86 38-86 84v428c0 46 40 84 86 84h42v86c0 118 96 214 214 214s214-96 214-214v-86h42zM512 298c-46 0-86 40-86 86s40 86 86 86 86-40 86-86-40-86-86-86z" />
<glyph unicode="&#xe90f;" glyph-name="blur-background" d="M469.333 640c0-47.128-38.205-85.333-85.333-85.333s-85.333 38.205-85.333 85.333c0 47.128 38.205 85.333 85.333 85.333s85.333-38.205 85.333-85.333zM725.333 640c0-47.128-38.205-85.333-85.333-85.333s-85.333 38.205-85.333 85.333c0 47.128 38.205 85.333 85.333 85.333s85.333-38.205 85.333-85.333zM469.333 384c0-47.128-38.205-85.333-85.333-85.333s-85.333 38.205-85.333 85.333c0 47.128 38.205 85.333 85.333 85.333s85.333-38.205 85.333-85.333zM426.667 170.667c0-23.564-19.103-42.667-42.667-42.667s-42.667 19.103-42.667 42.667c0 23.564 19.103 42.667 42.667 42.667s42.667-19.103 42.667-42.667zM682.667 170.667c0-23.564-19.103-42.667-42.667-42.667s-42.667 19.103-42.667 42.667c0 23.564 19.103 42.667 42.667 42.667s42.667-19.103 42.667-42.667zM213.333 384c0-23.564-19.103-42.667-42.667-42.667s-42.667 19.103-42.667 42.667c0 23.564 19.103 42.667 42.667 42.667s42.667-19.103 42.667-42.667zM213.333 640c0-23.564-19.103-42.667-42.667-42.667s-42.667 19.103-42.667 42.667c0 23.564 19.103 42.667 42.667 42.667s42.667-19.103 42.667-42.667zM896 384c0-23.564-19.103-42.667-42.667-42.667s-42.667 19.103-42.667 42.667c0 23.564 19.103 42.667 42.667 42.667s42.667-19.103 42.667-42.667zM896 640c0-23.564-19.103-42.667-42.667-42.667s-42.667 19.103-42.667 42.667c0 23.564 19.103 42.667 42.667 42.667s42.667-19.103 42.667-42.667zM426.667 853.333c0-23.564-19.103-42.667-42.667-42.667s-42.667 19.103-42.667 42.667c0 23.564 19.103 42.667 42.667 42.667s42.667-19.103 42.667-42.667zM682.667 853.333c0-23.564-19.103-42.667-42.667-42.667s-42.667 19.103-42.667 42.667c0 23.564 19.103 42.667 42.667 42.667s42.667-19.103 42.667-42.667zM725.333 384c0-47.128-38.205-85.333-85.333-85.333s-85.333 38.205-85.333 85.333c0 47.128 38.205 85.333 85.333 85.333s85.333-38.205 85.333-85.333z" />
<glyph unicode="&#xe910;" glyph-name="microphone" d="M738 554h72c0-146-116-266-256-286v-140h-84v140c-140 20-256 140-256 286h72c0-128 108-216 226-216s226 88 226 216zM512 426c-70 0-128 58-128 128v256c0 70 58 128 128 128s128-58 128-128v-256c0-70-58-128-128-128z" />
<glyph unicode="&#xe911;" glyph-name="send" d="M86 128v298l640 86-640 86v298l896-384z" />
<glyph unicode="&#xe912;" glyph-name="mic-disabled" d="M182 896l714-714-54-54-178 178c-32-20-72-32-110-38v-140h-84v140c-140 20-256 140-256 286h72c0-128 108-216 226-216 34 0 68 8 98 22l-70 70c-8-2-18-4-28-4-70 0-128 58-128 128v32l-256 256zM640 548l-256 254v8c0 70 58 128 128 128s128-58 128-128v-262zM810 554c0-50-14-98-38-140l-52 54c12 26 18 54 18 86h72z" />
<glyph unicode="&#xe913;" glyph-name="link" d="M640 426c114 0 342-56 342-170v-86h-684v86c0 114 228 170 342 170zM256 598h128v-86h-128v-128h-86v128h-128v86h128v128h86v-128zM640 512c-94 0-170 76-170 170s76 172 170 172 170-78 170-172-76-170-170-170z" />
<glyph unicode="&#xe914;" glyph-name="shared-video" d="M512 170c188 0 342 154 342 342s-154 342-342 342-342-154-342-342 154-342 342-342zM512 938c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426zM426 320v384l256-192z" />
<glyph unicode="&#xe915;" glyph-name="settings" d="M512 362c82 0 150 68 150 150s-68 150-150 150-150-68-150-150 68-150 150-150zM830 470l90-70c8-6 10-18 4-28l-86-148c-6-10-16-12-26-8l-106 42c-22-16-46-32-72-42l-16-112c-2-10-10-18-20-18h-172c-10 0-18 8-20 18l-16 112c-26 10-50 24-72 42l-106-42c-10-4-20-2-26 8l-86 148c-6 10-4 22 4 28l90 70c-2 14-2 28-2 42s0 28 2 42l-90 70c-8 6-10 18-4 28l86 148c6 10 16 12 26 8l106-42c22 16 46 32 72 42l16 112c2 10 10 18 20 18h172c10 0 18-8 20-18l16-112c26-10 50-24 72-42l106 42c10 4 20 2 26-8l86-148c6-10 4-22-4-28l-90-70c2-14 2-28 2-42s0-28-2-42z" />
<glyph unicode="&#xe916;" glyph-name="star" d="M512 366l160-96-42 182 142 124-188 16-72 172-72-172-188-16 142-124-42-182zM938 630l-232-202 70-300-264 160-264-160 70 300-232 202 306 26 120 282 120-282z" />
<glyph unicode="&#xe917;" glyph-name="share-desktop" d="M896 298v512h-768v-512h768zM896 896c46 0 86-40 86-86l-2-512c0-46-38-84-84-84h-214v-86h-340v86h-214c-46 0-86 38-86 84v512c0 46 40 86 86 86h768z" />
<glyph unicode="&#xe918;" glyph-name="camera" d="M726 576l170 170v-468l-170 170v-150c0-24-20-42-44-42h-512c-24 0-42 18-42 42v428c0 24 18 42 42 42h512c24 0 44-18 44-42v-150z" />
<glyph unicode="&#xe919;" glyph-name="camera-disabled" d="M140 938l756-756-54-54-136 136c-6-4-16-8-24-8h-512c-24 0-42 18-42 42v428c0 24 18 42 42 42h32l-116 116zM896 746v-456l-478 478h264c24 0 44-18 44-42v-150z" />
<glyph unicode="&#xe91a;" glyph-name="volume" d="M598 886c172-38 298-192 298-374s-126-336-298-374v88c124 36 212 150 212 286s-88 250-212 286v88zM704 512c0-76-42-140-106-172v344c64-32 106-96 106-172zM128 640h170l214 214v-684l-214 214h-170v256z" />
<glyph unicode="&#xe91b;" glyph-name="check" d="M384 334l452 452 60-60-512-512-238 238 60 60z" />
<glyph unicode="&#xe91c;" glyph-name="cancel" d="M726 358l-154 154 154 154-60 60-154-154-154 154-60-60 154-154-154-154 60-60 154 154 154-154zM512 938q176 0 301-125t125-301-125-301-301-125-301 125-125 301 125 301 301 125z" />
<glyph unicode="&#xe91d;" glyph-name="feedback" d="M42.667 128h170.667v512h-170.667v-512zM981.333 597.333c0 46.933-38.4 85.333-85.333 85.333h-269.227l40.533 194.987 1.28 13.653c0 17.493-7.253 33.707-18.773 45.227l-45.227 44.8-280.747-281.173c-15.787-15.36-25.173-36.693-25.173-60.16v-426.667c0-46.933 38.4-85.333 85.333-85.333h384c35.413 0 65.707 21.333 78.507 52.053l128.853 300.8c3.84 9.813 5.973 20.053 5.973 31.147v81.493l-0.427 0.427 0.427 3.413z" />
<glyph unicode="&#xe91e;" glyph-name="raised-hand" d="M982 790v-620c0-94-78-170-172-170h-310c-46 0-90 18-122 50l-336 342s54 52 56 52c10 8 22 12 34 12 10 0 18-2 26-6 2 0 184-104 184-104v508c0 36 28 64 64 64s64-28 64-64v-300h42v406c0 36 28 64 64 64s64-28 64-64v-406h42v364c0 36 28 64 64 64s64-28 64-64v-364h44v236c0 36 28 64 64 64s64-28 64-64z" />
<glyph unicode="&#xe91f;" glyph-name="menu-up" d="M512 682l256-256-60-60-196 196-196-196-60 60z" />
<glyph unicode="&#xe920;" glyph-name="menu-down" d="M708 658l60-60-256-256-256 256 60 60 196-196z" />
<glyph unicode="&#xe921;" glyph-name="switch-camera" d="M640 362l150 150-150 150v-108h-256v108l-150-150 150-150v108h256v-108zM854 854c46 0 84-40 84-86v-512c0-46-38-86-84-86h-684c-46 0-84 40-84 86v512c0 46 38 86 84 86h136l78 84h256l78-84h136z" />
<glyph unicode="&#xe922;" glyph-name="info" d="M512 938.667c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM554.667 298.667h-85.333v256h85.333v-256zM554.667 640h-85.333v85.333h85.333v-85.333z" />
<glyph unicode="&#xe923;" glyph-name="visibility" d="M512 640c70 0 128-58 128-128s-58-128-128-128-128 58-128 128 58 128 128 128zM512 298c118 0 214 96 214 214s-96 214-214 214-214-96-214-214 96-214 214-214zM512 832c214 0 396-132 470-320-74-188-256-320-470-320s-396 132-470 320c74 188 256 320 470 320z" />
<glyph unicode="&#xe924;" glyph-name="visibility-off" d="M506 640h6c70 0 128-58 128-128v-8zM322 606c-14-28-24-60-24-94 0-118 96-214 214-214 34 0 66 10 94 24l-66 66c-8-2-18-4-28-4-70 0-128 58-128 128 0 10 2 20 4 28zM86 842l54 54 756-756-54-54c-47.968 47.365-96.266 94.401-144 142-58-24-120-36-186-36-214 0-396 132-470 320 34 84 90 156 160 212-39.017 38.983-77.307 78.693-116 118zM512 726c-28 0-54-6-78-16l-92 92c52 20 110 30 170 30 214 0 394-132 468-320-32-80-82-148-146-202l-124 124c10 24 16 50 16 78 0 118-96 214-214 214z" />
<glyph unicode="&#xe926;" glyph-name="gsm-bars" d="M896 1024c70.692 0 128-57.308 128-128v-768c0-70.692-57.308-128-128-128s-128 57.308-128 128v768c0 70.692 57.308 128 128 128zM512 768c70.692 0 128-57.308 128-128v-512c0-70.692-57.308-128-128-128s-128 57.308-128 128v512c0 70.692 57.308 128 128 128zM128 384v0c70.692 0 128-57.308 128-128v-128c0-70.692-57.308-128-128-128s-128 57.308-128 128v128c0 70.692 57.308 128 128 128v0z" />
<glyph unicode="&#xe927;" glyph-name="HD" d="M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512c282.77 0 512-229.23 512-512s-229.23-512-512-512zM481.359 384v255.823h-54.273v-103.18h-116.813v103.18h-54.273v-255.823h54.273v106.903h116.813v-106.903h54.273zM544.258 640v-256h102.077c77.636 0 121.665 46.626 121.665 129.773 0 80.133-44.569 126.227-121.665 126.227h-102.077zM598.531 594.26v-164.521h39.177c47.983 0 74.94 29.075 74.94 83.147 0 51.767-27.855 81.374-74.94 81.374h-39.177z" />
<glyph unicode="&#xe928;" glyph-name="LD" d="M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512c282.77 0 512-229.23 512-512s-229.23-512-512-512zM472.4 433.325h-112.35v206.5h-52.85v-252.525h165.2v46.025zM520.35 640v-252.7h99.4c75.6 0 118.475 46.025 118.475 128.1 0 79.1-43.4 124.6-118.475 124.6h-99.4zM573.2 594.85v-162.4h38.15c46.725 0 72.975 28.7 72.975 82.075 0 51.1-27.125 80.325-72.975 80.325h-38.15z" />
<glyph unicode="&#xe929;" glyph-name="SD" d="M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512c282.77 0 512-229.23 512-512s-229.23-512-512-512zM281.6 451.175c1.925-47.075 40.95-76.65 101.15-76.65 63.35 0 102.375 31.15 102.375 82.075 0 39.2-21.875 61.075-72.625 71.75l-30.45 6.475c-29.575 6.3-41.65 15.225-41.65 30.8 0 19.25 17.5 31.5 43.925 31.5 25.55 0 44.1-13.3 46.55-33.25h49.7c-1.575 44.975-40.95 76.125-96.6 76.125-58.275 0-96.6-31.325-96.6-78.925 0-38.5 22.575-62.475 68.6-72.1l32.9-7c30.975-6.65 43.575-15.925 43.575-32.025 0-19.075-19.425-32.375-46.9-32.375-29.75 0-50.4 13.125-52.85 33.6h-51.1zM535 633.7v-252.7h99.4c75.6 0 118.475 46.025 118.475 128.1 0 79.1-43.4 124.6-118.475 124.6h-99.4zM587.85 588.55v-162.4h38.15c46.725 0 72.975 28.7 72.975 82.075 0 51.1-27.125 80.325-72.975 80.325h-38.15z" />
<glyph unicode="&#xe92a;" glyph-name="camera-take-picture" d="M725.333 512c0-117.821-95.513-213.333-213.333-213.333s-213.333 95.513-213.333 213.333c0 117.821 95.513 213.333 213.333 213.333s213.333-95.513 213.333-213.333zM512 256c141.385 0 256 114.615 256 256s-114.615 256-256 256v0c-141.385 0-256-114.615-256-256s114.615-256 256-256v0zM512 213.333c-164.949 0-298.667 133.718-298.667 298.667s133.718 298.667 298.667 298.667v0c164.949 0 298.667-133.718 298.667-298.667s-133.718-298.667-298.667-298.667v0z" />
<glyph unicode="&#xe92b;" glyph-name="rec" d="M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512c282.77 0 512-229.23 512-512s-229.23-512-512-512zM581.333 433.782h-110.595v59.233h104.338v40.332h-104.338v56.87h110.595v43.539h-161.665v-243.512h161.665v43.539zM738.771 384c58.849 0 101.802 36.282 106.029 88.933h-49.717c-4.904-26.832-26.888-44.045-56.143-44.045-38.556 0-62.4 31.895-62.4 83.196s23.844 83.027 62.231 83.027c29.086 0 51.239-18.394 56.143-46.407h49.717c-3.72 52.989-48.026 91.296-105.86 91.296-70.855 0-114.485-48.77-114.485-127.916 0-79.314 43.798-128.084 114.485-128.084zM230.27 478.502h41.769l45.489-88.258h57.834l-51.408 96.19c28.072 11.138 44.306 38.138 44.306 69.189 0 48.432-32.976 78.133-86.582 78.133h-102.478v-243.512h51.070v88.258zM230.27 592.58v-74.927h44.813c25.704 0 40.754 13.838 40.754 37.295 0 23.119-15.896 37.632-41.262 37.632h-44.306z" />
<glyph unicode="&#xe92d;" glyph-name="speaker" d="M0 512c0-282.795 229.205-512 512-512s512 229.205 512 512c0 282.795-229.205 512-512 512s-512-229.205-512-512zM525.005 759.362c-20.475 24.944-16.326 61.342 9.268 81.297s62.94 15.911 83.416-9.033c16.036-19.536 38.593-52.97 60.894-97.797 81.621-164.065 89.461-340.992-26.857-506.352-8.384-11.919-17.386-23.69-27.012-35.307-20.593-24.851-57.959-28.727-83.458-8.657s-29.476 56.487-8.882 81.338c7.686 9.275 14.833 18.621 21.455 28.035 88.66 126.041 82.71 260.306 17.953 390.475-10.599 21.305-21.94 40.51-33.198 57.196-6.515 9.657-11.322 16.057-13.578 18.805zM353.479 647.46c-19.353 24.679-15.129 60.448 9.434 79.893s60.164 15.2 79.517-9.479c9.635-12.287 22.577-32.644 35.209-60.034 50.35-109.176 50.35-231.689-33.639-349.612-18.198-25.551-53.566-31.441-78.997-13.157s-31.294 53.819-13.096 79.37c57.564 80.822 57.564 160.581 22.983 235.565-8.601 18.65-16.892 31.691-21.412 37.455z" />
<glyph unicode="&#xe92e;" glyph-name="tiles-many" d="M113.778 1024h227.556c62.838 0 113.778-50.94 113.778-113.778v-227.556c0-62.838-50.94-113.778-113.778-113.778h-227.556c-62.838 0-113.778 50.94-113.778 113.778v227.556c0 62.838 50.94 113.778 113.778 113.778zM170.667 910.222c-31.419 0-56.889-25.47-56.889-56.889v-113.778c0-31.419 25.47-56.889 56.889-56.889h113.778c31.419 0 56.889 25.47 56.889 56.889v113.778c0 31.419-25.47 56.889-56.889 56.889h-113.778zM113.778 455.111h227.556c62.838 0 113.778-50.94 113.778-113.778v-227.556c0-62.838-50.94-113.778-113.778-113.778h-227.556c-62.838 0-113.778 50.94-113.778 113.778v227.556c0 62.838 50.94 113.778 113.778 113.778zM170.667 341.333c-31.419 0-56.889-25.47-56.889-56.889v-113.778c0-31.419 25.47-56.889 56.889-56.889h113.778c31.419 0 56.889 25.47 56.889 56.889v113.778c0 31.419-25.47 56.889-56.889 56.889h-113.778zM682.667 1024h227.556c62.838 0 113.778-50.94 113.778-113.778v-227.556c0-62.838-50.94-113.778-113.778-113.778h-227.556c-62.838 0-113.778 50.94-113.778 113.778v227.556c0 62.838 50.94 113.778 113.778 113.778zM739.556 910.222c-31.419 0-56.889-25.47-56.889-56.889v-113.778c0-31.419 25.47-56.889 56.889-56.889h113.778c31.419 0 56.889 25.47 56.889 56.889v113.778c0 31.419-25.47 56.889-56.889 56.889h-113.778zM682.667 455.111h227.556c62.838 0 113.778-50.94 113.778-113.778v-227.556c0-62.838-50.94-113.778-113.778-113.778h-227.556c-62.838 0-113.778 50.94-113.778 113.778v227.556c0 62.838 50.94 113.778 113.778 113.778zM739.556 341.333c-31.419 0-56.889-25.47-56.889-56.889v-113.778c0-31.419 25.47-56.889 56.889-56.889h113.778c31.419 0 56.889 25.47 56.889 56.889v113.778c0 31.419-25.47 56.889-56.889 56.889h-113.778z" />
<glyph unicode="&#xe930;" glyph-name="closed_caption" d="M768 554v44c0 24-18 42-42 42h-128c-24 0-44-18-44-42v-172c0-24 20-42 44-42h128c24 0 42 18 42 42v44h-64v-22h-86v128h86v-22h64zM470 554v44c0 24-20 42-44 42h-128c-24 0-42-18-42-42v-172c0-24 18-42 42-42h128c24 0 44 18 44 42v44h-64v-22h-86v128h86v-22h64zM810 854c46 0 86-40 86-86v-512c0-46-40-86-86-86h-596c-48 0-86 40-86 86v512c0 46 38 86 86 86h596z" />
<glyph unicode="&#xf04b;" glyph-name="play" horiz-adv-x="809" d="M790.857 494.286l-758.857-421.714c-17.714-9.714-32-1.143-32 18.857v841.143c0 20 14.286 28.571 32 18.857l758.857-421.714c17.714-9.714 17.714-25.714 0-35.429z" />
<glyph unicode="&#xf04d;" glyph-name="stop" horiz-adv-x="878" d="M877.714 914.286v-804.571c0-20-16.571-36.571-36.571-36.571h-804.571c-20 0-36.571 16.571-36.571 36.571v804.571c0 20 16.571 36.571 36.571 36.571h804.571c20 0 36.571-16.571 36.571-36.571z" />
<glyph unicode="&#xf0a1;" glyph-name="dominant-speaker" d="M950.857 658.286c40.571 0 73.143-32.571 73.143-73.143s-32.571-73.143-73.143-73.143v-219.429c0-40-33.143-73.143-73.143-73.143-101.714 84.571-265.714 200.571-464 217.143-68-22.857-91.429-102.286-46.857-148-40-65.714 11.429-112 72-159.429-35.429-69.714-182.857-70.857-235.429-22.286-33.143 101.714-82.286 203.429-42.286 332h-69.714c-50.286 0-91.429 41.143-91.429 91.429v109.714c0 50.286 41.143 91.429 91.429 91.429h274.286c219.429 0 402.286 128 512 219.429 40 0 73.143-33.143 73.143-73.143v-219.429zM877.714 313.143v545.143c-149.143-114.286-293.714-180-438.857-196v-154.286c145.143-16 289.714-80.571 438.857-194.857z" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

3
images/user-groups.svg Normal file
View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.33331 2C6.28101 2 7.09675 2.56499 7.46207 3.37651C7.00766 3.45023 6.58406 3.61583 6.21095 3.85361C6.04111 3.54356 5.71176 3.33333 5.33331 3.33333C4.78103 3.33333 4.33331 3.78105 4.33331 4.33333C4.33331 4.75895 4.59921 5.12246 4.97395 5.26682C4.77672 5.69245 4.66665 6.16671 4.66665 6.66667L4.66678 6.6967C3.12249 6.85332 2.66665 7.65415 2.66665 9.83333C2.66665 9.89666 2.66835 9.95222 2.67088 10H3.13441C2.977 10.3982 2.86114 10.8423 2.7841 11.3333H2.33331C1.66665 11.3333 1.33331 10.8333 1.33331 9.83333C1.33331 7.60559 1.88097 6.20498 3.39417 5.63152C3.14521 5.26038 2.99998 4.81382 2.99998 4.33333C2.99998 3.04467 4.04465 2 5.33331 2ZM9.78901 3.85361C9.4159 3.61583 8.9923 3.45023 8.53788 3.37651C8.90321 2.56499 9.71895 2 10.6666 2C11.9553 2 13 3.04467 13 4.33333C13 4.81382 12.8547 5.26038 12.6058 5.63152C14.119 6.20498 14.6666 7.60559 14.6666 9.83333C14.6666 10.8333 14.3333 11.3333 13.6666 11.3333H13.2159C13.1388 10.8423 13.023 10.3982 12.8656 10H13.3291C13.3316 9.95222 13.3333 9.89666 13.3333 9.83333C13.3333 7.65415 12.8775 6.85332 11.3332 6.6967L11.3333 6.66667C11.3333 6.1667 11.2232 5.69245 11.026 5.26682C11.4008 5.12246 11.6666 4.75895 11.6666 4.33333C11.6666 3.78105 11.2189 3.33333 10.6666 3.33333C10.2882 3.33333 9.95885 3.54356 9.78901 3.85361ZM4.49998 14.6667C3.7222 14.6667 3.33331 14.1111 3.33331 13C3.33331 10.4598 4.0062 8.8875 5.87888 8.28308C5.5366 7.83462 5.33331 7.27438 5.33331 6.66667C5.33331 5.19391 6.52722 4 7.99998 4C9.47274 4 10.6666 5.19391 10.6666 6.66667C10.6666 7.27438 10.4634 7.83462 10.1211 8.28308C11.9938 8.8875 12.6666 10.4598 12.6666 13C12.6666 14.1111 12.2778 14.6667 11.5 14.6667H4.49998ZM9.33331 6.66667C9.33331 7.40305 8.73636 8 7.99998 8C7.2636 8 6.66665 7.40305 6.66665 6.66667C6.66665 5.93029 7.2636 5.33333 7.99998 5.33333C8.73636 5.33333 9.33331 5.93029 9.33331 6.66667ZM11.3333 13C11.3333 13.1426 11.3252 13.2536 11.3152 13.3333H4.68477C4.67476 13.2536 4.66665 13.1426 4.66665 13C4.66665 10.1957 5.42021 9.33333 7.99998 9.33333C10.5797 9.33333 11.3333 10.1957 11.3333 13Z" fill="#5E6D7A"/>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

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

View File

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

View File

@@ -17,9 +17,20 @@ target 'JitsiMeet' do
# React Native and its dependencies
#
pod 'FBLazyVector', :path => '../node_modules/react-native/Libraries/FBLazyVector/'
pod 'FBReactNativeSpec', :path => '../node_modules/react-native/Libraries/FBReactNativeSpec/'
pod 'RCTRequired', :path => '../node_modules/react-native/Libraries/RCTRequired/'
pod 'RCTTypeSafety', :path => '../node_modules/react-native/Libraries/TypeSafety/'
pod 'React', :path => '../node_modules/react-native/'
pod 'React-Core', :path => '../node_modules/react-native/React'
pod 'React-DevSupport', :path => '../node_modules/react-native/React'
pod 'ReactCommon', :path => '../node_modules/react-native/ReactCommon', :subspecs => [
'turbomodule'
]
pod 'React-Core', :path => '../node_modules/react-native/', :subspecs => [
'CoreModulesHeaders',
'DevSupport',
'RCTWebSocket'
]
pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
@@ -29,13 +40,12 @@ target 'JitsiMeet' do
pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
pod 'React-RCTWebSocket', :path => '../node_modules/react-native/Libraries/WebSocket'
pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
@@ -52,15 +62,16 @@ target 'JitsiMeet' do
pod 'react-native-webrtc', :path => '../node_modules/react-native-webrtc'
pod 'BVLinearGradient', :path => '../node_modules/react-native-linear-gradient'
pod 'RNCAsyncStorage', :path => '../node_modules/@react-native-community/async-storage'
pod 'RNGoogleSignin', :path => '../node_modules/react-native-google-signin'
pod 'RNGoogleSignin', :path => '../node_modules/@react-native-community/google-signin'
pod 'RNSound', :path => '../node_modules/react-native-sound'
pod 'RNVectorIcons', :path => '../node_modules/react-native-vector-icons'
pod 'RNSVG', :path => '../node_modules/react-native-svg'
pod 'RNWatch', :path => '../node_modules/react-native-watch-connectivity'
# Native pod dependencies
#
pod 'Amplitude-iOS', '~> 4.0.4'
pod 'CocoaLumberjack', '~>3.5.3'
pod 'ObjectiveDropboxOfficial', '~> 3.9.4'
use_native_modules!
@@ -70,6 +81,8 @@ post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'YES'
config.build_settings['SUPPORTS_MACCATALYST'] = 'NO'
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '10.0'
end
end
end

View File

@@ -1,12 +1,28 @@
PODS:
- Amplitude-iOS (4.0.4)
- AppAuth (1.2.0):
- AppAuth/Core (= 1.2.0)
- AppAuth/ExternalUserAgent (= 1.2.0)
- AppAuth/Core (1.2.0)
- AppAuth/ExternalUserAgent (1.2.0)
- boost-for-react-native (1.63.0)
- BVLinearGradient (2.5.6):
- React
- CocoaLumberjack (3.5.3):
- CocoaLumberjack/Core (= 3.5.3)
- CocoaLumberjack/Core (3.5.3)
- Crashlytics (3.12.0):
- Fabric (~> 1.9.0)
- DoubleConversion (1.1.6)
- Fabric (1.9.0)
- FBLazyVector (0.61.3)
- FBReactNativeSpec (0.61.3):
- Folly (= 2018.10.22.00)
- RCTRequired (= 0.61.3)
- RCTTypeSafety (= 0.61.3)
- React-Core (= 0.61.3)
- React-jsi (= 0.61.3)
- ReactCommon/turbomodule/core (= 0.61.3)
- Firebase/Core (5.18.0):
- Firebase/CoreOnly
- FirebaseAnalytics (= 5.7.0)
@@ -51,18 +67,10 @@ PODS:
- GoogleUtilities/Network (~> 5.2)
- "GoogleUtilities/NSData+zlib (~> 5.2)"
- nanopb (~> 0.3)
- GoogleSignIn (4.4.0):
- "GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)"
- "GoogleToolboxForMac/NSString+URLArguments (~> 2.1)"
- GoogleSignIn (5.0.1):
- AppAuth (~> 1.2)
- GTMAppAuth (~> 1.0)
- GTMSessionFetcher/Core (~> 1.1)
- GoogleToolboxForMac/DebugUtils (2.2.0):
- GoogleToolboxForMac/Defines (= 2.2.0)
- GoogleToolboxForMac/Defines (2.2.0)
- "GoogleToolboxForMac/NSDictionary+URLArguments (2.2.0)":
- GoogleToolboxForMac/DebugUtils (= 2.2.0)
- GoogleToolboxForMac/Defines (= 2.2.0)
- "GoogleToolboxForMac/NSString+URLArguments (= 2.2.0)"
- "GoogleToolboxForMac/NSString+URLArguments (2.2.0)"
- GoogleUtilities/AppDelegateSwizzler (5.4.1):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
@@ -81,58 +89,183 @@ PODS:
- GoogleUtilities/Logger
- GoogleUtilities/UserDefaults (5.4.1):
- GoogleUtilities/Logger
- GTMSessionFetcher/Core (1.2.1)
- GTMAppAuth (1.0.0):
- AppAuth/Core (~> 1.0)
- GTMSessionFetcher (~> 1.1)
- GTMSessionFetcher (1.2.2):
- GTMSessionFetcher/Full (= 1.2.2)
- GTMSessionFetcher/Core (1.2.2)
- GTMSessionFetcher/Full (1.2.2):
- GTMSessionFetcher/Core (= 1.2.2)
- nanopb (0.3.901):
- nanopb/decode (= 0.3.901)
- nanopb/encode (= 0.3.901)
- nanopb/decode (0.3.901)
- nanopb/encode (0.3.901)
- ObjectiveDropboxOfficial (3.9.4)
- React (0.60.5):
- React-Core (= 0.60.5)
- React-DevSupport (= 0.60.5)
- React-RCTActionSheet (= 0.60.5)
- React-RCTAnimation (= 0.60.5)
- React-RCTBlob (= 0.60.5)
- React-RCTImage (= 0.60.5)
- React-RCTLinking (= 0.60.5)
- React-RCTNetwork (= 0.60.5)
- React-RCTSettings (= 0.60.5)
- React-RCTText (= 0.60.5)
- React-RCTVibration (= 0.60.5)
- React-RCTWebSocket (= 0.60.5)
- React-Core (0.60.5):
- RCTRequired (0.61.3)
- RCTTypeSafety (0.61.3):
- FBLazyVector (= 0.61.3)
- Folly (= 2018.10.22.00)
- React-cxxreact (= 0.60.5)
- React-jsiexecutor (= 0.60.5)
- yoga (= 0.60.5.React)
- React-cxxreact (0.60.5):
- RCTRequired (= 0.61.3)
- React-Core (= 0.61.3)
- React (0.61.3):
- React-Core (= 0.61.3)
- React-Core/DevSupport (= 0.61.3)
- React-Core/RCTWebSocket (= 0.61.3)
- React-RCTActionSheet (= 0.61.3)
- React-RCTAnimation (= 0.61.3)
- React-RCTBlob (= 0.61.3)
- React-RCTImage (= 0.61.3)
- React-RCTLinking (= 0.61.3)
- React-RCTNetwork (= 0.61.3)
- React-RCTSettings (= 0.61.3)
- React-RCTText (= 0.61.3)
- React-RCTVibration (= 0.61.3)
- React-Core (0.61.3):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default (= 0.61.3)
- React-cxxreact (= 0.61.3)
- React-jsi (= 0.61.3)
- React-jsiexecutor (= 0.61.3)
- Yoga
- React-Core/CoreModulesHeaders (0.61.3):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.3)
- React-jsi (= 0.61.3)
- React-jsiexecutor (= 0.61.3)
- Yoga
- React-Core/Default (0.61.3):
- Folly (= 2018.10.22.00)
- glog
- React-cxxreact (= 0.61.3)
- React-jsi (= 0.61.3)
- React-jsiexecutor (= 0.61.3)
- Yoga
- React-Core/DevSupport (0.61.3):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default (= 0.61.3)
- React-Core/RCTWebSocket (= 0.61.3)
- React-cxxreact (= 0.61.3)
- React-jsi (= 0.61.3)
- React-jsiexecutor (= 0.61.3)
- React-jsinspector (= 0.61.3)
- Yoga
- React-Core/RCTActionSheetHeaders (0.61.3):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.3)
- React-jsi (= 0.61.3)
- React-jsiexecutor (= 0.61.3)
- Yoga
- React-Core/RCTAnimationHeaders (0.61.3):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.3)
- React-jsi (= 0.61.3)
- React-jsiexecutor (= 0.61.3)
- Yoga
- React-Core/RCTBlobHeaders (0.61.3):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.3)
- React-jsi (= 0.61.3)
- React-jsiexecutor (= 0.61.3)
- Yoga
- React-Core/RCTImageHeaders (0.61.3):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.3)
- React-jsi (= 0.61.3)
- React-jsiexecutor (= 0.61.3)
- Yoga
- React-Core/RCTLinkingHeaders (0.61.3):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.3)
- React-jsi (= 0.61.3)
- React-jsiexecutor (= 0.61.3)
- Yoga
- React-Core/RCTNetworkHeaders (0.61.3):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.3)
- React-jsi (= 0.61.3)
- React-jsiexecutor (= 0.61.3)
- Yoga
- React-Core/RCTSettingsHeaders (0.61.3):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.3)
- React-jsi (= 0.61.3)
- React-jsiexecutor (= 0.61.3)
- Yoga
- React-Core/RCTTextHeaders (0.61.3):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.3)
- React-jsi (= 0.61.3)
- React-jsiexecutor (= 0.61.3)
- Yoga
- React-Core/RCTVibrationHeaders (0.61.3):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.3)
- React-jsi (= 0.61.3)
- React-jsiexecutor (= 0.61.3)
- Yoga
- React-Core/RCTWebSocket (0.61.3):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default (= 0.61.3)
- React-cxxreact (= 0.61.3)
- React-jsi (= 0.61.3)
- React-jsiexecutor (= 0.61.3)
- Yoga
- React-CoreModules (0.61.3):
- FBReactNativeSpec (= 0.61.3)
- Folly (= 2018.10.22.00)
- RCTTypeSafety (= 0.61.3)
- React-Core/CoreModulesHeaders (= 0.61.3)
- React-RCTImage (= 0.61.3)
- ReactCommon/turbomodule/core (= 0.61.3)
- React-cxxreact (0.61.3):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-jsinspector (= 0.60.5)
- React-DevSupport (0.60.5):
- React-Core (= 0.60.5)
- React-RCTWebSocket (= 0.60.5)
- React-jsi (0.60.5):
- React-jsinspector (= 0.61.3)
- React-jsi (0.61.3):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-jsi/Default (= 0.60.5)
- React-jsi/Default (0.60.5):
- React-jsi/Default (= 0.61.3)
- React-jsi/Default (0.61.3):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-jsiexecutor (0.60.5):
- React-jsiexecutor (0.61.3):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-cxxreact (= 0.60.5)
- React-jsi (= 0.60.5)
- React-jsinspector (0.60.5)
- React-cxxreact (= 0.61.3)
- React-jsi (= 0.61.3)
- React-jsinspector (0.61.3)
- react-native-background-timer (2.1.1):
- React
- react-native-calendar-events (1.7.3):
@@ -141,71 +274,109 @@ PODS:
- React
- react-native-netinfo (4.1.5):
- React
- react-native-webrtc (1.69.2):
- react-native-webrtc (1.75.0):
- React
- react-native-webview (5.8.1):
- react-native-webview (7.4.1):
- React
- React-RCTActionSheet (0.60.5):
- React-Core (= 0.60.5)
- React-RCTAnimation (0.60.5):
- React-Core (= 0.60.5)
- React-RCTBlob (0.60.5):
- React-Core (= 0.60.5)
- React-RCTNetwork (= 0.60.5)
- React-RCTWebSocket (= 0.60.5)
- React-RCTImage (0.60.5):
- React-Core (= 0.60.5)
- React-RCTNetwork (= 0.60.5)
- React-RCTLinking (0.60.5):
- React-Core (= 0.60.5)
- React-RCTNetwork (0.60.5):
- React-Core (= 0.60.5)
- React-RCTSettings (0.60.5):
- React-Core (= 0.60.5)
- React-RCTText (0.60.5):
- React-Core (= 0.60.5)
- React-RCTVibration (0.60.5):
- React-Core (= 0.60.5)
- React-RCTWebSocket (0.60.5):
- React-Core (= 0.60.5)
- React-RCTActionSheet (0.61.3):
- React-Core/RCTActionSheetHeaders (= 0.61.3)
- React-RCTAnimation (0.61.3):
- React-Core/RCTAnimationHeaders (= 0.61.3)
- React-RCTBlob (0.61.3):
- React-Core/RCTBlobHeaders (= 0.61.3)
- React-Core/RCTWebSocket (= 0.61.3)
- React-jsi (= 0.61.3)
- React-RCTNetwork (= 0.61.3)
- React-RCTImage (0.61.3):
- React-Core/RCTImageHeaders (= 0.61.3)
- React-RCTNetwork (= 0.61.3)
- React-RCTLinking (0.61.3):
- React-Core/RCTLinkingHeaders (= 0.61.3)
- React-RCTNetwork (0.61.3):
- React-Core/RCTNetworkHeaders (= 0.61.3)
- React-RCTSettings (0.61.3):
- React-Core/RCTSettingsHeaders (= 0.61.3)
- React-RCTText (0.61.3):
- React-Core/RCTTextHeaders (= 0.61.3)
- React-RCTVibration (0.61.3):
- React-Core/RCTVibrationHeaders (= 0.61.3)
- ReactCommon/jscallinvoker (0.61.3):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-cxxreact (= 0.61.3)
- ReactCommon/turbomodule (0.61.3):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-Core (= 0.61.3)
- React-cxxreact (= 0.61.3)
- React-jsi (= 0.61.3)
- ReactCommon/jscallinvoker (= 0.61.3)
- ReactCommon/turbomodule/core (= 0.61.3)
- ReactCommon/turbomodule/samples (= 0.61.3)
- ReactCommon/turbomodule/core (0.61.3):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-Core (= 0.61.3)
- React-cxxreact (= 0.61.3)
- React-jsi (= 0.61.3)
- ReactCommon/jscallinvoker (= 0.61.3)
- ReactCommon/turbomodule/samples (0.61.3):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-Core (= 0.61.3)
- React-cxxreact (= 0.61.3)
- React-jsi (= 0.61.3)
- ReactCommon/jscallinvoker (= 0.61.3)
- ReactCommon/turbomodule/core (= 0.61.3)
- RNCAsyncStorage (1.3.4):
- React
- RNGoogleSignin (2.0.0):
- GoogleSignIn (~> 4.4.0)
- RNGoogleSignin (3.0.1):
- GoogleSignIn (~> 5.0.0)
- React
- RNSound (0.11.0):
- React
- RNSound/Core (= 0.11.0)
- RNSound/Core (0.11.0):
- React
- RNVectorIcons (6.0.2):
- RNSVG (9.7.1):
- React
- RNWatch (0.2.0):
- React
- yoga (0.60.5.React)
- Yoga (1.14.0)
DEPENDENCIES:
- Amplitude-iOS (~> 4.0.4)
- BVLinearGradient (from `../node_modules/react-native-linear-gradient`)
- CocoaLumberjack (~> 3.5.3)
- Crashlytics (~> 3.12.0)
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- Fabric (~> 1.9.0)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector/`)
- FBReactNativeSpec (from `../node_modules/react-native/Libraries/FBReactNativeSpec/`)
- Firebase/Core (~> 5.18.0)
- Firebase/DynamicLinks (~> 5.18.0)
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- ObjectiveDropboxOfficial (~> 3.9.4)
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired/`)
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety/`)
- React (from `../node_modules/react-native/`)
- React-Core (from `../node_modules/react-native/React`)
- React-Core/CoreModulesHeaders (from `../node_modules/react-native/`)
- React-Core/DevSupport (from `../node_modules/react-native/`)
- React-Core/RCTWebSocket (from `../node_modules/react-native/`)
- React-CoreModules (from `../node_modules/react-native/React/CoreModules`)
- React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`)
- React-DevSupport (from `../node_modules/react-native/React`)
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- react-native-background-timer (from `../node_modules/react-native-background-timer`)
- react-native-calendar-events (from `../node_modules/react-native-calendar-events`)
- react-native-keep-awake (from `../node_modules/react-native-keep-awake`)
- react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
- react-native-webrtc (from `../node_modules/react-native-webrtc`)
- react-native-webview (from `../node_modules/react-native-webview`)
- React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
@@ -217,18 +388,19 @@ DEPENDENCIES:
- React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`)
- React-RCTText (from `../node_modules/react-native/Libraries/Text`)
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
- React-RCTWebSocket (from `../node_modules/react-native/Libraries/WebSocket`)
- ReactCommon/turbomodule (from `../node_modules/react-native/ReactCommon`)
- "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)"
- RNGoogleSignin (from `../node_modules/react-native-google-signin`)
- "RNGoogleSignin (from `../node_modules/@react-native-community/google-signin`)"
- RNSound (from `../node_modules/react-native-sound`)
- RNVectorIcons (from `../node_modules/react-native-vector-icons`)
- RNSVG (from `../node_modules/react-native-svg`)
- RNWatch (from `../node_modules/react-native-watch-connectivity`)
- yoga (from `../node_modules/react-native/ReactCommon/yoga`)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
SPEC REPOS:
https://github.com/cocoapods/specs.git:
https://github.com/CocoaPods/Specs.git:
- Amplitude-iOS
- boost-for-react-native
- CocoaLumberjack
- Crashlytics
- Fabric
- Firebase
@@ -238,30 +410,40 @@ SPEC REPOS:
- FirebaseDynamicLinks
- FirebaseInstanceID
- GoogleAppMeasurement
- GoogleSignIn
- GoogleToolboxForMac
- GoogleUtilities
- GTMSessionFetcher
- nanopb
- ObjectiveDropboxOfficial
trunk:
- AppAuth
- GoogleSignIn
- GTMAppAuth
- GTMSessionFetcher
EXTERNAL SOURCES:
BVLinearGradient:
:path: "../node_modules/react-native-linear-gradient"
DoubleConversion:
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
FBLazyVector:
:path: "../node_modules/react-native/Libraries/FBLazyVector/"
FBReactNativeSpec:
:path: "../node_modules/react-native/Libraries/FBReactNativeSpec/"
Folly:
:podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec"
glog:
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
RCTRequired:
:path: "../node_modules/react-native/Libraries/RCTRequired/"
RCTTypeSafety:
:path: "../node_modules/react-native/Libraries/TypeSafety/"
React:
:path: "../node_modules/react-native/"
React-Core:
:path: "../node_modules/react-native/React"
:path: "../node_modules/react-native/"
React-CoreModules:
:path: "../node_modules/react-native/React/CoreModules"
React-cxxreact:
:path: "../node_modules/react-native/ReactCommon/cxxreact"
React-DevSupport:
:path: "../node_modules/react-native/React"
React-jsi:
:path: "../node_modules/react-native/ReactCommon/jsi"
React-jsiexecutor:
@@ -298,28 +480,32 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/Libraries/Text"
React-RCTVibration:
:path: "../node_modules/react-native/Libraries/Vibration"
React-RCTWebSocket:
:path: "../node_modules/react-native/Libraries/WebSocket"
ReactCommon:
:path: "../node_modules/react-native/ReactCommon"
RNCAsyncStorage:
:path: "../node_modules/@react-native-community/async-storage"
RNGoogleSignin:
:path: "../node_modules/react-native-google-signin"
:path: "../node_modules/@react-native-community/google-signin"
RNSound:
:path: "../node_modules/react-native-sound"
RNVectorIcons:
:path: "../node_modules/react-native-vector-icons"
RNSVG:
:path: "../node_modules/react-native-svg"
RNWatch:
:path: "../node_modules/react-native-watch-connectivity"
yoga:
Yoga:
:path: "../node_modules/react-native/ReactCommon/yoga"
SPEC CHECKSUMS:
Amplitude-iOS: 2ad4d7270c99186236c1272a3a9425463b1ae1a7
AppAuth: bce82c76043657c99d91e7882e8a9e1a93650cd4
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
CocoaLumberjack: 2f44e60eb91c176d471fdba43b9e3eae6a721947
Crashlytics: 07fb167b1694128c1c9a5a5cc319b0e9c3ca0933
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
Fabric: f988e33c97f08930a413e08123064d2e5f68d655
FBLazyVector: 5bc5b1606fc9a7ac6956de049f6e30901ed31c49
FBReactNativeSpec: f7be9bcc5ce259f7c39509f3f4caf59020d11d4c
Firebase: 02f3281965c075426141a0ce1277e9de6649cab9
FirebaseAnalytics: 23851fe602c872130a2c5c55040b302120346cc2
FirebaseAnalyticsInterop: efbe45c8385ec626e29f9525e5ebd38520dfb6c1
@@ -329,42 +515,44 @@ SPEC CHECKSUMS:
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
glog: 1f3da668190260b06b429bb211bfbee5cd790c28
GoogleAppMeasurement: 6cf307834da065863f9faf4c0de0a936d81dd832
GoogleSignIn: 7ff245e1a7b26d379099d3243a562f5747e23d39
GoogleToolboxForMac: ff31605b7d66400dcec09bed5861689aebadda4d
GoogleSignIn: 3a51b9bb8e48b635fd7f4272cee06ca260345b86
GoogleUtilities: 1e25823cbf46540b4284f6ef8e17b3a68ee12bbc
GTMSessionFetcher: 32aeca0aa144acea523e1c8e053089dec2cb98ca
GTMAppAuth: 4deac854479704f348309e7b66189e604cf5e01e
GTMSessionFetcher: 61bb0f61a4cb560030f1222021178008a5727a23
nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48
ObjectiveDropboxOfficial: a5afefc83f6467c42c45f2253f583f2ad1ffc701
React: 53c53c4d99097af47cf60594b8706b4e3321e722
React-Core: ba421f6b4f4cbe2fb17c0b6fc675f87622e78a64
React-cxxreact: 8384287780c4999351ad9b6e7a149d9ed10a2395
React-DevSupport: 197fb409737cff2c4f9986e77c220d7452cb9f9f
React-jsi: 4d8c9efb6312a9725b18d6fc818ffc103f60fec2
React-jsiexecutor: 90ad2f9db09513fc763bc757fdc3c4ff8bde2a30
React-jsinspector: e08662d1bf5b129a3d556eb9ea343a3f40353ae4
RCTRequired: a72523286ea3381f97b28d87529c265baad3ad7d
RCTTypeSafety: e3cc0537400222250f0be37bd69f4b339d3c0a0f
React: 3dc877fc32548b0c7108ca7f301466f4956cbff8
React-Core: ca94e2e7d22cdcc266a405c4d2ad5e5675145776
React-CoreModules: aa415458b5d7dacd10ac1b324d679f6e17cd8685
React-cxxreact: bac5da3d62ee98abd3c1bf7338a7cc6205da7f69
React-jsi: 8bcf5836caa8a759c135ab9ef97f3e023a7b94af
React-jsiexecutor: ae078e9df9c65bcdcf68f9a17656657932d95528
React-jsinspector: a8939cc6909607eb5e8a5ecfff7c6226984e174d
react-native-background-timer: 0d34748e53a972507c66963490c775321a88f6f2
react-native-calendar-events: 2fe35a9294af05de0ed819d3a1b5dac048d2c010
react-native-keep-awake: eba3137546b10003361b37c761f6c429b59814ae
react-native-netinfo: 8d8db463bcc5db66a8ac5c48a7d86beb3b92f61a
react-native-webrtc: 1415d2a54b2246dd85ba95eb3e4bf2b66533f951
react-native-webview: a95842e3f351a6d2c8bc8bcc9eab689c7e7e5ad4
React-RCTActionSheet: b0f1ea83f4bf75fb966eae9bfc47b78c8d3efd90
React-RCTAnimation: 359ba1b5690b1e87cc173558a78e82d35919333e
React-RCTBlob: 5e2b55f76e9a1c7ae52b826923502ddc3238df24
React-RCTImage: f5f1c50922164e89bdda67bcd0153952a5cfe719
React-RCTLinking: d0ecbd791e9ddddc41fa1f66b0255de90e8ee1e9
React-RCTNetwork: e26946300b0ab7bb6c4a6348090e93fa21f33a9d
React-RCTSettings: d0d37cb521b7470c998595a44f05847777cc3f42
React-RCTText: b074d89033583d4f2eb5faf7ea2db3a13c7553a2
React-RCTVibration: 2105b2e0e2b66a6408fc69a46c8a7fb5b2fdade0
React-RCTWebSocket: cd932a16b7214898b6b7f788c8bddb3637246ac4
react-native-webrtc: c5e3d631179a933548a8e49bddbd8fad02586095
react-native-webview: 4dbc1d2a4a6b9c5e9e723c62651917aa2b5e579e
React-RCTActionSheet: 94671eef55b01a93be735605822ef712d5ea208e
React-RCTAnimation: 524ae33e73de9c0fe6501a7a4bda8e01d26499d9
React-RCTBlob: 5481c2db702f57207af7e7a9b32d90524b821b72
React-RCTImage: b472cc0606f8a7c1ac270d6ccc57123a09439a32
React-RCTLinking: 9cfc7bfdfda078489736695ac476de1f265b9f82
React-RCTNetwork: 967547e4eeac92e55d41573a82da7fff4003052a
React-RCTSettings: 6ab7911172056b5077dacd9240f057eeeb1b121b
React-RCTText: b8f895b94aa0e7778fef28d13f3d71eed4a10c3d
React-RCTVibration: 262588c97551b0b1c675468cda857466ba5af18f
ReactCommon: c2c63d9290b422ca6ad5b3663073a015dd892ae9
RNCAsyncStorage: 8e31405a9f12fbf42c2bb330e4560bfd79c18323
RNGoogleSignin: d030c6c6591db24c3cee649f64c7babf0a1699a0
RNGoogleSignin: 39336070b35fc4cea6a98cf111e00480317be0ae
RNSound: c980916b596cc15c8dcd2f6ecd3b13c4881dbe20
RNVectorIcons: d819334932bcda3332deb3d2c8ea4d069e0b98f9
RNSVG: aac12785382e8fd4f28d072fe640612e34914631
RNWatch: 09738b339eceb66e4d80a2371633ca5fb380fa42
yoga: 312528f5bbbba37b4dcea5ef00e8b4033fdd9411
Yoga: 02036f6383c0008edb7ef0773a0e6beb6ce82bd1
PODFILE CHECKSUM: 0907bfe60b5b5f11dbdc6b4e65d40a248d000513
PODFILE CHECKSUM: 63c90b1d33cd96709fb72bad6be440ae9c3deecb
COCOAPODS: 1.7.2
COCOAPODS: 1.8.1

View File

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

View File

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

View File

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

View File

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

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

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

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

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

View File

@@ -2,7 +2,7 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildSystemType</key>
<string>Original</string>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@@ -23,11 +23,8 @@
0BCA495F1EC4B6C600B793EE /* AudioMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495C1EC4B6C600B793EE /* AudioMode.m */; };
0BCA49601EC4B6C600B793EE /* POSIX.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495D1EC4B6C600B793EE /* POSIX.m */; };
0BCA49611EC4B6C600B793EE /* Proximity.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495E1EC4B6C600B793EE /* Proximity.m */; };
0BCA496C1EC4BBF900B793EE /* jitsi.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 0BCA496B1EC4BBF900B793EE /* jitsi.ttf */; };
0BD906EA1EC0C00300C8C18E /* JitsiMeet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BD906E81EC0C00300C8C18E /* JitsiMeet.h */; settings = {ATTRIBUTES = (Public, ); }; };
0F65EECE1D95DA94561BB47E /* libPods-JitsiMeet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 03F2ADC957FF109849B7FCA1 /* libPods-JitsiMeet.a */; };
C30F88D0CB0F4F5593216D24 /* liveStreamingOff.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = C30F88D1CB0F4F5593216D24 /* liveStreamingOff.mp3 */; };
C30F88D2CB0F4F5593216D24 /* liveStreamingOn.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = C30F88D3CB0F4F5593216D24 /* liveStreamingOn.mp3 */; };
6C31EDC820C06D490089C899 /* recordingOn.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 6C31EDC720C06D490089C899 /* recordingOn.mp3 */; };
6C31EDCA20C06D530089C899 /* recordingOff.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 6C31EDC920C06D530089C899 /* recordingOff.mp3 */; };
75635B0A20751D6D00F29C9F /* joined.wav in Resources */ = {isa = PBXBuildFile; fileRef = 75635B0820751D6D00F29C9F /* joined.wav */; };
@@ -36,6 +33,8 @@
A4414AE020B37F1A003546E6 /* rejected.wav in Resources */ = {isa = PBXBuildFile; fileRef = A4414ADF20B37F1A003546E6 /* rejected.wav */; };
A480429C21EE335600289B73 /* AmplitudeModule.m in Sources */ = {isa = PBXBuildFile; fileRef = A480429B21EE335600289B73 /* AmplitudeModule.m */; };
A4A934E9212F3ADB001E9388 /* Dropbox.m in Sources */ = {isa = PBXBuildFile; fileRef = A4A934E8212F3ADB001E9388 /* Dropbox.m */; };
C30F88D0CB0F4F5593216D24 /* liveStreamingOff.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = C30F88D1CB0F4F5593216D24 /* liveStreamingOff.mp3 */; };
C30F88D2CB0F4F5593216D24 /* liveStreamingOn.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = C30F88D3CB0F4F5593216D24 /* liveStreamingOn.mp3 */; };
C6245F5D2053091D0040BE68 /* image-resize@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C6245F5B2053091D0040BE68 /* image-resize@2x.png */; };
C6245F5E2053091D0040BE68 /* image-resize@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C6245F5C2053091D0040BE68 /* image-resize@3x.png */; };
C69EFA0C209A0F660027712B /* JMCallKitEmitter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C69EFA09209A0F650027712B /* JMCallKitEmitter.swift */; };
@@ -43,8 +42,16 @@
C69EFA0E209A0F660027712B /* JMCallKitListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = C69EFA0B209A0F660027712B /* JMCallKitListener.swift */; };
C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3425E204EF76800E062DD /* DragGestureController.swift */; };
C6CC49AF207412CF000DFA42 /* PiPViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6CC49AE207412CF000DFA42 /* PiPViewCoordinator.swift */; };
DE438CDA2350934700DD541D /* JavaScriptSandbox.m in Sources */ = {isa = PBXBuildFile; fileRef = DE438CD82350934700DD541D /* JavaScriptSandbox.m */; };
DE65AACA2317FFCD00290BEC /* LogUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AAC92317FFCD00290BEC /* LogUtils.h */; };
DE65AACC2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */; };
DE762DB422AFDE76000DEBD6 /* JitsiMeetUserInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DE762DB322AFDE76000DEBD6 /* JitsiMeetUserInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
DE762DB622AFDE8D000DEBD6 /* JitsiMeetUserInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = DE762DB522AFDE8D000DEBD6 /* JitsiMeetUserInfo.m */; };
DE81A2D42316AC4D00AE1940 /* JitsiMeetLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = DE81A2D22316AC4D00AE1940 /* JitsiMeetLogger.h */; settings = {ATTRIBUTES = (Public, ); }; };
DE81A2D52316AC4D00AE1940 /* JitsiMeetLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = DE81A2D32316AC4D00AE1940 /* JitsiMeetLogger.m */; };
DE81A2D92316AC7600AE1940 /* LogBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = DE81A2D72316AC7600AE1940 /* LogBridge.m */; };
DE81A2DE2317ED5400AE1940 /* JitsiMeetBaseLogHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = DE81A2DC2317ED5400AE1940 /* JitsiMeetBaseLogHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
DE81A2DF2317ED5400AE1940 /* JitsiMeetBaseLogHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = DE81A2DD2317ED5400AE1940 /* JitsiMeetBaseLogHandler.m */; };
DEAD3226220C497000E93636 /* JitsiMeetConferenceOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = DEAD3224220C497000E93636 /* JitsiMeetConferenceOptions.h */; settings = {ATTRIBUTES = (Public, ); }; };
DEAD3227220C497000E93636 /* JitsiMeetConferenceOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = DEAD3225220C497000E93636 /* JitsiMeetConferenceOptions.m */; };
DEAFA779229EAD520033A7FA /* RNRootView.m in Sources */ = {isa = PBXBuildFile; fileRef = DEAFA778229EAD520033A7FA /* RNRootView.m */; };
@@ -77,8 +84,6 @@
0BD906E51EC0C00300C8C18E /* JitsiMeet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JitsiMeet.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0BD906E81EC0C00300C8C18E /* JitsiMeet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeet.h; sourceTree = "<group>"; };
0BD906E91EC0C00300C8C18E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C30F88D1CB0F4F5593216D24 /* liveStreamingOff.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = liveStreamingOff.mp3; path = ../../sounds/liveStreamingOff.mp3; sourceTree = "<group>"; };
C30F88D3CB0F4F5593216D24 /* liveStreamingOn.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = liveStreamingOn.mp3; path = ../../sounds/liveStreamingOn.mp3; sourceTree = "<group>"; };
6C31EDC720C06D490089C899 /* recordingOn.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = recordingOn.mp3; path = ../../sounds/recordingOn.mp3; sourceTree = "<group>"; };
6C31EDC920C06D530089C899 /* recordingOff.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = recordingOff.mp3; path = ../../sounds/recordingOff.mp3; sourceTree = "<group>"; };
75635B0820751D6D00F29C9F /* joined.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = joined.wav; path = ../../sounds/joined.wav; sourceTree = "<group>"; };
@@ -90,6 +95,8 @@
A480429B21EE335600289B73 /* AmplitudeModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AmplitudeModule.m; path = src/analytics/AmplitudeModule.m; sourceTree = SOURCE_ROOT; };
A4A934E8212F3ADB001E9388 /* Dropbox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Dropbox.m; sourceTree = "<group>"; };
A4A934EB21349A06001E9388 /* Dropbox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Dropbox.h; sourceTree = "<group>"; };
C30F88D1CB0F4F5593216D24 /* liveStreamingOff.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = liveStreamingOff.mp3; path = ../../sounds/liveStreamingOff.mp3; sourceTree = "<group>"; };
C30F88D3CB0F4F5593216D24 /* liveStreamingOn.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = liveStreamingOn.mp3; path = ../../sounds/liveStreamingOn.mp3; sourceTree = "<group>"; };
C6245F5B2053091D0040BE68 /* image-resize@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "image-resize@2x.png"; path = "src/picture-in-picture/image-resize@2x.png"; sourceTree = "<group>"; };
C6245F5C2053091D0040BE68 /* image-resize@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "image-resize@3x.png"; path = "src/picture-in-picture/image-resize@3x.png"; sourceTree = "<group>"; };
C69EFA09209A0F650027712B /* JMCallKitEmitter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JMCallKitEmitter.swift; sourceTree = "<group>"; };
@@ -98,9 +105,17 @@
C6A3425E204EF76800E062DD /* DragGestureController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DragGestureController.swift; sourceTree = "<group>"; };
C6CC49AE207412CF000DFA42 /* PiPViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PiPViewCoordinator.swift; sourceTree = "<group>"; };
C6F99C13204DB63D0001F710 /* JitsiMeetView+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetView+Private.h"; sourceTree = "<group>"; };
DE438CD82350934700DD541D /* JavaScriptSandbox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JavaScriptSandbox.m; sourceTree = "<group>"; };
DE65AAC92317FFCD00290BEC /* LogUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LogUtils.h; sourceTree = "<group>"; };
DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetBaseLogHandler+Private.h"; sourceTree = "<group>"; };
DE762DB322AFDE76000DEBD6 /* JitsiMeetUserInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeetUserInfo.h; sourceTree = "<group>"; };
DE762DB522AFDE8D000DEBD6 /* JitsiMeetUserInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JitsiMeetUserInfo.m; sourceTree = "<group>"; };
DE762DB722AFE166000DEBD6 /* JitsiMeetUserInfo+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetUserInfo+Private.h"; sourceTree = "<group>"; };
DE81A2D22316AC4D00AE1940 /* JitsiMeetLogger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeetLogger.h; sourceTree = "<group>"; };
DE81A2D32316AC4D00AE1940 /* JitsiMeetLogger.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JitsiMeetLogger.m; sourceTree = "<group>"; };
DE81A2D72316AC7600AE1940 /* LogBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LogBridge.m; sourceTree = "<group>"; };
DE81A2DC2317ED5400AE1940 /* JitsiMeetBaseLogHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeetBaseLogHandler.h; sourceTree = "<group>"; };
DE81A2DD2317ED5400AE1940 /* JitsiMeetBaseLogHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JitsiMeetBaseLogHandler.m; sourceTree = "<group>"; };
DEAD3224220C497000E93636 /* JitsiMeetConferenceOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeetConferenceOptions.h; sourceTree = "<group>"; };
DEAD3225220C497000E93636 /* JitsiMeetConferenceOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JitsiMeetConferenceOptions.m; sourceTree = "<group>"; };
DEAD3228220C734300E93636 /* JitsiMeetConferenceOptions+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetConferenceOptions+Private.h"; sourceTree = "<group>"; };
@@ -177,6 +192,7 @@
A4A934E7212F3AB8001E9388 /* dropbox */,
0BA13D301EE83FF8007BEF7F /* ExternalAPI.m */,
0BD906E91EC0C00300C8C18E /* Info.plist */,
DE438CD82350934700DD541D /* JavaScriptSandbox.m */,
0BD906E81EC0C00300C8C18E /* JitsiMeet.h */,
DEFE535821FB311F00011A3A /* JitsiMeet+Private.h */,
DEFE535321FB1BF800011A3A /* JitsiMeet.m */,
@@ -186,8 +202,15 @@
DE762DB322AFDE76000DEBD6 /* JitsiMeetUserInfo.h */,
DE762DB722AFE166000DEBD6 /* JitsiMeetUserInfo+Private.h */,
DE762DB522AFDE8D000DEBD6 /* JitsiMeetUserInfo.m */,
DE81A2D22316AC4D00AE1940 /* JitsiMeetLogger.h */,
DE81A2D32316AC4D00AE1940 /* JitsiMeetLogger.m */,
DE81A2DC2317ED5400AE1940 /* JitsiMeetBaseLogHandler.h */,
DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */,
DE81A2DD2317ED5400AE1940 /* JitsiMeetBaseLogHandler.m */,
0B412F161EDEC65D00B1A0A6 /* JitsiMeetView.h */,
0B412F171EDEC65D00B1A0A6 /* JitsiMeetView.m */,
DE81A2D72316AC7600AE1940 /* LogBridge.m */,
DE65AAC92317FFCD00290BEC /* LogUtils.h */,
DEAFA777229EAD3B0033A7FA /* RNRootView.h */,
DEAFA778229EAD520033A7FA /* RNRootView.m */,
C6F99C13204DB63D0001F710 /* JitsiMeetView+Private.h */,
@@ -273,8 +296,12 @@
DE762DB422AFDE76000DEBD6 /* JitsiMeetUserInfo.h in Headers */,
0B412F181EDEC65D00B1A0A6 /* JitsiMeetView.h in Headers */,
0B93EF7E1EC9DDCD0030D24D /* RCTBridgeWrapper.h in Headers */,
DE81A2DE2317ED5400AE1940 /* JitsiMeetBaseLogHandler.h in Headers */,
DE65AACC2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h in Headers */,
0B412F221EDEF6EA00B1A0A6 /* JitsiMeetViewDelegate.h in Headers */,
0BD906EA1EC0C00300C8C18E /* JitsiMeet.h in Headers */,
DE81A2D42316AC4D00AE1940 /* JitsiMeetLogger.h in Headers */,
DE65AACA2317FFCD00290BEC /* LogUtils.h in Headers */,
DEAD3226220C497000E93636 /* JitsiMeetConferenceOptions.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -294,7 +321,6 @@
0BD906E31EC0C00300C8C18E /* Resources */,
0BCA49651EC4B77500B793EE /* Package React bundle */,
C7BC10B338C94EEB98048E64 /* [CP] Copy Pods Resources */,
0B64F7BE2175DFEA005009CD /* Remove unneeded fonts */,
);
buildRules = (
);
@@ -351,7 +377,6 @@
6C31EDCA20C06D530089C899 /* recordingOff.mp3 in Resources */,
A4414AE020B37F1A003546E6 /* rejected.wav in Resources */,
0B49424620AD8DBD00BD2DE0 /* outgoingRinging.wav in Resources */,
0BCA496C1EC4BBF900B793EE /* jitsi.ttf in Resources */,
C6245F5D2053091D0040BE68 /* image-resize@2x.png in Resources */,
6C31EDC820C06D490089C899 /* recordingOn.mp3 in Resources */,
0BC4B8691F8C03A700CE8B21 /* CallKitIcon.png in Resources */,
@@ -364,24 +389,6 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
0B64F7BE2175DFEA005009CD /* Remove unneeded fonts */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "Remove unneeded fonts";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# We need to manually do this because react-native-vecotr-icons lists fonts as resources in the Pod spec file\n# so they are automatically added.\n\nshopt -s extglob\n\nrm -f ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/!(jitsi).ttf\n";
};
0BCA49651EC4B77500B793EE /* Package React bundle */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -426,21 +433,6 @@
"${PODS_ROOT}/Amplitude-iOS/Amplitude/ComodoRsaCA.der",
"${PODS_ROOT}/Amplitude-iOS/Amplitude/ComodoRsaDomainValidationCA.der",
"${PODS_ROOT}/GoogleSignIn/Resources/GoogleSignIn.bundle",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Feather.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Regular.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Foundation.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Octicons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Zocial.ttf",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
@@ -449,21 +441,6 @@
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ComodoRsaCA.der",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ComodoRsaDomainValidationCA.der",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleSignIn.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AntDesign.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Entypo.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EvilIcons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Feather.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Brands.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Regular.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Solid.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Foundation.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Ionicons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialCommunityIcons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialIcons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Octicons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SimpleLineIcons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Zocial.ttf",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@@ -496,7 +473,9 @@
buildActionMask = 2147483647;
files = (
0BB9AD7B1F5EC8F4001C08DB /* CallKit.m in Sources */,
DE81A2DF2317ED5400AE1940 /* JitsiMeetBaseLogHandler.m in Sources */,
0BB9AD7D1F60356D001C08DB /* AppInfo.m in Sources */,
DE81A2D92316AC7600AE1940 /* LogBridge.m in Sources */,
DEAFA779229EAD520033A7FA /* RNRootView.m in Sources */,
DE762DB622AFDE8D000DEBD6 /* JitsiMeetUserInfo.m in Sources */,
DEAD3227220C497000E93636 /* JitsiMeetConferenceOptions.m in Sources */,
@@ -513,9 +492,11 @@
C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */,
A4A934E9212F3ADB001E9388 /* Dropbox.m in Sources */,
C69EFA0D209A0F660027712B /* JMCallKitProxy.swift in Sources */,
DE81A2D52316AC4D00AE1940 /* JitsiMeetLogger.m in Sources */,
C69EFA0E209A0F660027712B /* JMCallKitListener.swift in Sources */,
0B412F191EDEC65D00B1A0A6 /* JitsiMeetView.m in Sources */,
DEFE535421FB1BF800011A3A /* JitsiMeet.m in Sources */,
DE438CDA2350934700DD541D /* JavaScriptSandbox.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -646,6 +627,7 @@
baseConfigurationReference = 98E09B5C73D9036B4ED252FC /* Pods-JitsiMeet.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
BUILD_LIBRARY_FOR_DISTRIBUTION = NO;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
@@ -657,15 +639,18 @@
ENABLE_BITCODE = NO;
INFOPLIST_FILE = src/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.JitsiMeetSDK.ios;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SUPPORTS_MACCATALYST = NO;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
@@ -674,6 +659,7 @@
baseConfigurationReference = 9C77CA3CC919B081F1A52982 /* Pods-JitsiMeet.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
@@ -685,14 +671,17 @@
ENABLE_BITCODE = YES;
INFOPLIST_FILE = src/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.JitsiMeetSDK.ios;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SUPPORTS_MACCATALYST = NO;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};

View File

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

View File

@@ -20,6 +20,8 @@
#import <React/RCTLog.h>
#import <WebRTC/WebRTC.h>
#import "LogUtils.h"
// Audio mode
typedef enum {
@@ -167,7 +169,7 @@ RCT_EXPORT_METHOD(setMode:(int)mode
RCT_EXPORT_METHOD(setAudioDevice:(NSString *)device
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {
NSLog(@"[AudioMode] Selected device: %@", device);
DDLogInfo(@"[AudioMode] Selected device: %@", device);
RTCAudioSession *session = [RTCAudioSession sharedInstance];
[session lockForConfiguration];
@@ -260,7 +262,7 @@ RCT_EXPORT_METHOD(updateDeviceList) {
// This is to play well with other components which could be integrated
// into the final application.
if (self->activeMode != kAudioModeDefault) {
NSLog(@"[AudioMode] Route changed, reapplying RTCAudioSession config");
DDLogInfo(@"[AudioMode] Route changed, reapplying RTCAudioSession config");
RTCAudioSessionConfiguration *config = [self configForMode:self->activeMode];
[self setConfig:config error:nil];
if (self->forceSpeaker && !self->isSpeakerOn) {
@@ -274,7 +276,7 @@ RCT_EXPORT_METHOD(updateDeviceList) {
}
- (void)audioSession:(RTCAudioSession *)audioSession didSetActive:(BOOL)active {
NSLog(@"[AudioMode] Audio session didSetActive:%d", active);
DDLogInfo(@"[AudioMode] Audio session didSetActive:%d", active);
}
#pragma mark - Helper methods

View File

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

View File

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

View File

@@ -18,6 +18,8 @@
#import <JitsiMeet/JitsiMeetView.h>
#import <JitsiMeet/JitsiMeetViewDelegate.h>
#import <JitsiMeet/JitsiMeetConferenceOptions.h>
#import <JitsiMeet/JitsiMeetLogger.h>
#import <JitsiMeet/JitsiMeetBaseLogHandler.h>
@interface JitsiMeet : NSObject
@@ -35,7 +37,6 @@
* List of domains used for universal linking.
*/
@property (copy, nonatomic, nullable) NSArray<NSString *> *universalLinkDomains;
/**
* Default conference options used for all conferences. These options will be merged
* with those passed to JitsiMeetView.join when joining a conference.

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,105 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "JitsiMeetBaseLogHandler+Private.h"
@interface PrivateLogger : DDAbstractLogger <DDLogger>
@end
@implementation PrivateLogger {
JitsiMeetBaseLogHandler *_delegate;
}
- (instancetype)initWithDelegate:(JitsiMeetBaseLogHandler *)delegate {
if (self = [super init]) {
_delegate = delegate;
}
return self;
}
#pragma mark - DDAbstractLogger interface
- (void)logMessage:(DDLogMessage *)logMessage {
NSString *logMsg = logMessage.message;
if (_logFormatter)
logMsg = [_logFormatter formatLogMessage:logMessage];
if (logMsg && _delegate) {
switch (logMessage.flag) {
case DDLogFlagError:
[_delegate logError:logMsg];
break;
case DDLogFlagWarning:
[_delegate logWarn:logMsg];
break;
case DDLogFlagInfo:
[_delegate logInfo:logMsg];
break;
case DDLogFlagDebug:
[_delegate logDebug:logMsg];
break;
case DDLogFlagVerbose:
[_delegate logVerbose:logMsg];
break;
}
}
}
@end
@implementation JitsiMeetBaseLogHandler
#pragma mark - Proxy logger not to expose the CocoaLumberjack headers
- (instancetype)init {
if (self = [super init]) {
self.logger = [[PrivateLogger alloc] initWithDelegate:self];
}
return self;
}
#pragma mark - Public API
- (void)logVerbose:(NSString *)msg {
// Override me!
[self doesNotRecognizeSelector:_cmd];
}
- (void)logDebug:(NSString *)msg {
// Override me!
[self doesNotRecognizeSelector:_cmd];
}
- (void)logInfo:(NSString *)msg {
// Override me!
[self doesNotRecognizeSelector:_cmd];
}
- (void)logWarn:(NSString *)msg {
// Override me!
[self doesNotRecognizeSelector:_cmd];
}
- (void)logError:(NSString *)msg {
// Override me!
[self doesNotRecognizeSelector:_cmd];
}
@end

View File

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

View File

@@ -0,0 +1,42 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "LogUtils.h"
#import "JitsiMeetLogger.h"
#import "JitsiMeetBaseLogHandler+Private.h"
@implementation JitsiMeetLogger
/**
* This gets called automagically when the program starts.
*/
__attribute__((constructor))
static void initializeLogger() {
NSString *mainBundleId = [NSBundle mainBundle].bundleIdentifier;
DDOSLogger *osLogger = [[DDOSLogger alloc] initWithSubsystem:mainBundleId category:@"JitsiMeetSDK"];
[DDLog addLogger:osLogger];
}
+ (void)addHandler:(JitsiMeetBaseLogHandler *)handler {
[DDLog addLogger:handler.logger];
}
+ (void)removeHandler:(JitsiMeetBaseLogHandler *)handler {
[DDLog removeLogger:handler.logger];
}
@end

57
ios/sdk/src/LogBridge.m Normal file
View File

@@ -0,0 +1,57 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <React/RCTBridgeModule.h>
#import "LogUtils.h"
@interface LogBridge : NSObject<RCTBridgeModule>
@end
@implementation LogBridge
RCT_EXPORT_MODULE();
+ (BOOL)requiresMainQueueSetup {
return NO;
}
RCT_EXPORT_METHOD(trace:(NSString *)msg) {
DDLogDebug(@"%@", msg);
}
RCT_EXPORT_METHOD(debug:(NSString *)msg) {
DDLogDebug(@"%@", msg);
}
RCT_EXPORT_METHOD(info:(NSString *)msg) {
DDLogInfo(@"%@", msg);
}
RCT_EXPORT_METHOD(log:(NSString *)msg) {
DDLogInfo(@"%@", msg);
}
RCT_EXPORT_METHOD(warn:(NSString *)msg) {
DDLogWarn(@"%@", msg);
}
RCT_EXPORT_METHOD(error:(NSString *)msg) {
DDLogError(@"%@", msg);
}
@end

23
ios/sdk/src/LogUtils.h Normal file
View File

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

View File

@@ -19,5 +19,6 @@
NSMutableDictionary* mergeProps(NSDictionary *a, NSDictionary *b);
void registerReactFatalErrorHandler(void);
void registerReactLogHandler(void);
#endif /* JM_REACTUTILS_H */

View File

@@ -15,7 +15,9 @@
*/
#import <React/RCTAssert.h>
#import <React/RCTLog.h>
#import "LogUtils.h"
#import "ReactUtils.h"
#pragma mark - Utility functions
@@ -67,19 +69,11 @@ NSMutableDictionary* mergeProps(NSDictionary *a, NSDictionary *b) {
*/
RCTFatalHandler _RCTFatal = ^(NSError *error) {
id jsStackTrace = error.userInfo[RCTJSStackTraceKey];
@try {
NSString *name
= [NSString stringWithFormat:@"%@: %@",
RCTFatalExceptionName,
error.localizedDescription];
NSString *message
= RCTFormatError(error.localizedDescription, jsStackTrace, 75);
[NSException raise:name format:@"%@", message];
} @catch (NSException *e) {
if (!jsStackTrace) {
@throw;
}
}
NSString *name
= [NSString stringWithFormat:@"%@: %@", RCTFatalExceptionName, error.localizedDescription];
NSString *message
= RCTFormatError(error.localizedDescription, jsStackTrace, -1);
DDLogError(@"FATAL ERROR: %@\n%@", name, message);
};
/**
@@ -98,3 +92,62 @@ void registerReactFatalErrorHandler() {
}
#endif
}
/**
* A `RTCLogFunction` implementation which uses CocoaLumberjack.
*/
RCTLogFunction _RCTLog
= ^(RCTLogLevel level, __unused RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message)
{
// Convert RN log levels into Lumberjack's log flags.
//
DDLogFlag logFlag;
switch (level) {
case RCTLogLevelTrace:
logFlag = DDLogFlagDebug;
break;
case RCTLogLevelInfo:
logFlag = DDLogFlagInfo;
break;
case RCTLogLevelWarning:
logFlag = DDLogFlagWarning;
break;
case RCTLogLevelError:
logFlag = DDLogFlagError;
break;
case RCTLogLevelFatal:
logFlag = DDLogFlagError;
break;
default:
// Just in case more are added in the future.
logFlag = DDLogFlagInfo;
break;
}
// Build the message object we want to log.
//
DDLogMessage *logMessage
= [[DDLogMessage alloc] initWithMessage:message
level:LOG_LEVEL_DEF
flag:logFlag
context:0
file:fileName
function:nil
line:[lineNumber integerValue]
tag:nil
options:0
timestamp:nil];
// Log the message. Errors are logged synchronously, and other async, as the Lumberjack defaults.
//
[DDLog log:logFlag != DDLogFlagError
message:logMessage];
};
/**
* Helper function which registers a React Native log handler.
*/
void registerReactLogHandler() {
RCTSetLogFunction(_RCTLog);
RCTSetLogThreshold(RCTLogLevelInfo);
}

View File

@@ -15,10 +15,12 @@
*/
#import <React/RCTBridgeModule.h>
#import "Amplitude.h"
#import "LogUtils.h"
@interface AmplitudeModule : NSObject<RCTBridgeModule>
@end
@implementation AmplitudeModule
@@ -50,7 +52,7 @@ RCT_EXPORT_METHOD(logEvent:(NSString*)instanceName eventType:(NSString*)eventTyp
options:NSJSONReadingMutableContainers
error:&error];
if (eventProperties == nil) {
NSLog(@"[Amplitude handler] Error parsing event properties: %@", error);
DDLogError(@"[Amplitude] Error parsing event properties: %@", error);
} else {
[[Amplitude instanceWithName:instanceName] logEvent:eventType withEventProperties:eventProperties];
}

View File

@@ -30,6 +30,9 @@
#import <JitsiMeet/JitsiMeet-Swift.h>
#import "LogUtils.h"
// The events emitted/supported by RNCallKit:
static NSString * const RNCallKitPerformAnswerCallAction
= @"performAnswerCallAction";
@@ -69,9 +72,7 @@ RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(endCall:(NSString *)callUUID
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {
#ifdef DEBUG
NSLog(@"[RNCallKit][endCall] callUUID = %@", callUUID);
#endif
DDLogInfo(@"[RNCallKit][endCall] callUUID = %@", callUUID);
NSUUID *callUUID_ = [[NSUUID alloc] initWithUUIDString:callUUID];
@@ -92,9 +93,7 @@ RCT_EXPORT_METHOD(setMuted:(NSString *)callUUID
muted:(BOOL)muted
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {
#ifdef DEBUG
NSLog(@"[RNCallKit][setMuted] callUUID = %@", callUUID);
#endif
DDLogInfo(@"[RNCallKit][setMuted] callUUID = %@", callUUID);
NSUUID *callUUID_ = [[NSUUID alloc] initWithUUIDString:callUUID];
@@ -111,11 +110,7 @@ RCT_EXPORT_METHOD(setMuted:(NSString *)callUUID
}
RCT_EXPORT_METHOD(setProviderConfiguration:(NSDictionary *)dictionary) {
#ifdef DEBUG
NSLog(
@"[RNCallKit][setProviderConfiguration:] dictionary = %@",
dictionary);
#endif
DDLogInfo(@"[RNCallKit][setProviderConfiguration:] dictionary = %@", dictionary);
if (![JMCallKitProxy isProviderConfigured]) {
[self configureProviderFromDictionary:dictionary];
@@ -131,9 +126,7 @@ RCT_EXPORT_METHOD(startCall:(NSString *)callUUID
video:(BOOL)video
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {
#ifdef DEBUG
NSLog(@"[RNCallKit][startCall] callUUID = %@", callUUID);
#endif
DDLogInfo(@"[RNCallKit][startCall] callUUID = %@", callUUID);
NSUUID *callUUID_ = [[NSUUID alloc] initWithUUIDString:callUUID];
@@ -197,12 +190,7 @@ RCT_EXPORT_METHOD(updateCall:(NSString *)callUUID
options:(NSDictionary *)options
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {
#ifdef DEBUG
NSLog(
@"[RNCallKit][updateCall] callUUID = %@ options = %@",
callUUID,
options);
#endif
DDLogInfo(@"[RNCallKit][updateCall] callUUID = %@ options = %@", callUUID, options);
NSUUID *callUUID_ = [[NSUUID alloc] initWithUUIDString:callUUID];
@@ -225,9 +213,7 @@ RCT_EXPORT_METHOD(updateCall:(NSString *)callUUID
#pragma mark - Helper methods
- (void)configureProviderFromDictionary:(NSDictionary* )dictionary {
#ifdef DEBUG
NSLog(@"[RNCallKit][providerConfigurationFromDictionary:]");
#endif
DDLogInfo(@"[RNCallKit][providerConfigurationFromDictionary: %@]", dictionary);
if (!dictionary) {
dictionary = @{};
@@ -271,17 +257,12 @@ RCT_EXPORT_METHOD(updateCall:(NSString *)callUUID
- (void)requestTransaction:(CXTransaction *)transaction
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject {
#ifdef DEBUG
NSLog(@"[RNCallKit][requestTransaction] transaction = %@", transaction);
#endif
DDLogInfo(@"[RNCallKit][requestTransaction] transaction = %@", transaction);
[JMCallKitProxy request:transaction
completion:^(NSError * _Nullable error) {
if (error) {
NSLog(
@"[RNCallKit][requestTransaction] Error requesting transaction (%@): (%@)",
transaction.actions,
error);
DDLogError(@"[RNCallKit][requestTransaction] Error requesting transaction (%@): (%@)", transaction.actions, error);
reject(nil, @"Error processing CallKit transaction", error);
} else {
resolve(nil);
@@ -293,18 +274,14 @@ RCT_EXPORT_METHOD(updateCall:(NSString *)callUUID
// Called when the provider has been reset. We should terminate all calls.
- (void)providerDidReset {
#ifdef DEBUG
NSLog(@"[RNCallKit][CXProviderDelegate][providerDidReset:]");
#endif
DDLogInfo(@"[RNCallKit][CXProviderDelegate][providerDidReset:]");
[self sendEventWithName:RNCallKitProviderDidReset body:nil];
}
// Answering incoming call
- (void) performAnswerCallWithUUID:(NSUUID *)UUID {
#ifdef DEBUG
NSLog(@"[RNCallKit][CXProviderDelegate][provider:performAnswerCallAction:]");
#endif
DDLogInfo(@"[RNCallKit][CXProviderDelegate][provider:performAnswerCallAction:]");
[self sendEventWithName:RNCallKitPerformAnswerCallAction
body:@{ @"callUUID": UUID.UUIDString }];
@@ -312,9 +289,7 @@ RCT_EXPORT_METHOD(updateCall:(NSString *)callUUID
// Call ended, user request
- (void) performEndCallWithUUID:(NSUUID *)UUID {
#ifdef DEBUG
NSLog(@"[RNCallKit][CXProviderDelegate][provider:performEndCallAction:]");
#endif
DDLogInfo(@"[RNCallKit][CXProviderDelegate][provider:performEndCallAction:]");
[self sendEventWithName:RNCallKitPerformEndCallAction
body:@{ @"callUUID": UUID.UUIDString }];
@@ -323,9 +298,7 @@ RCT_EXPORT_METHOD(updateCall:(NSString *)callUUID
// Handle audio mute from CallKit view
- (void) performSetMutedCallWithUUID:(NSUUID *)UUID
isMuted:(BOOL)isMuted {
#ifdef DEBUG
NSLog(@"[RNCallKit][CXProviderDelegate][provider:performSetMutedCallAction:]");
#endif
DDLogInfo(@"[RNCallKit][CXProviderDelegate][provider:performSetMutedCallAction:]");
[self sendEventWithName:RNCallKitPerformSetMutedCallAction
body:@{
@@ -337,31 +310,26 @@ RCT_EXPORT_METHOD(updateCall:(NSString *)callUUID
// Starting outgoing call
- (void) performStartCallWithUUID:(NSUUID *)UUID
isVideo:(BOOL)isVideo {
#ifdef DEBUG
NSLog(@"[RNCallKit][CXProviderDelegate][provider:performStartCallAction:]");
#endif
DDLogInfo(@"[RNCallKit][CXProviderDelegate][provider:performStartCallAction:]");
[JMCallKitProxy reportOutgoingCallWith:UUID
startedConnectingAt:nil];
}
- (void) providerDidActivateAudioSessionWithSession:(AVAudioSession *)session {
#ifdef DEBUG
NSLog(@"[RNCallKit][CXProviderDelegate][provider:didActivateAudioSession:]");
#endif
DDLogInfo(@"[RNCallKit][CXProviderDelegate][provider:didActivateAudioSession:]");
[[RTCAudioSession sharedInstance] audioSessionDidActivate:session];
}
- (void) providerDidDeactivateAudioSessionWithSession:(AVAudioSession *)session {
#ifdef DEBUG
NSLog(@"[RNCallKit][CXProviderDelegate][provider:didDeactivateAudioSession:]");
#endif
DDLogInfo(@"[RNCallKit][CXProviderDelegate][provider:didDeactivateAudioSession:]");
[[RTCAudioSession sharedInstance] audioSessionDidDeactivate:session];
}
- (void) providerTimedOutPerformingActionWithAction:(CXAction *)action {
#ifdef DEBUG
NSLog(@"[RNCallKit][CXProviderDelegate][provider:timedOutPerformingAction:]");
#endif
DDLogWarn(@"[RNCallKit][CXProviderDelegate][provider:timedOutPerformingAction:]");
}

View File

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

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