Compare commits

..

608 Commits

Author SHA1 Message Date
Saúl Ibarra Corretgé
5d90107875 android: raise SDK and app versions 2019-09-26 13:25:25 +02:00
Saúl Ibarra Corretgé
2d79e08747 deps: react-native-webrtc@latest
Avoid Android crashes.
2019-09-26 13:24:23 +02:00
Saúl Ibarra Corretgé
f702f828e3 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-26 12:31:50 +02:00
Saúl Ibarra Corretgé
26ffde072e android: raise SDK version 2019-09-20 10:26:41 +02:00
Saúl Ibarra Corretgé
c8b20e037e android: make reportConnectedOutgoingCall return a Promise
The call-integration middleware relies on it returning it, as iOS does.
2019-09-20 10:26:28 +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
Saúl Ibarra Corretgé
c0a5e4f203 rn: fix crash when serializing calendar entries on iOS
Original PR: https://github.com/wmcmahan/react-native-calendar-events/pull/253
2019-09-03 12:37:31 +02:00
virtuacoplenny
55ff9dbe80 feat(api): expose method for playing touch tones (#4584) 2019-08-30 14:17:22 -07:00
Hristo Terezov
bd99108e8e feat(analytics):Add white/black list functionality 2019-08-30 10:26:22 -07:00
damencho
0c042b4078 Adds config to auto turn on captions when recording is started. 2019-08-30 15:46:29 +01:00
damencho
743bbcb846 Commit from translate.jitsi.org by user damencho.: 548 of 596 strings translated (3 fuzzy). 2019-08-30 14:47:00 +00:00
damencho
4ef2f0211a Commit from translate.jitsi.org by user damencho.: 436 of 596 strings translated (18 fuzzy). 2019-08-30 14:46:52 +00:00
damencho
86f765a01f Commit from translate.jitsi.org by user damencho.: 596 of 596 strings translated (0 fuzzy). 2019-08-30 14:46:23 +00:00
damencho
9e8b8313e0 Commit from translate.jitsi.org by user damencho.: 438 of 586 strings translated (16 fuzzy). 2019-08-30 14:46:11 +00:00
damencho
f4a8115b00 Commit from translate.jitsi.org by user damencho.: 552 of 586 strings translated (3 fuzzy). 2019-08-30 14:46:01 +00:00
Bettenbuk Zoltan
a93bd422d3 feat: new invite layout 2019-08-28 13:57:33 +02:00
Bettenbuk Zoltan
c1598b7376 feat: make display name prompt platform independent 2019-08-26 22:20:22 +02:00
Leonard Kim
bc403adb46 feat(api): allow for explicit screenshare state toggling 2019-08-26 06:53:28 -07:00
Bettenbuk Zoltan
1941275f93 feat: mobile chat emojis 2019-08-26 15:37:58 +02:00
paweldomas
6ae9bbe0c5 feat: report analytics for the network connection
Will emit new 'network.info' action with the online/offline status and
extra details for native like the network type and
'isConnectionExpensive' flag.
2019-08-23 13:36:33 -05:00
Jip-Hop
2c70388a9e Get participant specific video element
* Get participant specific video element

We now have the ability to select the video element for specific participants. I'm tweaking the jitsi-meet-electron app for my use case. I need to open Always On Top windows for specific participants, so the current _getLargeVideo() wont suffice.

I made a post about this in the Developers section on the Jitsi Community Forum, but it got blocked by Akismet.

* Add dots at end of sentence.

* Fixed ESlint errors and add additional check for iframe.

* Use _myUserID instead of string.

* Return the local video by default if participantId is undefined.

* Fixed mistake in string template.
2019-08-23 08:35:10 -07:00
Saúl Ibarra Corretgé
e0815de2ad rn,welcome: fix accessing local participant
It need not always exist, since it's created asynchronousluy on app
initiualization. Make sure we are ready for it.

I've seen backtraces because of this.
2019-08-23 17:16:22 +02:00
Saúl Ibarra Corretgé
02e058370e logging: disable caller info globally 2019-08-23 17:11:29 +02:00
Saúl Ibarra Corretgé
8a7b795d37 deps: lib-jitsi-meet@latest 2019-08-23 17:11:29 +02:00
Saúl Ibarra Corretgé
d24ca796ad deps: jitsi-meet-logger@latest 2019-08-23 17:11:29 +02:00
Leonard Kim
af2c61fd96 fix(pinning): dynamically check auto-pin setting
Any overrides set on interfaceConfig are not
applied on module load. As such, call to get
the value of the auto pin setting, providing
time for the bootstrapping to set overrides.
Otherwise iframe api users cannot override
the setting.
2019-08-23 07:36:27 -07:00
Saúl Ibarra Corretgé
5a934c071a logging: use individual, names loggers
React Native doesn't define __filename nor __dirname so do it artisanally. In
addition, this helps with centralizing the configuration passed to loggers.
2019-08-23 10:57:38 +02:00
Saúl Ibarra Corretgé
bfe4237430 deps: update jitsi-meet-logger 2019-08-23 10:57:38 +02:00
damencho
84c60a5fdf Removes i18n strings for p2p and turn. 2019-08-22 15:44:13 +01:00
Bettenbuk Zoltan
cfc7210ac8 feat: add send message button 2019-08-22 12:03:39 +02:00
damencho
57ac951192 Commit from translate.jitsi.org by user damencho.: 533 of 597 strings translated (3 fuzzy). 2019-08-21 12:26:23 +00:00
Saúl Ibarra Corretgé
36fee03d5e deps: update lib-jitsi-meet 2019-08-21 12:52:09 +02:00
paweldomas
14b747e0a4 fix(ios/xcode): increase node heap space for the bundle JS step 2019-08-21 11:12:56 +02:00
Saúl Ibarra Corretgé
c113b2e765 ios: update Podfile.lock 2019-08-21 11:12:56 +02:00
Saúl Ibarra Corretgé
560e65da37 deps: update lib-jitsi-meet 2019-08-21 11:12:56 +02:00
Saúl Ibarra Corretgé
861cf7d842 deps: react-redux@7.1.0
RN 0.60 loudly complains (loudly) about deprecated methods which react-redux was using.
2019-08-21 11:12:56 +02:00
Saúl Ibarra Corretgé
dd23ed09ad deps: react-native@0.60 2019-08-21 11:12:56 +02:00
Saúl Ibarra Corretgé
64897b9c91 rn,toolbox: simplify logic for showing Toolbox on mobile 2019-08-20 20:04:27 +02:00
Saúl Ibarra Corretgé
0dc8c687f2 rn,filmstrip: ignore the 'visible' parameter on mobile
Mobile uses a different logic for deciding whether to show the filmstrip or not:
if there are more than 1 participants or not, and there is no way to manually
toggle it.
2019-08-20 20:04:27 +02:00
paweldomas
c65d29d1a7 travis: wait 10 seconds after script to catch the error logged
Adds wait time suggested by Travis support in order to see the last
error logged.
2019-08-20 10:20:59 -05:00
Saúl Ibarra Corretgé
6aa895b679 android: attempt to fix assertion errors in ReactInstanceManager
This is the main one:
df4e67fe75/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java (L512)

Why this happens is a mystery wrapped in an enigma.
2019-08-16 17:59:47 +02:00
Saúl Ibarra Corretgé
dae451e6fa android: fix crash when parsing calendar events
Upstream PR: https://github.com/wmcmahan/react-native-calendar-events/pull/268
2019-08-16 17:46:53 +02:00
Hristo Terezov
3c1f056d2a fix(dialog): Don't steal focus 2019-08-16 07:40:47 -07:00
Leonard Kim
663e0a6693 fix(deep-linking): add back description copy 2019-08-16 16:30:16 +03:00
Saúl Ibarra Corretgé
53f98df8f3 deps: react-native@0.59.10 2019-08-16 07:26:54 +02:00
Saúl Ibarra Corretgé
6616f728f6 proximity: enable the proximity sensor when the device is set to earpiece 2019-08-14 18:57:03 +02:00
Saúl Ibarra Corretgé
1c1e8a942b audio-mode: refactor device handling
This commit refactors device selection (more heavily on iOS) to make it
consistent across platforms.

Due to its complexity I couldn't break out each step into separate commits,
apologies to the reviewer.

Changes made to device handling:

- speaker is always the default, regardless of the mode
- "Phone" shows as a selectable option, even in video call mode
- "Phone" is not displayed when wired headphones are present
- Shared device picker between iOS and Android
- Runtime device updates while the picker is open
2019-08-14 18:57:03 +02:00
George Politis
9721d99918 Updates lib-jitsi-meet. 2019-08-14 16:00:46 +02:00
Saúl Ibarra Corretgé
69c21cbb11 avatar: make code a bit clearer
Uses nullish coalescing and optional chaining.
2019-08-14 15:36:40 +02:00
Saúl Ibarra Corretgé
abefc56750 deps: add babel plugins for optional chaining and nullish coalescing
They are in Stage 3 and are already dependencies or the React Native preset.

References:
https://babeljs.io/docs/en/babel-plugin-proposal-optional-chaining
https://babeljs.io/docs/en/babel-plugin-proposal-nullish-coalescing-operator
2019-08-14 15:36:40 +02:00
damencho
a4a1685224 chore(lib-jitsi-meet): Update. 2019-08-13 10:16:20 -07:00
damencho
21fb225726 Adds a retry logic when fetching conference numbers and pin. 2019-08-13 19:00:18 +03:00
damencho
75ab890707 Uses the wrapped fetch from base/util. 2019-08-13 19:00:18 +03:00
damencho
2ded8363ad Leaves room only when it is already joined.
In case of hitting errors like max participant limit reached and when clicking hangup, the attempt to leave room second time results error and reload screen.
2019-08-13 16:04:43 +03:00
Leonard Kim
c0a8a386a5 fix(pinning): debounce autopin subscriber
The store's remote tracks get cleared
and re-added when switching in and out
of p2p, which can cause pinning thrashing.
Avoid that with a debounce.
2019-08-12 17:31:53 -07:00
Leonard Kim
7af081ea99 fix(avatars): re-render avatar on any resize 2019-08-12 12:41:57 -07:00
Дамян Минков
8800cb4580 Adds live streaming sound notification. (#4532)
* Adds live streaming sound notification.

* Adds ios resources for the new files.
2019-08-12 18:34:38 +03:00
Karthik Muralidharan
b658f20a30 feat(API): add dominant speaker changed event
Fixes: https://github.com/jitsi/jitsi-meet/issues/4049
2019-08-09 10:09:33 +02:00
Hristo Terezov
c3e52f32f9 feat: Add logging for thumbnail display mode and tile view. 2019-08-09 01:08:19 -07:00
George Politis
ab73d808fe Updates lib-jitsi-meet. 2019-08-08 18:05:50 +02:00
dependabot[bot]
e110460793 Bump jquery from 3.3.1 to 3.4.0
Bumps [jquery](https://github.com/jquery/jquery) from 3.3.1 to 3.4.0.
- [Release notes](https://github.com/jquery/jquery/releases)
- [Commits](https://github.com/jquery/jquery/compare/3.3.1...3.4.0)

Signed-off-by: dependabot[bot] <support@github.com>
2019-08-08 14:37:18 +02:00
dependabot[bot]
c0ee451ca1 Bump lodash from 4.17.11 to 4.17.13
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.13.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.13)

Signed-off-by: dependabot[bot] <support@github.com>
2019-08-08 10:34:51 +02:00
Saúl Ibarra Corretgé
67dca97d1d rn,participants: don't render thumbnnail for screen-shares 2019-08-07 20:16:13 +02:00
Saúl Ibarra Corretgé
fd0ca76255 web,avatar: fix setting avatar size
Use the width of its container as the size, so the font icons can be rendered at
a good size.
2019-08-07 20:16:13 +02:00
Saúl Ibarra Corretgé
149e53af76 avatar: render a special avatar if the user is sharing their screen 2019-08-07 20:16:13 +02:00
Saúl Ibarra Corretgé
f3e7952e51 audio-only: implement initial "low bandwidth mode"
It's an evolution of audio-only mode, where we also allow for receiving a remote
screen-share.

Diving deeper: this basically sets last N to 1 or 0 depending on the
availability of a screen-share.
2019-08-07 20:16:13 +02:00
Saúl Ibarra Corretgé
0f77cf9e0c android: use adaptive icons 2019-08-07 14:40:20 +02:00
damencho
66eb09fb63 Revert raisedHand thumb tooltip i18n string. 2019-08-07 14:59:24 +03:00
Hristo Terezov
b7f2c7d487 chore(lib-jitsi-meet): Update. 2019-08-06 01:59:01 -07:00
Bettenbuk Zoltan
bed3f62536 feat: make links in chat clickable 2019-08-06 08:48:37 +02:00
Leonard Kim
e8eb7e1e1f fix(suboptimal-browser): remove inserting of app name in notification
This prevents inserting any user overridden APP_NAME
values into html. A new translation key is being used
to immediately stop non-english languages from using the
problematic string.

Also tweaked the copy to remove the "eer" and fix
some grammar.
2019-08-05 06:47:44 -07:00
Leonard Kim
1409d6fb5e fix(deep-linking): do not accept native app name as raw html
There is no need to display the native app name as
raw html.
2019-08-04 06:45:00 -07:00
Bettenbuk Zoltan
a2cbd9229a fix: render notification description on mobile 2019-08-02 21:14:19 +02:00
Saúl Ibarra Corretgé
bf50a110c7 lastn: simplify computing the effective last N value 2019-08-02 15:54:47 +02:00
Saúl Ibarra Corretgé
467c9d36cf audio-only,lastn: move audio-only and last N handling to standalone features
This refactors all handling of audio-only and last N to 2 features in preparation
for "low bandwidth mode".

The main motivation to do this is that lastN is a "global" setting so it helps
to have all processing for it in a single place.
2019-08-02 15:54:47 +02:00
damencho
6ddd17c769 Removes resolveAppName postprocess we do not need.
i18next.options are initialized before interfaceConfig overwrites are processed which leads to wrong translations.
2019-08-01 12:47:58 +01:00
virtuacoplenny
732f2c1963 ref(feedback): emit api feedback submitted on completion (#4499)
* ref(feedback): emit api feedback submitted on completion

Compared to firing the event on submission because
the submission ajax will not be completed at that
time..

* squash: update package.json
2019-07-31 10:59:22 -07:00
Bettenbuk Zoltan
e7144eb674 Get chat message display name from backend 2019-07-31 10:48:22 +02:00
Saúl Ibarra Corretgé
b5489b7c81 rn,filmstrip: don't unpin participant when hiding filmstrip
The filmstrip is currently only hidden when PiP mode is entered. There is no
real reason not to leave the large view as it was.
2019-07-30 18:51:40 +02:00
Saúl Ibarra Corretgé
4d5332cadf rn,conference: log pin participant analytics events also on mobile 2019-07-30 17:11:43 +02:00
Saúl Ibarra Corretgé
5261f61110 conference: don't pin participants on the JVB
When a participant is pinned in the UI we then proceed to mark it as selected on
the JVB. This will make the participant part of the last N set and will receive
the highest (or configured highest) video quality.

Pinning a participant at the JVB level just makes sure it will be part of the
last N set.

Since only one participant can be pinned in the UI, there is no point in pinning
it at the JVB level, since selecting it already achieved the same result.
2019-07-30 17:11:43 +02:00
paweldomas
8c7d6da5d5 deps: update LJM to get analytics fixes
Bumps LJM to 3c8058743177b6b6963d3bc3df14f4ea650ef310.
2019-07-30 15:45:43 +02:00
Leonard Kim
6d91728a74 fix(proxy): stop screenshare when the connection stops 2019-07-30 06:40:57 -07:00
Hristo Terezov
9b32fc95eb chore(package): update lib-jitsi-meet version. 2019-07-30 01:55:02 -07:00
Leonard Kim
6bc1d87753 feat(shortcuts): add shortcut for opening video quality modal 2019-07-29 11:40:07 -07:00
damencho
a5fc62b920 Updates correct loading and fix checking is dominant speaker. 2019-07-26 11:18:55 +01:00
Saúl Ibarra Corretgé
49f6010905 pagedlist: fix refresh on wrapped components 2019-07-26 10:38:54 +02:00
paweldomas
1c27f567ee feat: send analytics event when conference is rejoined 2019-07-26 08:25:53 +02:00
paweldomas
7684b2bf98 ref: move getCurrentConferenceUrl to base/connection
Moves getCurrentConferenceUrl method to base/connection to allow reuse.
The new location is not ideal, but looks the best based on the imports
required (trying to avoid circular dependencies).
2019-07-26 08:25:53 +02:00
damencho
8886bcdb73 Fixes missing strings. 2019-07-26 07:07:31 +01:00
Saúl Ibarra Corretgé
437bdb92be deps: update react-native-webrtc and lib-jitsi-meet
Support for the MediaStream constructor has been added to react-native-webrtc.
2019-07-25 23:52:54 +02:00
Saúl Ibarra Corretgé
6943659dc9 rn: enable auto-pinning on screenshare on mobile 2019-07-25 14:27:04 +02:00
Saúl Ibarra Corretgé
35f934e197 config: remove old backwards compatibility shim
It was added for
3ea2f00578
over 2 years ago. That's long enough!
2019-07-25 11:45:16 +02:00
damencho
aca0469bd0 Fixes mobile wifi stats timestamp value type. 2019-07-25 10:20:48 +01:00
Дамян Минков
11f2e7291e Talk while muted sound notification (#4473)
* Moves talk while muted as a new feature.

* Adds sound notification for talk while muted.

* Reorder imports and changes the dispatch of the notification.

* Introduces sounds.js for talk while muted.
2019-07-23 21:56:05 +01:00
Bettenbuk Zoltan
7a985dd843 fix: disable reduced UI on welcome page 2019-07-23 17:52:03 +02:00
damencho
e09ea36055 Maps available locales for countries to the doubled languages.
This maps the tow letter languages as enGB to the country file for en.
Copies countries-en.json as countries-enGB.json.
2019-07-23 10:10:03 +01:00
damencho
ad3a087091 Commit from translate.jitsi.org by user damencho.: 532 of 586 strings translated (9 fuzzy). 2019-07-22 23:06:01 +00:00
damencho
d379b4d53b Commit from translate.jitsi.org by user damencho.: 546 of 586 strings translated (0 fuzzy). 2019-07-22 23:05:43 +00:00
damencho
7a99d57274 Commit from translate.jitsi.org by user damencho.: 478 of 586 strings translated (6 fuzzy). 2019-07-22 23:00:06 +00:00
damencho
85bc0ed5fc Commit from translate.jitsi.org by user damencho.: 535 of 586 strings translated (6 fuzzy). 2019-07-22 22:57:36 +00:00
damencho
f4dda6e7ce Commit from translate.jitsi.org by user damencho.: 434 of 586 strings translated (15 fuzzy). 2019-07-22 22:54:29 +00:00
damencho
5c8dfabf7c Commit from translate.jitsi.org by user damencho.: 538 of 586 strings translated (0 fuzzy). 2019-07-22 22:50:47 +00:00
damencho
20d03f3228 Commit from translate.jitsi.org by user damencho.: 343 of 586 strings translated (18 fuzzy). 2019-07-22 22:46:35 +00:00
damencho
268137bb97 Commit from translate.jitsi.org by user damencho.: 342 of 586 strings translated (19 fuzzy). 2019-07-22 22:44:50 +00:00
damencho
f87463780c Commit from translate.jitsi.org by user damencho.: 506 of 586 strings translated (1 fuzzy). 2019-07-22 22:42:16 +00:00
damencho
6b2ced63c7 Commit from translate.jitsi.org by user damencho.: 506 of 586 strings translated (0 fuzzy). 2019-07-22 22:40:00 +00:00
damencho
d6fbe55360 Commit from translate.jitsi.org by user damencho.: 411 of 586 strings translated (9 fuzzy). 2019-07-22 22:38:36 +00:00
damencho
0feeb94fc7 Commit from translate.jitsi.org by user damencho.: 491 of 586 strings translated (5 fuzzy). 2019-07-22 22:36:34 +00:00
damencho
c9c509ec51 Commit from translate.jitsi.org by user damencho.: 539 of 586 strings translated (4 fuzzy). 2019-07-22 22:34:45 +00:00
damencho
f7ff457a3b Commit from translate.jitsi.org by user damencho.: 536 of 586 strings translated (3 fuzzy). 2019-07-22 22:32:29 +00:00
damencho
72127aaa0b Commit from translate.jitsi.org by user damencho.: 505 of 586 strings translated (4 fuzzy). 2019-07-22 22:30:42 +00:00
damencho
b8854a3b45 Commit from translate.jitsi.org by user damencho.: 538 of 586 strings translated (4 fuzzy). 2019-07-22 22:27:01 +00:00
damencho
e6e7001857 Commit from translate.jitsi.org by user damencho.: 535 of 586 strings translated (7 fuzzy). 2019-07-22 22:19:53 +00:00
damencho
6d4601fe66 Updates used languages and fixes loading them. 2019-07-22 17:48:44 +01:00
damencho
8ecb01ec21 Commit from translate.jitsi.org by user damencho.: 545 of 586 strings translated (1 fuzzy). 2019-07-22 14:48:34 +00:00
damencho
14ccb41015 Commit from translate.jitsi.org by user damencho.: 545 of 586 strings translated (1 fuzzy). 2019-07-22 14:29:08 +00:00
damencho
348cde54e7 Commit from translate.jitsi.org by user damencho.: 545 of 586 strings translated (1 fuzzy). 2019-07-22 14:24:36 +00:00
damencho
430bd3f141 Commit from translate.jitsi.org by user damencho.: 535 of 586 strings translated (7 fuzzy). 2019-07-22 13:03:23 +00:00
damencho
b36f419e86 Commit from translate.jitsi.org by user damencho.: 122 of 586 strings translated (28 fuzzy). 2019-07-22 13:03:11 +00:00
damencho
ed1d03db71 Commit from translate.jitsi.org by user damencho.: 524 of 586 strings translated (5 fuzzy). 2019-07-22 13:02:58 +00:00
damencho
5d837571c0 Commit from translate.jitsi.org by user damencho.: 538 of 586 strings translated (5 fuzzy). 2019-07-22 13:02:46 +00:00
damencho
f23532d7f4 Commit from translate.jitsi.org by user damencho.: 78 of 586 strings translated (12 fuzzy). 2019-07-22 13:02:33 +00:00
damencho
0280294a8f Commit from translate.jitsi.org by user damencho.: 80 of 586 strings translated (12 fuzzy). 2019-07-22 13:02:19 +00:00
damencho
fdd1418236 Commit from translate.jitsi.org by user damencho.: 433 of 586 strings translated (16 fuzzy). 2019-07-22 13:02:05 +00:00
damencho
bae47434b1 Commit from translate.jitsi.org by user damencho.: 531 of 586 strings translated (10 fuzzy). 2019-07-22 13:01:52 +00:00
damencho
3c98cfc136 Commit from translate.jitsi.org by user damencho.: 216 of 586 strings translated (36 fuzzy). 2019-07-22 13:01:25 +00:00
damencho
17e5bc7b73 Commit from translate.jitsi.org by user damencho.: 89 of 586 strings translated (5 fuzzy). 2019-07-22 13:01:11 +00:00
damencho
6092655099 Commit from translate.jitsi.org by user damencho.: 503 of 586 strings translated (6 fuzzy). 2019-07-22 13:00:59 +00:00
damencho
721cca669f Commit from translate.jitsi.org by user damencho.: 0 of 586 strings translated (0 fuzzy). 2019-07-22 13:00:49 +00:00
damencho
c62ff0939d Commit from translate.jitsi.org by user damencho.: 505 of 586 strings translated (1 fuzzy). 2019-07-22 12:58:57 +00:00
damencho
ecf050c2d9 Commit from translate.jitsi.org by user damencho.: 344 of 586 strings translated (15 fuzzy). 2019-07-22 12:58:46 +00:00
damencho
069137b02a Commit from translate.jitsi.org by user damencho.: 25 of 586 strings translated (0 fuzzy). 2019-07-22 12:58:34 +00:00
damencho
f053cad66c Commit from translate.jitsi.org by user damencho.: 123 of 586 strings translated (20 fuzzy). 2019-07-22 12:58:22 +00:00
damencho
4be3042cb0 Commit from translate.jitsi.org by user damencho.: 445 of 586 strings translated (25 fuzzy). 2019-07-22 12:58:09 +00:00
damencho
593235d683 Commit from translate.jitsi.org by user damencho.: 490 of 586 strings translated (6 fuzzy). 2019-07-22 12:57:56 +00:00
damencho
7bd8ddbba2 Commit from translate.jitsi.org by user damencho.: 39 of 586 strings translated (2 fuzzy). 2019-07-22 12:57:44 +00:00
damencho
14232b1d93 Commit from translate.jitsi.org by user damencho.: 515 of 586 strings translated (17 fuzzy). 2019-07-22 12:57:25 +00:00
damencho
ff4887a3c8 Commit from translate.jitsi.org by user damencho.: 535 of 586 strings translated (4 fuzzy). 2019-07-22 12:57:12 +00:00
damencho
0289aacd4f Commit from translate.jitsi.org by user damencho.: 505 of 586 strings translated (2 fuzzy). 2019-07-22 12:57:01 +00:00
damencho
99c13eaec0 Commit from translate.jitsi.org by user damencho.: 254 of 586 strings translated (22 fuzzy). 2019-07-22 12:56:48 +00:00
damencho
1a713dfa27 Commit from translate.jitsi.org by user damencho.: 536 of 586 strings translated (4 fuzzy). 2019-07-22 12:56:36 +00:00
damencho
7e84b51ee0 Commit from translate.jitsi.org by user damencho.: 534 of 586 strings translated (4 fuzzy). 2019-07-22 12:56:22 +00:00
damencho
86fa442d0e Commit from translate.jitsi.org by user damencho.: 148 of 586 strings translated (18 fuzzy). 2019-07-22 12:55:58 +00:00
damencho
93b88f1a16 Commit from translate.jitsi.org by user damencho.: 342 of 586 strings translated (19 fuzzy). 2019-07-22 12:55:46 +00:00
damencho
2041d4fffb Commit from translate.jitsi.org by user damencho.: 534 of 586 strings translated (0 fuzzy). 2019-07-22 12:54:35 +00:00
jitsi-pootle
83c3e7c725 New files added from translate.jitsi.org based on templates 2019-07-22 12:53:40 +00:00
damencho
a34331891a Commit from translate.jitsi.org by user damencho.: 477 of 586 strings translated (7 fuzzy). 2019-07-22 12:46:37 +00:00
damencho
56dd83740c Commit from translate.jitsi.org by user damencho.: 533 of 586 strings translated (8 fuzzy). 2019-07-22 12:46:23 +00:00
damencho
debe50c3f4 Commit from translate.jitsi.org by user damencho.: 227 of 586 strings translated (22 fuzzy). 2019-07-22 12:46:08 +00:00
damencho
d9985c786c Commit from translate.jitsi.org by user damencho.: 5 of 586 strings translated (0 fuzzy). 2019-07-22 12:42:06 +00:00
damencho
ed910947d4 Commit from translate.jitsi.org by user damencho.: 268 of 586 strings translated (27 fuzzy). 2019-07-22 12:41:32 +00:00
damencho
c4c5eace25 Commit from translate.jitsi.org by user damencho.: 206 of 586 strings translated (29 fuzzy). 2019-07-22 12:40:07 +00:00
damencho
c6bf646fe8 Commit from translate.jitsi.org by user damencho.: 410 of 586 strings translated (10 fuzzy). 2019-07-22 12:37:36 +00:00
jitsi-pootle
ab2bb7686e New files added from translate.jitsi.org based on templates 2019-07-22 10:14:05 +00:00
jitsi-pootle
12b53c38b9 New files added from translate.jitsi.org based on templates 2019-07-22 10:14:05 +00:00
jitsi-pootle
ca31c8b199 New files added from translate.jitsi.org based on templates 2019-07-22 10:14:05 +00:00
jitsi-pootle
1b331ce090 New files added from translate.jitsi.org based on templates 2019-07-22 10:14:05 +00:00
jitsi-pootle
edd55e7798 New files added from translate.jitsi.org based on templates 2019-07-22 10:14:05 +00:00
Дамян Минков
9f4da84701 I18next update (#4456)
* Removes unused translations.

* Fixes using translated strings.

* Moves using latest i18next versions and stop using compatibility modes.

* Sorts i18next options.

* Fixes defaultNS used by i18next.

This is used when translating html tags with data-i18n keys as attributes, used by jQuery-Impromptu.
2019-07-22 11:10:25 +01:00
Leonard Kim
0097360396 feat(deep-linking): allow disabling through override 2019-07-19 14:48:46 -07:00
Hristo Terezov
b5cef05941 fix(AOT): imports. 2019-07-19 07:17:15 -07:00
George Politis
ddab9224b2 Merge pull request #4460 from jitsi/analytics-event-for-connectivity-issues
deps: update lib-jitsi-meet
2019-07-18 18:26:28 +02:00
George Politis
a5693c6e96 updates package-lock.json 2019-07-18 17:25:46 +02:00
George Politis
8dd345b192 deps: update lib-jitsi-meet
With the update we get a new analytics event that sends connectivity
issues events to the analytics backend.
2019-07-18 17:10:29 +02:00
Leonard Kim
130ab886ee fix(chat): show toolbar on open 2019-07-18 06:08:27 -07:00
Leonard Kim
c0e9f2b95a fix(chat): workaround for chat scroll causing layout misalignment 2019-07-18 06:08:27 -07:00
Leonard Kim
011972872e fix(blur): add beta label to toolbar button 2019-07-16 10:35:31 -07:00
Saúl Ibarra Corretgé
ef5720a3f0 deps: update react-native-webrtc
Fixes: https://github.com/jitsi/jitsi-meet/issues/4436
2019-07-16 17:55:37 +01:00
Bettenbuk Zoltan
ec30af2844 feat: always show labels 2019-07-16 17:32:58 +02:00
Bettenbuk Zoltan
e08aeca28c feat: use css to place the toolbox buttons 2019-07-16 17:01:24 +02:00
Bettenbuk Zoltan
ad7892ebce aot: jigasi participant icon 2019-07-16 13:04:17 +02:00
Saúl Ibarra Corretgé
cbc7e1b6be android: fix crash if UserInfo is not set
Fixes: https://github.com/jitsi/jitsi-meet-sdk-samples/issues/11
2019-07-16 07:29:07 +01:00
Saúl Ibarra Corretgé
da7d959b9a android: raise SDK version 2019-07-16 07:29:07 +01:00
virtuacoplenny
ada57ebcd0 ref(user-interaction): do not store listener, move browser check to lib (#4441)
* ref(user-interaction): remove storing of listener

* ref(user-interaction): move browser requirement check to lib-jitsi-meet

* ref(user-interaction): no inner function for listener, use module scope
2019-07-13 06:59:58 -07:00
Bettenbuk Zoltan
1993ad10eb feat: apply color brand guidelines 2019-07-12 20:48:49 +02:00
Bettenbuk Zoltan
d305caf910 feat: borderless toolbox icons 2019-07-12 20:48:49 +02:00
Bettenbuk Zoltan
a25a504a59 feat: add bottom gradient 2019-07-12 20:48:49 +02:00
damencho
250c61279b Updates react-native callstats dependency, to use siteID on mobile. 2019-07-12 18:24:44 +01:00
Saúl Ibarra Corretgé
1e18af2d1a rn: fix not showing a prompt when permissions have been denied
This only shows up if we cannot prompt again, like when turning permissions off
in the Settings app in iOS.
2019-07-12 17:50:54 +02:00
Дамян Минков
eb1fd4fd88 Merge pull request #4438 from jitsi/cs-siteid
Passes confID when initializing JitsiConference.
2019-07-12 14:25:35 +01:00
Matthias Herzog
e0c8b6b3c0 fix welcome page title fixes #4273 2019-07-12 14:25:26 +01:00
Дамян Минков
9071cd4813 Listens for suspend events from jitsi-power-monitor on postis channel. (#4428)
* Listens for suspend events from jitsi-power-monitor on postis channel.

* Removes duplicated type and actions.

* Moves suspendDetected state from overlay to power-monitor feature.
2019-07-12 14:08:34 +01:00
Saúl Ibarra Corretgé
9bf650c700 android: keep okio classes
Fixes running profile builds.
2019-07-12 14:22:36 +02:00
Saúl Ibarra Corretgé
49e3b03885 android: custom initialization of the WebRTC module
Set our own audio device manager so we can tweak it if need be (enabling /
disabling the HW AEC on specific devices).

Switch to using the software video encoder / decoder. This may feel like a
downgrade, but it has advantages:

- simulcast is now working (on par with iOS)
- certain devices have broken VP8 HW encoders (I'm looking at you Samsung Galaxy
S7) so this fixes that
2019-07-12 14:22:36 +02:00
Saúl Ibarra Corretgé
31e996ac3f android: always run adb reverse when starting the packager
It tends to close, so always open the reverse tunnel.
2019-07-12 14:22:36 +02:00
Saúl Ibarra Corretgé
d1c447e97b deps: update react-native-webrtc
- Fix crash in PeerConnection.close (Android)
- Add ability to customize PeerConnectionFactory (Android)
2019-07-12 14:22:36 +02:00
damencho
8a34c0a80f Updates lib-jitsi-meet. 2019-07-12 11:17:53 +01:00
virtuacoplenny
2f626ea474 ref(api): move participant join and left to middleware (#4365) 2019-07-11 12:44:27 -07:00
Bettenbuk Zoltan
0a76eebca7 feat: central back button registry 2019-07-11 16:14:08 +02:00
damencho
0e9e695251 Passes confID when initializing JitsiConference.
The confID is domain.com/RoomName or domain.com/tenant/RoomName, adds the tenant if any and also keeps the room name case.
2019-07-11 14:58:14 +01:00
Leonard Kim
b86df7a8e3 fix(remote-control): do not assume failed query is missing support
Multiple requests for checkUserRemoteControlSupport can be in
flight simultaneously. Order of promise resolution is not
guaranteed. It is possible for Request A and Request B to be
in flight and then Request B's promise chain resolves first.
Request A could have encountered errors and then resolve. Then
what could happen is checkUserRemoteControlSupport returns true
for remote control support due to Request B and the UI updates.
But then checkUserRemoteControlSupport returns false for
remote control support due to Request A's error and the UI
updates to hide remote control.
2019-07-11 07:25:08 +01:00
Bettenbuk Zoltan
5b25e02e26 feat: use dialog instead of alert when inviting 2019-07-10 20:50:14 +02:00
Bettenbuk Zoltan
0e6f14bb7c fix: avoid false triggering CDU in SlidingView 2019-07-10 20:49:50 +02:00
Leonard Kim
57b9954d9c fix(api): support params with value of undefined 2019-07-10 11:09:11 -07:00
virtuacoplenny
249dd7b8b8 fix(invite): decode the meeting name (#4411)
* fix(invite): decode the meeting name

* squash: try to make mobile join same encoded meeting name as web

* Decodes and generated texts for share and copy meeting info.

Decodes in all cases except when it contains a space, as it will generate wrong links when pasted/shared in external applications.
2019-07-10 10:27:11 -07:00
Bettenbuk Zoltan
b31d7b4451 ref: remove createStyleSheet from dialog styles 2019-07-10 16:42:56 +02:00
Bettenbuk Zoltan
8dea3389ee fix: avoid clicking behind dialogs 2019-07-10 16:42:56 +02:00
virtuacoplenny
e7f9e8e7f7 fix(conference): require user interaction to unmute in iframe (#4429)
* fix(conference): require user interaction to unmute in iframe

* squash: explicitly whitelist react native
2019-07-10 12:02:27 +01:00
Bettenbuk Zoltan
a53a86ee7a feat: add room lock pwd error message 2019-07-10 11:01:49 +02:00
Saúl Ibarra Corretgé
598b6f0598 deps: update react-native-webrtc
WebRTC is now at M75
2019-07-09 17:22:32 +02:00
Saúl Ibarra Corretgé
b245945c4a android: be explicit about starting a foreground service
After calling startService we are supposed to have a bit of time before turning
the service into a foreground service, but certain devices seem to be more
spartan and we've seen the following failure:

Caused by java.lang.IllegalStateException: Not allowed to start service Intent { act=JitsiMeetOngoingConferenceService:START cmp=org.jitsi.meet/.sdk.JitsiMeetOngoingConferenceService }: app is in background uid UidRecord{f6778d5 u0a220 CAC  bg:+1m1s417ms idle change:idle procs:1 proclist:15604, seq(0,0,0)}
       at android.app.ContextImpl.startServiceCommon + 1600(ContextImpl.java:1600)
       at android.app.ContextImpl.startService + 1546(ContextImpl.java:1546)
       at android.content.ContextWrapper.startService + 669(ContextWrapper.java:669)
       at org.jitsi.meet.sdk.JitsiMeetOngoingConferenceService.launch + 50(JitsiMeetOngoingConferenceService.java:50)

Be expliocit and call startForegroundService, on supported platforms.
2019-07-09 16:14:39 +02:00
Bettenbuk Zoltan
301a8e319a fix: reduce avatar font size 2019-07-09 15:45:38 +02:00
Saúl Ibarra Corretgé
820abfd059 ios: sync Podfile.lock 2019-07-09 12:58:07 +02:00
Hristo Terezov
1d42420a36 fix(font): Bring back the missing icons. 2019-07-08 20:03:04 +01:00
Hristo Terezov
1b4bdb5142 fix(blur): on FF 2019-07-08 20:03:04 +01:00
Hristo Terezov
f030a3f1fb fix(blur): when switching video tracks. 2019-07-08 20:03:04 +01:00
Hristo Terezov
8f79779ca7 fix(blur): Disable for SS 2019-07-08 20:03:04 +01:00
Saúl Ibarra Corretgé
c5111bb359 rn: update default color scheme 2019-07-08 20:27:44 +02:00
Bettenbuk Zoltan
42814eac7d feat: add icon based avatar and icon for pstn 2019-07-08 16:53:30 +02:00
Bettenbuk Zoltan
74d0013acc feat: use participant id for avatar color 2019-07-08 16:53:30 +02:00
Bettenbuk Zoltan
88e4850c4d fix: remove locally generated avatar ID 2019-07-08 16:53:30 +02:00
Bettenbuk Zoltan
87f9b1cf92 ref: remove unnecesary functions 2019-07-08 16:53:30 +02:00
Bettenbuk Zoltan
fe1187d7b7 ref: remove unused libs 2019-07-08 16:53:30 +02:00
Bettenbuk Zoltan
a35b36d6df feat: dynamic avatar font size 2019-07-08 16:53:30 +02:00
Bettenbuk Zoltan
a04982fd96 fix: AlwaysOnTop avatar 2019-07-08 16:53:30 +02:00
Bettenbuk Zoltan
658679f89e fix: undefined participant in avatar call 2019-07-08 16:53:30 +02:00
Bettenbuk Zoltan
f90fc665f8 ui: bigger padding to default avatar 2019-07-08 16:53:30 +02:00
Bettenbuk Zoltan
0c8130af41 fix: default avatar relative url 2019-07-08 16:53:30 +02:00
paweldomas
e4c5968459 fix: bring back the add meeting URL button
Brings back the button for generating meeting URLs for calendar events.
2019-07-08 09:26:33 -05:00
damencho
a148cd41a4 Fixes loading wifi-stats when used from jitsi-meet electron utils. 2019-07-08 14:30:20 +01:00
Saúl Ibarra Corretgé
f8a049759d android: fix crash if notification is null
I cannot see a path leading to it being null, but Crashlytics demonstrated it's
possible (so far in a small subset of old devices). Be defensive then.
2019-07-05 10:11:00 +02:00
Hristo Terezov
4b4225e14f chore(lib-jitsi-meet): Update. 2019-07-04 06:26:32 -07:00
Hristo Terezov
3b0c5d0b6a fix(blur): many small issues. 2019-07-04 06:26:32 -07:00
Cristian Florin Ghita
3b750ddd5a Add video background blur 2019-07-04 06:26:32 -07:00
Saúl Ibarra Corretgé
6383d000a9 rn: raise version to 19.3 2019-07-03 21:09:15 +02:00
Bettenbuk Zoltan
a48d67bdc7 fix: inconsistent state when quickly closing a sliding view 2019-07-03 13:43:56 +02:00
Saúl Ibarra Corretgé
2f92e72858 android: raise SDK version 2019-07-03 13:28:31 +02:00
Saúl Ibarra Corretgé
d2c85ada1b android: fix deadlock in uncaught exception handler
The app is about to crash at that stage so it was a moot point to try to leave
the conference anyway.

Stopping ConnectionServers is still a good idea though, since a crash may leave
the device in a bad state otherwise.
2019-07-03 13:28:18 +02:00
Saúl Ibarra Corretgé
55b95c52d6 android: fix synchronized access to listeners set
Fixes this issue:

~~~
    java.util.ConcurrentModificationException
        at java.util.HashMap$HashIterator.nextNode(HashMap.java:1441)
        at java.util.HashMap$KeyIterator.next(HashMap.java:1465)
        at org.jitsi.meet.sdk.OngoingConferenceTracker.updateListeners(OngoingConferenceTracker.java:89)
        at org.jitsi.meet.sdk.OngoingConferenceTracker.onExternalAPIEvent(OngoingConferenceTracker.java:74)
        at org.jitsi.meet.sdk.ExternalAPIModule.sendEvent(ExternalAPIModule.java:71)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:372)
        at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:158)
        at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:29)
        at android.os.Looper.loop(Looper.java:214)
        at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:232)
        at java.lang.Thread.run(Thread.java:764)
~~~
2019-07-03 13:28:18 +02:00
Chris Hansen
52362c4675 Fix spelling mistake on pragma mark
It causes a compiler error in Xcode 11 because it doesn't know how to parse it.
2019-07-02 14:11:01 -07:00
netaskd
8da0552541 microsoftCalendar: add showing calendar events in local timezone. 2019-07-02 21:20:00 +01:00
Hristo Terezov
7ce0def995 fix(mobile): After PR #4396 2019-07-02 10:36:37 -07:00
Hristo Terezov
48285e8a2d fix(conference): Don't use this._room.
this._room should be used only by jitsi-meet-torture and for test purposes. Also this._room is assigned later than room. This may cause some issues, for example conference.getMyUserId() may return undefined while the user id is already available beacuse this._room hasn't been assigned yet.
2019-07-02 07:38:57 -07:00
Hristo Terezov
21dcc41d31 ref(large-video): switch LargeVideo logic to react 2019-07-02 07:38:57 -07:00
Дамян Минков
625d268373 Room lock update (#4394)
* Adds a notification when remote lock happens.

* Updates translations.

Removes unused strings and extracts room password to separate translation, to be able to change it when deployment uses only digits.

* Formats the conference pin when showing it.

* Removes member from translation in favour of participant.

* Updates formatting of the pin.

* Adds a notification when password is remotely removed.
2019-07-02 14:14:58 +01:00
Дамян Минков
681782ed20 Adds back talk while muted notification. (#4392)
* Adds back talk while muted notification.

* Adds unmute button to the notification.
2019-07-02 12:59:25 +01:00
Saúl Ibarra Corretgé
1baa85b649 rn: hide invite button if the functionality is not available 2019-07-02 12:30:50 +02:00
Bettenbuk Zoltan
72137a2811 feat: initial based avatars 2019-07-01 23:59:16 +02:00
Leonard Kim
0734ce7ae3 feat(api): add notifications for kicked participants 2019-07-01 12:53:25 -07:00
Дамян Минков
2dc06c28e3 Adds option to be able to cancel locked rooms and leave. (#4391)
* Adds option to be able to cancel locked rooms and leave.

* Removes not needed operations when canceling password prompt.
2019-07-01 13:02:25 +01:00
paweldomas
5848669552 feat(analytics): time since last success in connection dropped
Update LJM to 9bcc2a26cc94683b8ed302418695a331b450df97 in order to bring
in the analytics update which will add a property indicating how much
time has passed since the last successful XMPP request came through.
2019-06-28 13:30:50 -05:00
Leonard Kim
c0376d238a ref(notifications): do not notify of local participant left
Join notifications are already supressed for the local
participant, so hide the left notification. For now
the notification is not being shown on mobile to keep
the same existing behavior and because a copy change
will be needed, but will be added once batching is
implemented.
2019-06-28 09:18:18 -07:00
Leonard Kim
979b773c3c ref(notifications): move join notification firing to notifications feature 2019-06-27 17:29:02 -07:00
Leonard Kim
3195a449ca ref(conference): web and native exercise same redux flow for kicked out 2019-06-27 09:34:05 -07:00
Bettenbuk Zoltan
d7483f07e3 feat: add possibility to clear invite search field 2019-06-27 18:17:37 +02:00
Дамян Минков
9c1b802997 Device selection now always shows the device that it managed to open. (#4384)
* Device selection now always shows the device that managed to open.

* Simplifies implementation, skips using state.
2019-06-27 17:04:47 +01:00
damencho
bb3a10b0fc Safe guard for removed parent node of the iframe. 2019-06-27 14:23:59 +01:00
paweldomas
97e8b31cee fix: update LJM to fix reload on hangup
Updates LJM to c0af82a215d0893f1999df299cfdfcbc9ce9e72a
2019-06-26 22:11:12 +02:00
Saúl Ibarra Corretgé
55218de779 rn: add a reduced UI mode for the welcome page
The only way to render the welcome page in reduced UI mode currently is to
hangup a call from the Android ongoing notification while in PiP mode.
2019-06-26 21:45:27 +02:00
Saúl Ibarra Corretgé
714e0e045d android: add notification while there is an ongoing meeting
The notification is posted by a foreground service, which also has the nice
side-effect of keeping the app alive for a long time.
2019-06-26 21:45:27 +02:00
Saúl Ibarra Corretgé
0bc369afb4 android: add ability to get the current Activity running RN
This helper method gets the current Activity attached to React Native (via the
ReactContext). This is useful for modules which need access to it, without being
actual React Native modules.
2019-06-26 21:45:27 +02:00
Saúl Ibarra Corretgé
f71ec55170 android: add ability to keep track of the current ongoing conference 2019-06-26 21:45:27 +02:00
yanas
760885437a Merge pull request #4369 from jitsi/quality-text-change
Changes call quality strings to video quality.
2019-06-26 17:24:34 +01:00
damencho
f77976b742 Notify for detecting suspend. 2019-06-26 17:10:34 +01:00
Saúl Ibarra Corretgé
9e95e7cd97 rn: bump SDK version to 2.2.0 2019-06-26 12:04:17 +02:00
Leonard Kim
9d94257e79 ref(api): move conference join notification to middleware 2019-06-26 10:47:18 +02:00
Leonard Kim
13cfd61c83 fix(index): set reload link as attribute, not raw html 2019-06-25 12:48:31 -07:00
Leonard Kim
fa818bc386 feat(screenshare): allow auto-pin remote only 2019-06-25 11:21:23 +01:00
Saúl Ibarra Corretgé
a73a642c64 rn: fix CallKit failure screen flash when kicked
Pretend we have left instead of triggering a call failure. The user was already
told in the dialog.
2019-06-25 10:25:33 +02:00
Leonard Kim
94b3f6410d ref(api): move local participant name change 2019-06-24 13:15:02 -07:00
Leonard Kim
3d30f6e9cd ref(api): move filmstrip display notification 2019-06-24 13:15:02 -07:00
Leonard Kim
40c16f0bac ref(api): move tile view subscriber to api dir 2019-06-24 13:15:02 -07:00
Leonard Kim
a1db63a8c2 ref(api): move feedbackSubmitted notification to api middleware 2019-06-24 13:15:02 -07:00
Leonard Kim
59a9c2d947 fix(notifications): show notifications after reducers update to get name
Otherwise the participant will not have been added yet
to state so the participant name will not display in
the notification.
2019-06-24 10:51:17 -07:00
Yana Stamcheva
fc897b9bac Changes call quality to video quality. 2019-06-24 14:39:22 +01:00
damencho
96f013c549 Fixes few undefined errors on standby. 2019-06-24 12:06:27 +01:00
damencho
742905e05a Removes duplicated text. 2019-06-24 12:06:27 +01:00
damencho
bde44a94e8 Changes display name prompt to non modal, so people can mute/unmute. 2019-06-24 12:06:27 +01:00
Saúl Ibarra Corretgé
1786bfadce android: make some activity attributes private
They are only meant to be used internally. This reduces the risk of SDK users
sending garbage when we expect a specific type.
2019-06-21 21:48:46 +02:00
Saúl Ibarra Corretgé
b2e840636a sounds: lower log severity
When native SDK users end a meeting the view gets disposed and detached from
React, and then the entire app gets destroyed and these errors get printed at
the error level, throwing some people off.
2019-06-21 21:48:46 +02:00
Saúl Ibarra Corretgé
ddaa22048f android: make sure we left the current meeting when the activity is destroyed
If the user swipes the activity from the recents list there is no other chance,
onDestroy gets called directly.
2019-06-21 21:48:46 +02:00
Saúl Ibarra Corretgé
3e77890387 android: fix not calling super in onNewIntent 2019-06-21 21:48:46 +02:00
Leonard Kim
1e39c12963 fix(suboptimal): allow checks for chromium based browsers 2019-06-21 09:55:43 -07:00
Saúl Ibarra Corretgé
243fdba80f android: fix exception when sending events without URL
ENTER_PIP_MODE, for example, does not have it.
2019-06-21 15:42:10 +02:00
Дамян Минков
08c4933c1b Fixes inviting more than one participant (#4352)
* Fixes inviting more than one participant.

* Shows a notification when participants are invited.

* Adds support for both .id and .user_id props for people query results.
2019-06-21 13:17:47 +01:00
Leonard Kim
d5e0dea469 fix(suboptimal): ignore mobile browsers in whitelists/blacklists 2019-06-21 11:01:40 +01:00
paweldomas
033aa0dd6e fix(base/conference/reducer): check if room is defined
This was hit on a corner case when ConnectionService will deny
the request to start the call. I am not sure, but it could have been
that the conference object has been disposed or closed or something
else, but the fact is that 'conference.room' was not defined and things
crashed. It is not safe to access conference's private field 'room'. It
is true JitsiConference doesn't follow the practice of marking this
field as private with the underscore '_', but it is not a public field.
2019-06-20 13:19:04 -05:00
Saúl Ibarra Corretgé
803870ef8f android: add a uncaught exception handler
Its main task is to cleanup conferences (specially the connection services
stuff) to make sure the system is left in a working state even when the
unexpected happens.
2019-06-20 17:03:24 +02:00
virtuacoplenny
bf67a4a675 Configurable (sub)optimal and unsupported browsers (#4351)
* Configurable (sub)optimal and unsupported browsers

* maybe this helps somehow
2019-06-20 14:02:15 +01:00
Bettenbuk Zoltan
ee2036a2a7 feat: show on stage function 2019-06-20 11:05:34 +02:00
Bettenbuk Zoltan
4c3ed190f3 feat: add ability to toggle toolbox from tile view 2019-06-20 11:05:34 +02:00
Hristo Terezov
a91b49c2c1 feat(reload): on offer / answer error. 2019-06-19 05:25:43 -07:00
Saúl Ibarra Corretgé
186ba70cb7 participants: skip local participant join notification
Also, use the helper function to get the display name for a participant.
2019-06-19 13:15:17 +02:00
Leonard Kim
12c18657d5 fix(welcome-page): make Tabs more resilient to bad props
In case wrong props are passed in, such as pointing to
an index that does not contain a value in the tabs
array.
2019-06-18 17:55:21 -07:00
Leonard Kim
9f8e7d4050 chore(deps): bump lib to a89d673 for caps version fixes 2019-06-18 17:24:12 -07:00
Leonard Kim
4cea7018f5 fix(tile-view): back to single click to pin
Undoes the logic added in:
ebcde745ef
2019-06-18 15:14:20 -07:00
Saúl Ibarra Corretgé
54a9b9199e rn: adapt to API changes in google signin 2019-06-18 14:51:44 +02:00
Saúl Ibarra Corretgé
4591b36c3e android: handle onActivityResult Activity lifecycle method
It may be called in the Activity instead of in the Fragment. Handle both.
2019-06-18 14:51:44 +02:00
Saúl Ibarra Corretgé
db862b5b3b misc: add Android debug builds to .gitignore 2019-06-18 14:51:44 +02:00
Saúl Ibarra Corretgé
70b864f00b deps: react-native-google-signin@2.0.0 2019-06-18 14:51:44 +02:00
Saúl Ibarra Corretgé
73b6a7a134 android: fix React packager not working on debug builds on a device 2019-06-18 14:51:44 +02:00
Saúl Ibarra Corretgé
8b5b112c6a android: don't default to making libre builds 2019-06-18 14:51:44 +02:00
Leonard Kim
2f7f9f24c4 fix(display-name): dismiss prompt if name gets set 2019-06-17 15:10:53 +01:00
Leonard Kim
1197c26529 fix(always-on-top): enforce circle avatar 2019-06-17 16:08:39 +02:00
Дамян Минков
6eb66b639e Notify for kick and mute (#4328)
* Updates kick showing who kicked us.

* Notify participants that someone was kicked.

* Shows notification to user who is remotely muted.

* Updates the notification type.

* Muted by notification for mobile.

* Moves code to react and adds the kick notifications to mobile.

* Updates lib-jitsi-meet.
2019-06-17 16:00:09 +02:00
Saúl Ibarra Corretgé
fa88db6897 ios: update CocoaPods to 1.7.1 2019-06-14 13:24:14 +02:00
Дамян Минков
64eb4b5609 Updates start silent, turning on startWithAudioMuted and few UI tweaks. (#4314)
* Updates start silent, turning on startWithAudioMuted and few UI tweaks.

Disabled mic unmute button and removes remote participants volume slider.

* Adds analytics for start silent.

* Removes extra semi colon.

* Updates lib-jitsi-meet and updates meeting info text.
2019-06-14 12:16:08 +01:00
Emil Ivov
ef2455caea Merge pull request #4333 from saghul/display-name-copy
lang: update display name request copy
2019-06-14 11:13:22 +01:00
Saúl Ibarra Corretgé
ca11cbf6cc calendar-sync: fix loading calendar entries
Checking if the calendar support in the reducer is not only useless but wrong,
since we don't have access to the entire store (the calendar support is checked
in the base/config feature). If calendar support is not enabled the actions
being reduced won't be dispatched anyway, so no harm is done by removing the
check.
2019-06-14 11:32:39 +02:00
Saúl Ibarra Corretgé
f15a2aea68 lang: update display name request copy 2019-06-14 11:03:32 +02:00
paweldomas
e6c3d7ded7 chore(deps): bump LJM version to increase frozen video timeout
Update LJM to 25ca5cbd2a93150e74f029075bc7ac734ed97a2f
2019-06-13 12:32:25 -05:00
Hristo Terezov
2861198251 ref(no-data-from-source): logic. 2019-06-13 09:52:10 -07:00
Hristo Terezov
226c0bb084 ref(track-error): Remove NO_DATA_FROM_SOURCE 2019-06-13 09:52:10 -07:00
Saúl Ibarra Corretgé
30c0bfc108 rn: disable vertical scrollbars on bottom sheets 2019-06-13 10:07:55 +02:00
Leonard Kim
df50e7fa69 fix(large-video): make blurred background fit whole screen 2019-06-12 20:27:04 -07:00
Saúl Ibarra Corretgé
f85ac3ef91 rn: fix video unmuting when disabling audio-only
When the video unmute button disabled audio-only, also unmute video. This fixes
a weird case in which the user need to "unmute twice" if they were muted beofre
they enabled audio-only mode. That's ok if the audio-only button was used, but
not if the video-unmute button was used, since the expectation is to have video,
of course.
2019-06-12 18:54:35 +02:00
Saúl Ibarra Corretgé
e33b334307 rn: add SDK API to set user information
At the moment it includes:

- display name
- email
- avatar URL

This information is used *only* if no token was specified.
2019-06-11 17:27:16 +00:00
Bettenbuk Zoltan
ce6f7308ad fix: avoid keyboard with search results list 2019-06-11 19:14:15 +02:00
Bettenbuk Zoltan
f66478fa34 feat: don't auto-stage bot type participants 2019-06-11 17:55:44 +02:00
Bettenbuk Zoltan
bf99051885 fix: invite search result sorting 2019-06-11 17:55:44 +02:00
Bettenbuk Zoltan
7234ca69c8 feat: invite field autofocus 2019-06-11 17:55:44 +02:00
Bettenbuk Zoltan
ae965877f3 fix: invite list needs double tap to select 2019-06-11 17:55:44 +02:00
Leonard Kim
ae3b70eb13 feat(api): notify of password required 2019-06-11 08:12:37 -07:00
Saúl Ibarra Corretgé
97e0303065 feature-flags: add flag for enabling calendar integration 2019-06-11 13:37:50 +00:00
Saúl Ibarra Corretgé
35ffbe1720 feature-flags: add flag for enabling chat 2019-06-11 13:37:50 +00:00
Saúl Ibarra Corretgé
f7b92f65ca ios: add feature flag to enable recording on iOS 2019-06-11 13:37:50 +00:00
Saúl Ibarra Corretgé
cf7b10d53d feature-flags: initial implementation
The welcomePageEnabled and pictureInPictureEnabled props on mobile have been
converted to feature flags.
2019-06-11 13:37:50 +00:00
Saúl Ibarra Corretgé
d798f93614 deps: check-in the diff when npm 6.9.0 is used 2019-06-11 13:08:23 +00:00
Saúl Ibarra Corretgé
4ddfcaf584 toolbox: disable audio-mode when video-unmuting
If audio-only was engaged, use the video (un)mute button to disengage it. This
should simplify the flow for getting back to video.
2019-06-11 13:08:23 +00:00
Saúl Ibarra Corretgé
431a221c63 ios: be resilient to invalid UUIDs 2019-06-11 10:04:15 +00:00
Mihai Damian
477826089c ios: Added property for setting PiP initial position 2019-06-11 09:25:23 +00:00
Hristo Terezov
a46369cf22 chore(package.json): Update lib-jitsi-meet 2019-06-10 06:53:36 -07:00
Hristo Terezov
651791b8df feat(deeplinking): Pass state to openDesktopApp. 2019-06-10 04:14:41 -07:00
virtuacoplenny
09cc738219 fix(recording): do not prompt hidden participants for name (#4309)
* fix(recording): do not prompt hidden participants for name

* squash: update package.json
2019-06-10 11:27:08 +01:00
Leonard Kim
6d8ec4d147 fix(unsupported): stop recommending safari 2019-06-07 07:36:20 -07:00
Leonard Kim
d65a068fdb feat(deep-linking): hide web button on unsupported browsers 2019-06-07 07:36:20 -07:00
Leonard Kim
cf23045f8d feat(unsupported): provide custom blacklist for branding 2019-06-07 07:36:20 -07:00
Leonard Kim
e47d2d13ce fix(deep-linking): deep link first, then show unsupported
Re-structure the custom routing to split between
platforms instead of between intended route features.
This made it easier for me to understand where to
do the checks for unsupported browser after deep-linking
had been checked.
2019-06-07 07:36:20 -07:00
Aaron van Meerten
07b7f03aa7 Merge pull request #4308 from jitsi/prosody-token-allow-asap-server-override
allows override of asap key server in token utility
2019-06-06 14:26:25 -06:00
Aaron van Meerten
7ce44f85ca changed to using a setter for the asapKeyServer 2019-06-06 15:22:38 -05:00
Aaron van Meerten
41e0d782ce allows override of asap key server in token utility 2019-06-06 14:41:46 -05:00
Aaron van Meerten
2a8fafdd36 Merge pull request #4303 from jitsi/start-silent
Adds a config param startSilent to disable audio output.
2019-06-05 12:29:57 -06:00
damencho
faee1c139e Adds a config param startSilent to disable audio output. 2019-06-05 18:01:18 +01:00
virtuacoplenny
eb644987ce fix(settings): do not use non-set localStorage values (#4299)
If a value is not set in localStorage then null is
returned. null should not be converted to an empty
string (via _.escape) because that will then be
stored in localStorage as the user set preference
and will keep overriding any other values set
in localStorage for the displayname.
2019-06-04 17:42:48 -07:00
damencho
de60a70daf Commit from translate.jitsi.org by user damencho.: 555 of 625 strings translated (8 fuzzy). 2019-06-03 11:19:10 +00:00
damencho
2904dfa794 Commit from translate.jitsi.org by user damencho.: 584 of 625 strings translated (2 fuzzy). 2019-06-03 11:19:01 +00:00
damencho
d51cf7c581 Commit from translate.jitsi.org by user damencho.: 625 of 625 strings translated (0 fuzzy). 2019-06-03 10:58:25 +00:00
Hristo Terezov
f25e6c6a5d chore(package.json): Update lib-jitsi-meet version 2019-06-01 02:28:04 -07:00
Hristo Terezov
5fb9422513 feat(API): Add show feedback parameter to hangup 2019-06-01 02:28:04 -07:00
Hristo Terezov
d01cfc8466 fix(conference): API left event. 2019-06-01 02:28:04 -07:00
Saúl Ibarra Corretgé
fa3888991f rn: avoid logging initial props in release builds
They may contain sensitive information.
2019-05-31 11:49:36 +02:00
virtuacoplenny
ded355a807 fix(settings): use moderator check helper (#4292) 2019-05-30 14:10:40 -07:00
Leonard Kim
b655c8d54a fix(large-video): clear remote video stream on track removal
VideoLayout schedules a large video update by passing in
the video stream on the small video instance. When a stream
is removed, the UI is removed from the small video instance
but a reference to the stream is left. So when VideoLayout
schedules the large video update after a stream removal,
the old stream from the small video instance is re-used,
even though it has been removed.

This change also brings balance with RemoteVideo method
"addRemoteStreamElement" which sets the stream on the
small video instance, so now "removeRemoteStreamElement
unsets it.
2019-05-30 09:46:35 -07:00
Leonard Kim
42a6e6faaf ref(large-video): remove redundant call to update on stream removal 2019-05-30 09:46:35 -07:00
Leonard Kim
c7954c284d ref(large-video): move layout update on stream removal to layout middleware 2019-05-30 09:46:35 -07:00
virtuacoplenny
251da1861a feat(api): notify api of mic and camera errors (#4289)
- Use actions to notify the rest of the app that
  a mic or camera error has occurred
- Use middleware to respond to those notifications
  of errors by showing in-app notifications and
  notifying the external api
2019-05-29 14:17:07 -07:00
Hristo Terezov
9712804040 fix(Amplitude): user id 2019-05-29 09:53:31 -07:00
Hristo Terezov
fecbef0aff fix(AmplitudeModule): class name 2019-05-29 17:22:50 +02:00
Saúl Ibarra Corretgé
d65b71b584 rn: add ability to set the conference subject 2019-05-29 14:48:02 +02:00
Saúl Ibarra Corretgé
579d291bca config: add ability to pass the subject as a URL parameter 2019-05-29 14:48:02 +02:00
Saúl Ibarra Corretgé
871026f4ba conference: clear the pending subject after it has been set 2019-05-29 14:48:02 +02:00
Saúl Ibarra Corretgé
9a8a070c62 rn: show conference subject if set 2019-05-29 14:48:02 +02:00
Leonard Kim
7cf4c7bd78 Revert "feat(screenshare): enable auto-pin of latest and last screenshare"
This reverts commit f42d0411b1.

The UX provided by this feature flag in its current state is not
desired. Also, I noticed filmstrip sometimes failing to properly
update small video display mode on pin/unpin. The feature is
being left in for consumers of jitsi-meet to enable as needed.
2019-05-28 15:28:50 -07:00
Hristo Terezov
72a1def571 feat(config): whitelist config.analytics 2019-05-24 13:42:12 -07:00
damencho
0dad99c3b7 Enables local video flip menu by default. 2019-05-24 23:09:24 +03:00
Hristo Terezov
840c0190c4 fix(deep-linking): Don't rely on custom scheme 2019-05-24 12:51:14 -07:00
Leonard Kim
e0fdeea69b fix(large-video): do not stretch dominant speaker avatar 2019-05-24 12:00:35 -07:00
Leonard Kim
e3612929f8 fix(avatar): dynamically size avatar in dynamically sizable filmstrip 2019-05-24 12:00:35 -07:00
Hristo Terezov
70921bb6ef feat(analytics): local tracks duration event. 2019-05-24 10:09:25 -07:00
Saúl Ibarra Corretgé
371ca4eef1 ios: don't require bitcode for Debug builds 2019-05-24 14:11:08 +02:00
Bettenbuk Zoltan
54fdb7066f feat: scrollable bottom sheet 2019-05-24 14:06:17 +02:00
Bettenbuk Zoltan
85bcb0c757 fix: auth dialog button labels 2019-05-24 11:35:56 +02:00
Bettenbuk Zoltan
d387cbe5bd fix: iOS 10 bottom sheet style 2019-05-24 11:28:28 +02:00
paweldomas
1bc28e4904 watchos: display a message if the recent list is empty 2019-05-24 09:41:31 +02:00
Saúl Ibarra Corretgé
cb3419ba2a android: enter PiP mode when pressing back button
When in a conference, try to enter PiP when pressing the back button. If this is
not possible (because it's unsupported, not enabled, etc.) fall back to the
previous behavior of simply hanging up.
2019-05-23 16:00:12 +02:00
Saúl Ibarra Corretgé
a2f8e156da app: avoid loading config when going back to the welcome page 2019-05-23 15:16:31 +02:00
Saúl Ibarra Corretgé
a4cf79c161 rn: fix losing audio if call is hangup too quickly
This PR changes the logic for connecting / disconnecting conferences. Instead of
doing it in mount / unmount events from the Conference component, it moves the
logic to the appNavigatee action.

This fixes a regression introduced in 774c5ecd when trying to make sure the
conference terminated event is always sent.

By moving the logic to appNavigate we no longer depend on side-effects for
connecting / disconnecting, and the code should be more maintainable moving
forward.

An improvement to this is the concept of sessions, which, while not tackled
here, was taken into consideration.
2019-05-23 15:16:31 +02:00
Saúl Ibarra Corretgé
9352517705 ios: always log delegate method calls 2019-05-23 15:16:31 +02:00
Saúl Ibarra Corretgé
47d5163c52 rn: don't tag builds by default
People run these in their own checkout and will run into problems because
tagging will fail.
2019-05-23 12:07:04 +02:00
Bettenbuk Zoltan
def22b01bb fix: set explicit color for search field to avoid theme override 2019-05-23 12:06:50 +02:00
Saúl Ibarra Corretgé
9445cf99fd Revert "ios: remove no longer needed code"
This reverts commit 603d161788.
2019-05-22 18:10:35 +02:00
paweldomas
96b226de24 watchos: change the icons
Inverts the icons to follow more what's in the phone app instead of
CallKit.
2019-05-22 17:25:35 +02:00
Bettenbuk Zoltan
5101f69e4e feat: don’t render moderator icon if everyone is moderator 2019-05-22 14:08:52 +02:00
François Benaiteau
61b66e0edf doc: fix incorrect code examples for universal / deep linking 2019-05-22 14:08:37 +02:00
Bettenbuk Zoltan
700051f809 fix: device selection colour scheme support 2019-05-22 12:29:28 +02:00
Дамян Минков
d16e10baec room-lock: adds ability to allow only digits for room locking 2019-05-22 09:43:17 +02:00
ibauersachs
11e5c14f83 Commit from translate.jitsi.org by user ibauersachs.: 317 of 625 strings translated (31 fuzzy). 2019-05-21 17:02:23 +00:00
ibauersachs
ded58d77d1 Commit from translate.jitsi.org by user ibauersachs.: 319 of 613 strings translated (26 fuzzy). 2019-05-21 16:58:20 +00:00
ibauersachs
8642c372c4 Commit from translate.jitsi.org by user ibauersachs.: 323 of 583 strings translated (4 fuzzy). 2019-05-21 16:56:52 +00:00
ibauersachs
edbf591059 Commit from translate.jitsi.org by user ibauersachs.: 430 of 583 strings translated (18 fuzzy). 2019-05-21 16:55:09 +00:00
jitsi-pootle
ded4291d6a New files added from translate.jitsi.org based on templates 2019-05-21 14:09:04 +00:00
Дамян Минков
a14fead0f3 Groups devices notifications by type audio/video. (#4238)
* Groups devices notifications by type audio/video.

* Fixes passing correct device array.
2019-05-20 21:35:42 +01:00
Saúl Ibarra Corretgé
466e1e3eb8 android: fix publishing new async storage package
The naming didn't match, so adjust it. @ cannot be used for maven artifact
names.
2019-05-20 17:33:36 +02:00
Saúl Ibarra Corretgé
8a90f0dab1 android: include SDK version in Maven repo commit message 2019-05-20 17:33:17 +02:00
Leonard Kim
d7e0aa3f61 fix(api): enable the external api before the first redux update
For the external api to fire update events out of the iframe, it
must first be initialized within the jitsi app. Any invocations
by the app to send updates events before initialization will
cause the api to swallow the events. The chosen fix is to
initialize the api earlier so the first update of app's redux
store fires update events that the api will also fire out of
the iframe.

This change will affect current behavior in that right now
the update event of the initial set of the avatar url is
blocked, but the change will make that event fire out of the
iframe.
2019-05-20 11:56:08 +02:00
Leonard Kim
37b343a797 feat(api): add ability to toggle tile view 2019-05-20 02:53:16 -07:00
Leonard Kim
149485905c fix(api): store passed in devices as user selected
Currently devices set through the api are stored
as ids, and not user selected. This can cause
other existing user selected devices to take
precedence over the devices passed into the api.
2019-05-17 10:47:31 +01:00
Aaron van Meerten
7f1df5629e Merge pull request #4229 from jitsi/poltergeist-prefix-support
updates bosh to support optional prefix
2019-05-16 15:40:28 -06:00
Leonard Kim
f42d0411b1 feat(screenshare): enable auto-pin of latest and last screenshare 2019-05-16 14:19:34 -07:00
Aaron van Meerten
8d1d573266 updates bosh to support optional prefix
use optional prefix in poltergeist room lookup
2019-05-16 14:23:36 -05:00
Leonard Kim
d86b60ea72 fix(chat): maintain bottom scroll on input resize 2019-05-15 08:06:35 -07:00
Leonard Kim
dfe5fbb702 ref(chat): change initial input size to 1 line 2019-05-15 08:06:35 -07:00
Leonard Kim
09f881c0f5 ref(chat): bring in package for text area auto-resizing 2019-05-15 08:06:35 -07:00
Leonard Kim
f1546008f9 ref(chat): removed unused getChatInputRef callback for input 2019-05-15 08:06:35 -07:00
Leonard Kim
d8df7fde84 ref(chat): clean up public blur/focus methods on input
Method blur is not called. Method blur is called
internally only.
2019-05-15 08:06:35 -07:00
Saúl Ibarra Corretgé
1c809eb428 ios: strip bitcode when releasing the SDK 2019-05-15 14:07:25 +02:00
Saúl Ibarra Corretgé
e94edcd4ae ios: automagically download a bitcode WebRTC build if needed 2019-05-15 09:54:17 +02:00
paweldomas
b48651396f fix(travis): upload through ssh proxy 2019-05-14 19:37:37 -05:00
Leonard Kim
e2044074ad Revert "fix(welcome-page): remove watermark container to avoid z-index wars"
This reverts commit 890151fa72.
2019-05-14 12:42:54 -07:00
Saúl Ibarra Corretgé
f060ac9db1 ios: notify RTCAudioSession about CallKit AVAudioSession activation 2019-05-14 21:09:39 +02:00
Leonard Kim
5a53d7f32a fix(chat): re-fix letting long messages wrap 2019-05-14 09:20:25 -07:00
Leonard Kim
4eec13da1c ref(chat): de-parameterize AbstractMessageContainer 2019-05-14 09:20:25 -07:00
Leonard Kim
cb8282dfe5 ref(chat): remove unused method 2019-05-14 09:20:25 -07:00
Leonard Kim
5cd0b1a9be fix(chat): fix auto-scrolling to bottom
Empower the parent.
2019-05-14 09:20:25 -07:00
Leonard Kim
504fadaf71 ref(chat): on web, move timestamp to chat message 2019-05-14 09:20:25 -07:00
Leonard Kim
7187e540a8 ref(chat): on native, show messages as grouped by sender 2019-05-14 09:20:25 -07:00
Leonard Kim
34dffbfc5e ref(chat): on native, group messages by sender (no styling) 2019-05-14 09:20:25 -07:00
Leonard Kim
a9637f93c3 ref(chat): create AbstractMessageContainer
So mobile and web can share logic for grouping chat
messages by sender.
2019-05-14 09:20:25 -07:00
Leonard Kim
0e8b0a9c5c ref(chat): create web MessageContainer component 2019-05-14 09:20:25 -07:00
Saúl Ibarra Corretgé
e66b596a0d ios: add ability to override SDK version when releasing 2019-05-14 17:00:02 +02:00
Saúl Ibarra Corretgé
6f320f463d rn: don't use annotated tags when building the SDKs 2019-05-14 17:00:02 +02:00
Saúl Ibarra Corretgé
02955ab57c deps: react-native@0.59.8
https://github.com/react-native-community/releases/blob/master/CHANGELOG.md#v0598
2019-05-14 10:22:50 +02:00
Leonard Kim
a9d76a2577 fix(large-video): vertically align center screenshare
Stop using special case logic for aligning screenshare videos.
It may be possible to have positioning all done using CSS but that
seems to be a more significant refactoring.
2019-05-10 08:09:56 -07:00
Bettenbuk Zoltan
dcf31baf3a doc: update google auth doc 2019-05-10 13:22:05 +02:00
Bettenbuk Zoltan
1e346f10ab rn: fix streaming key input color 2019-05-10 13:22:05 +02:00
Leonard Kim
a114d55fac fix(chat): ensure really long words can trigger wrapping 2019-05-09 08:25:47 -07:00
Leonard Kim
afde717ca4 ref(chat): use message type as classname 2019-05-09 07:06:27 -07:00
Leonard Kim
fb5a45f714 feat(chat): on web, group messages by sender 2019-05-09 07:06:27 -07:00
Дамян Минков
f5ac18da18 Add option to allow guest(moderators) to add a room password 2019-05-09 13:30:38 +02:00
Saúl Ibarra Corretgé
103ae363f6 ios: fix CallKit crash in development mode
It's possible a CallKit event arrives when the React Bridge has been torn down
and there is an assert that checks this. In order to avoid a crash, just skip
the event.
2019-05-09 13:22:58 +02:00
damencho
9bde673397 Updates copy info with parltcipant name info if available. 2019-05-09 10:33:55 +01:00
paweldomas
ff6b27eafa fix(travis): add watch dev prov profile 2019-05-08 19:01:28 -05:00
paweldomas
8cb19ccbf6 fix(travis): download WebRTC bitcode 2019-05-08 19:01:28 -05:00
damencho
198eba3682 Does not play sound notifications on the recording side. 2019-05-08 10:27:05 -07:00
Leonard Kim
a49f62238b ref(chat): clean up extra dom 2019-05-08 08:57:00 -07:00
Leonard Kim
a8233bdb84 ref(chat): move some colors to css variables 2019-05-08 08:57:00 -07:00
Leonard Kim
ec2826e0fc ref(chat): make wider 2019-05-08 08:57:00 -07:00
Leonard Kim
3d9606f6da ref(chat): use somewhat transparent background 2019-05-08 08:57:00 -07:00
Leonard Kim
01458eeff9 ref(chat): add a header for holding the close button 2019-05-08 08:57:00 -07:00
Leonard Kim
0318568a30 ref(chat): add light top border on input for visual separation 2019-05-08 08:57:00 -07:00
Leonard Kim
4d04141f24 ref(chat): change input placeholder 2019-05-08 08:57:00 -07:00
Leonard Kim
afbc622fb9 ref(chat): differentiate local and remote messages with background color 2019-05-08 08:57:00 -07:00
Leonard Kim
fbc7f865ec ref(chat): change chat bubble borders based on sender
For remote chat messages, all corners should be rounded
except the top left. For local messages all corners
should be rounded except the top right.
2019-05-08 08:57:00 -07:00
Leonard Kim
2a4bac7a27 ref(chat): remove chat bubble arrow 2019-05-08 08:57:00 -07:00
Saúl Ibarra Corretgé
b45a5da6e2 rn: use new AsyncStorage package
It was extracted from the RN core to a community maintained package.
2019-05-08 16:03:09 +02:00
Saúl Ibarra Corretgé
2fad9f9ba8 ios: update Podfile.lock 2019-05-08 12:12:54 +01:00
Saúl Ibarra Corretgé
8b0e5b9d15 android: set system navbar color to match the header 2019-05-08 12:44:17 +02:00
paweldomas
0889ffdf27 android fix: do not enter PiP mode when the permissions alert is shown
Entering PiP mode while the permissions dialog is display will not only
fail, but also mess up the Activity lifecycle on some OS versions.
We may end up with two activity/fragment instances and a situation where
the onStop callback was not called yet on the instance #1 while
the onResume has been already called on instance #2.
2019-05-08 10:15:14 +02:00
Bettenbuk Zoltan
86d0d4fc22 rn: add DialInSummary 2019-05-07 18:02:14 +02:00
Bettenbuk Zoltan
7e9df74e60 rn: add generic alert dialog 2019-05-07 18:02:14 +02:00
Bettenbuk Zoltan
3eca67e1ad rn: add HeaderWithNavigation component 2019-05-07 18:02:14 +02:00
Дамян Минков
c040b3a7dd Fall back to using label for preferred devices (#4171)
* Skips setting undefined device id to sink in audio preview.

* Fallbacks to use labels for user selected devices.

* Fixes comment.
2019-05-07 09:53:01 +01:00
Leonard Kim
3f4a71c26d fix(welcome-page): remove watermark container to avoid z-index wars
By making the container 100% height and position relative, that
would cause it to overlap any static-positioned  elements below it.
The 100% makes it so that any watermarks intended for the bottom
of the page show up on the bottom of the page. However, it's not
needed because watermark stylings already try to position the
watermarks at the bottom.
2019-05-04 11:03:48 -07:00
Leonard Kim
e7db8d6812 fix(chat): save chat error messages into redux
The proper field name is "messageType",
not "type." Also using "type" would
override the actionType.
2019-05-03 14:06:36 -07:00
Saúl Ibarra Corretgé
7d2ac0244d deps: react-native-webrtc@4064c6f2db4f8b961daaaa8dafc6a896d7cfbc43
New M69 build with Metal crash fixes.
2019-05-03 19:29:30 +02:00
Saúl Ibarra Corretgé
c0efea5168 ios: enable bitcode
Time has come. We need to enable bitcode. It's optional for iOS targets, but
mandatory for the entire project if there is a watchOS target. Since we have a
watchOS target, it's time to enable it.
2019-05-03 19:29:30 +02:00
Saúl Ibarra Corretgé
5ed53dcef5 ios: update Fastlane for watchOS app 2019-05-03 19:29:30 +02:00
Saúl Ibarra Corretgé
746159a1ac ios: set compilation mode to "wholemodule" for release builds 2019-05-03 19:29:30 +02:00
Saúl Ibarra Corretgé
43a8fd2a53 ios: set iOS deployment target correctly everywhere 2019-05-03 19:29:30 +02:00
Saúl Ibarra Corretgé
a26bb2c1a6 watchos: add watchOS app
Co-authored-by: Pawel Domas <pawel.domas@jitsi.org>
2019-05-03 19:29:30 +02:00
paweldomas
e4af5ddbe9 feat(base/connection): throw error and add isInviteURLReady 2019-05-03 19:29:30 +02:00
Дамян Минков
768cff48a4 Notify for new device (#4165)
* Fix detecting preferred audio output.

Fixes detecting when a new output device is found and we have stored user preference of using that device.

* Does not store which is the currently open device on save.

Does not save the currently opened device when saving settings dialog, this will be done once we successfully replace the tracks to use the new devices.

* Saves opened audio device after successfully changing it.

If we do it earlier _updateAudioDeviceId is using localAudio and can store wrong value.

* Adds notification for new non preferred devices.

A notification is shown which gives an option to the user to select and use the newly plugged devices.
Adding custom button and handler for the action to the notifications.

* Changes logic to search and handle all newly added devices from array.

* Moves some utility methods to features/base/devices.
2019-05-03 18:25:33 +01:00
damencho
384f0d4317 Removes hardcoded defaulting to US number from the code. 2019-05-03 16:55:22 +01:00
damencho
0ec4e6a805 Makes numbers clickable on the more numbers page when opened on mobile. 2019-05-03 16:55:22 +01:00
Saúl Ibarra Corretgé
5cc01b074e ios: update Podfile.lock for RN update 2019-05-03 10:27:17 +02:00
damencho
deaf5ba612 Always uses the id for the device extrackted from the track.
When updating the currently used devices always uses the id that is used by the local track instance.
2019-05-02 11:55:46 +01:00
damencho
740c1eb84f Adds new persistent state for devices user selection.
The state about currently opened devices is filtered and not stored, where we only store when user selects a device preferences.
Also allow changing input devices for Firefox when we are not in a conference.
2019-05-02 11:55:46 +01:00
Saúl Ibarra Corretgé
2d45709a6a android: add the ability to make a "libre" build
A libre build will exclude the following:

- Analytics modules
- Google Play services GMS
- Crashlytics
- Firebase
2019-05-02 09:26:20 +02:00
Saúl Ibarra Corretgé
6bbc2927ab analytics: don't initialize handlers if they are not properly configured 2019-05-02 09:26:20 +02:00
Saúl Ibarra Corretgé
08891b17b6 android: expose JitsiMeetActivity.leave() 2019-05-02 09:26:20 +02:00
Saúl Ibarra Corretgé
aab3428347 android: make JitsiMeetActivity.join public 2019-05-02 09:26:20 +02:00
Saúl Ibarra Corretgé
bf7b1c5cfc rn: add support for alpha.jitsi.net 2019-05-01 23:23:24 +02:00
Saúl Ibarra Corretgé
7b347baab6 deps: react-native@0.59.5 2019-05-01 19:16:08 +02:00
Saúl Ibarra Corretgé
f9b3d470e9 cc: fix showing CC button if config option is undefined 2019-04-30 14:50:56 +02:00
Saúl Ibarra Corretgé
7b78fa45f4 invite: don't consider "add people" enabled if there is no search URL
This avoids showing the + button when there is no service configured, ie with
the default Jitsi Meet install.
2019-04-30 14:50:56 +02:00
Saúl Ibarra Corretgé
34dcbd991e rn: wait for animation before hiding SlidingView 2019-04-30 12:45:53 +02:00
Saúl Ibarra Corretgé
70dc22c107 rn: refactor BottomSheet
Avoid using a Modal since those create trouble with the view hierarchy.
2019-04-30 12:45:53 +02:00
damencho
89719520e2 Disposes the tracks in component was unmounted while creating those.
The issue is if you quickly click Devices and then another tab, we may leave open tracks (video light stays on even when you are video muted).
2019-04-29 14:38:17 +00:00
Дамян Минков
ce7bdb35ac Merge pull request #4152 from jitsi/prosody-0.10-update
Updates config if prosody 0.10 is used.
2019-04-29 14:36:55 +00:00
Дамян Минков
bf8c716477 Merge pull request #4150 from jitsi/invitation-update
Update copy invite text.
2019-04-29 14:36:46 +00:00
Дамян Минков
93e8d755d3 Merge pull request #4148 from zbettenbuk/recording-web-css-fix
Safeguard Container style when used cross-platform
2019-04-29 14:36:35 +00:00
damencho
c09eee0985 Disables chat when we are in recorder mode. 2019-04-29 14:36:22 +00:00
damencho
4f6a0d7d3a Updates config if prosody 0.10 is used. 2019-04-29 15:24:55 +01:00
damencho
dd5233d31b Update copy invite text. 2019-04-29 15:06:36 +01:00
Bettenbuk Zoltan
31638133b7 Safeguard Container style when used cross-platform 2019-04-29 13:37:30 +02:00
Bettenbuk Zoltan
b886f8d72d rn: specify chat text field font color 2019-04-26 21:33:11 +02:00
Дамян Минков
a6555c5d24 Singleton follow me (#4144)
* Prints errors in case of wrong initialization.

Not printing can masks some errors in the code.

* Allow only one Follow Me moderator in a meeting.

* Sends Follow Me state with all presences of the moderator.

This fixes an issue where the moderator sends the Follow Me state and then for example mute or unmute video (this will produce a presence without Follow Me state) and the new comers will not reflect current Follow Me state till a change of it comes.

* Changes fixing comments.

* Changes fixing comments.
2019-04-26 18:11:53 +00:00
Hristo Terezov
98c8fb09c4 feat(package.json): Update lib-jitsi-meet. 2019-04-26 07:54:38 -07:00
Leonard Kim
b76b261cab fix(invite): show telephone icon 2019-04-26 07:46:41 -07:00
Bettenbuk Zoltan
0b6c51f666 rn: replace 3rd party chat library with custom implementation 2019-04-26 15:17:36 +02:00
Sylvia van Os
1cb9bbc7a4 Fix wrong filename change 2019-04-26 09:06:43 +00:00
Sylvia van Os
fee9bdb98c Fix NAT documentation 2019-04-26 09:06:43 +00:00
virtuacoplenny
fb82cf4517 fix(modal): bump dep to 8.0.1 to remove scrollbars (#4139) 2019-04-25 11:58:11 -07:00
Saúl Ibarra Corretgé
85388b8d23 ios: handle some corner cases with Firebase Dynamic Links
- handle some weird bug
(https://github.com/firebase/firebase-ios-sdk/issues/233)
- use a common function to extract the URL off a dynamic link
2019-04-25 18:18:09 +02:00
Saúl Ibarra Corretgé
33f133ac25 ios: simplify code for handling CallKit listeners
Replace the Swift array with an Objective-C one, since it's going to store
Objective-C objects and not Swift objects (or Swift objects which inherit from
NSObject, which is equivalent).

This avoids the need for JMCallKitEventListenerWrapper entirely, since an
NSArray can store NSObjectProtocol objects, unlike a Swift array, which prompted
the creation of the wrapper in the first place.
2019-04-25 18:17:55 +02:00
Saúl Ibarra Corretgé
774c5ecd18 rn: ensure the conference terminated event is always sent
Dear reader, I'm not proud at all of what you are about to read, but sometimes
life just gives you lemons, so enjoy some lemonade!

Joining a conference implies first creating the XMPP connection and then joining
the MUC. It's very possible the XMPP connection was made but there was no chance
for the conference to be created.

This patch fixes this case by artificially genrating a conference terminated
event in such case. In order to have all the necessary knowledge for this event
to be sent the connection now keeps track of the conference that runs it.

In addition, there is an even more obscure corner case: it's not impossible to
try to disconnect when there is not even a connection. This was fixed by
creating a fake disconnect event. Alas the location URL is lost at this point,
but it's better than nothing I guess.
2019-04-25 14:04:26 +02:00
Saúl Ibarra Corretgé
ccc5e19e3c rn: fix filling LoadConfigOverlay's background 2019-04-24 17:41:28 +02:00
Saúl Ibarra Corretgé
32a81b0be5 rn: add our benevolent employer to the list of known domains 2019-04-24 17:36:41 +02:00
Saúl Ibarra Corretgé
59db39d4d9 rn: cleanup old code
This legacy code was added about a year ago to ease the migration between
releases:
631f51d627

I consider this not to be needed anymore.
2019-04-24 17:36:41 +02:00
damencho
2219298501 Updates web styling for file recording service sharing option. 2019-04-24 14:54:33 +00:00
Bettenbuk Zoltan
f92d530b0a Fix double file recording sharing switch 2019-04-24 10:35:43 +00:00
Bettenbuk Zoltan
e98c169c2f [RN] Fix iOS keyboard bug on invite search dialog 2019-04-24 11:48:09 +02:00
Saúl Ibarra Corretgé
6bf962817b ios: add a CallKit icon
The SDK will now search for an asset called "CallKitIcon" on the main bundle,
and fallback to a built-in asset it it's not there, allowing SDK users to
customize it by just adding asset with that name.
2019-04-24 10:03:46 +02:00
virtuacoplenny
4c286b8580 chore(deps): bump lib to get fixed rtc.destroy call (#4122) 2019-04-23 15:38:32 -07:00
Дамян Минков
37639a5614 Merge pull request #4121 from jitsi/remove-edge-support
Removes Edge support.
2019-04-23 20:32:17 +00:00
Bettenbuk Zoltan
b7198ba4b3 Add recording file sharing switch 2019-04-23 20:32:10 +00:00
damencho
2180d33e3d Adds alias for external_api.js in all default web config. 2019-04-23 20:31:53 +00:00
damencho
43a0ae578e Removes Edge support. 2019-04-23 17:55:07 +01:00
Bettenbuk Zoltan
154200460d Add some other paths to proxy bypass 2019-04-23 18:00:27 +02:00
Saúl Ibarra Corretgé
9a92dc578c ios: fix resetting CallKit's CXProvider
When CallKit is enabled / disabled, a new CXProvider must be created in order to
not confuse CallKit (it misbehaves otherwise).
2019-04-23 09:55:01 +02:00
paweldomas
eb38300c0d chore: update LJM to 1bfc96a2876d6527bfa27cf46d4f1e9f6e65edbc
Updates LJM in order to stop printing few obsolete error messages.
2019-04-18 12:24:23 -05:00
paweldomas
37b1ccbe61 ios: update react-native-werbtc in order to fix leaking streams 2019-04-18 12:24:23 -05:00
Bettenbuk Zoltan
725f9b1961 [RN] Rename lock room button 2019-04-18 14:18:08 +01:00
Leonard Kim
b172639237 fix(follow-me): remove duplicate default state 2019-04-17 15:58:55 -05:00
virtuacoplenny
c7013f5c4b ref(follow-me): hook into redux (#3991)
Use subscribers to detect state change and emit those
out to other participants. Use middleware to register
the command listener.
2019-04-17 08:05:32 -07:00
Saúl Ibarra Corretgé
aefa836406 Revert "misc: don't show a warning on Safari with VP8"
This reverts commit 9625be1db3.
2019-04-17 15:15:48 +02:00
virtuacoplenny
f6c410610a fix(toolbar): let click through gradient (#4107)
Otherwise it can eat clicks on elements it is above,
like YouTube and Etherpad controls.
2019-04-17 06:15:08 -07:00
Saúl Ibarra Corretgé
603d161788 ios: remove no longer needed code
Ever since we switched to handling track events instead of mute actions this has
been dead code. It was also added in the wrong place, since it's responsibility
of the JS code to solve the ping-pong problem.
2019-04-17 13:24:42 +02:00
Saúl Ibarra Corretgé
c1f8a35156 doc: add links to the sample SDK applications repo 2019-04-17 09:37:28 +02:00
virtuacoplenny
866dc4dbc6 ref(subtitles): remove logic around dialing transcriber (#4011) 2019-04-16 12:27:17 -07:00
damencho
69a12395d2 Removes debug log and adds safety check whether config exists. 2019-04-16 21:16:38 +02:00
virtuacoplenny
17627291e8 ref(css): use var for desktop drag area margin (#4104) 2019-04-16 11:45:25 -07:00
Hristo Terezov
30669c7699 feat(lib-jitsi-meet): Update version. 2019-04-16 17:05:02 +01:00
Hristo Terezov
4abc2db24a fix(device-selection): Default device change. 2019-04-16 17:05:02 +01:00
Bettenbuk Zoltan
2b4ace75ae [RN] Add connection indicator 2019-04-16 17:33:23 +02:00
Saúl Ibarra Corretgé
3217ef2bb4 ios: make sure symbols are uploaded to TestFlight
While that option should default to true, let's be explicit about it.
2019-04-16 15:43:15 +02:00
Bettenbuk Zoltan
e5caca9cfd [RN] Add display name label to tile view 2019-04-15 18:58:15 +02:00
Bettenbuk Zoltan
42c85c22a9 [RN] rearrange display-name files for later refactor 2019-04-15 18:58:15 +02:00
Leonard Kim
fd0eef4c84 fix(chat): change margins to avoid different background color 2019-04-12 22:39:09 +01:00
Leonard Kim
ab022c62f5 fix(filmstrip): bring down height to avoid electron drag area 2019-04-12 22:39:09 +01:00
Leonard Kim
f9c0c3e2f6 fix(chat): bring down elements to avoid electron drag area 2019-04-12 22:39:09 +01:00
paweldomas
70ec7c5b3d ios: bump travis osx_image to 10.2 2019-04-12 16:16:57 -05:00
virtuacoplenny
ca38bd53fe fix(chat): use css for arrow (#4097) 2019-04-12 13:59:03 -07:00
Leonard Kim
b3cae9a962 fix(chat): allow smiley opener to expand in width
The chat icons are different on windows and mac, with
windows icons being bigger. By settings a specific
width on the smiley container, windows would see
part of the smiley cut off.
2019-04-12 18:29:04 +01:00
Saúl Ibarra Corretgé
b768b88491 android: add ability to override SDK version when releasing 2019-04-12 15:39:29 +02:00
Saúl Ibarra Corretgé
9f339c452b android: raise SDK version 2019-04-12 15:39:29 +02:00
Leonard Kim
c34f9cf233 fix(screenshare): properly gate autopin behavior behind flag check 2019-04-11 09:09:48 -07:00
virtuacoplenny
76642b7c4b feat(screenshare): add auto pin of latest screen share (#4076) 2019-04-11 08:53:34 -07:00
Saúl Ibarra Corretgé
b78989f5f2 android: improve SDK release script
- don't hardcode defaults in gradle files
- allow for uploading also to HTTP URLs
- support HTTP authentication when publishing
2019-04-11 17:43:33 +02:00
virtuacoplenny
088b5d95c2 chore(deps): update lib for listener leak fix (#4084) 2019-04-11 08:00:05 -07:00
virtuacoplenny
c6e5adbe0e fix(large-video): respect update in progress when queuing update (#4078)
When a fade in/out animation is in progress, another large
video update can be queued but can try to force itself onto
large video. For example a pin can be in progress and while
the fade in/out animation plays, local video can change its
video type during the animation and forcing an update of
large video. This results in local video getting forcible
updated onto large video while the pinned video is left on
small video only.
2019-04-10 08:16:02 -07:00
Bettenbuk Zoltan
8bb56be317 [RN] Add conference connecting overlay 2019-04-10 15:47:36 +02:00
Bettenbuk Zoltan
84b917d708 Reorg overlay feature files 2019-04-10 15:47:36 +02:00
Bettenbuk Zoltan
18d908ce84 Fix flow errors from base/connection 2019-04-10 15:47:36 +02:00
Bettenbuk Zoltan
3987655f2a Refactor config loading 2019-04-10 15:47:36 +02:00
Saúl Ibarra Corretgé
ee3b8af4cf ios: remove PiP sample application
It now lives here: https://github.com/jitsi/jitsi-meet-sdk-samples
2019-04-10 15:10:47 +02:00
Saúl Ibarra Corretgé
9625be1db3 misc: don't show a warning on Safari with VP8 2019-04-10 14:15:02 +02:00
Saúl Ibarra Corretgé
21c0745504 android,ios: now working on version 19.2 2019-04-10 14:14:04 +02:00
Saúl Ibarra Corretgé
26c9ee5f9c deps: lib-jitsi-meet@9659b4e413b12c637810fb2ab52354f1357a177e 2019-04-10 12:32:57 +02:00
Saúl Ibarra Corretgé
9b7af64e11 ios: raise SDK version 2019-04-09 16:08:45 +02:00
Saúl Ibarra Corretgé
f26c5570df ios: update sample PiP app
- Xcode 10.2 + Swift 5
- Latest SDK API
- Fix warnings
2019-04-09 16:08:45 +02:00
Saúl Ibarra Corretgé
d37a0eee3a ios: fix compilation warnings 2019-04-09 16:08:45 +02:00
Saúl Ibarra Corretgé
024fc73e63 ios: update to Xcode 5 and Swift 5 2019-04-09 16:08:45 +02:00
Saúl Ibarra Corretgé
bdaabf6d3d odeps: react-native@0.59.4
Fixes a crash on some old Android devices.
2019-04-09 16:08:45 +02:00
virtuacoplenny
7a677ead93 ref(device-selection): set audio output sink id after receiving ref (#4066)
The Audio.js setRef callback does not behave like react ref callback
in that the former will not have fired before componentDidMount
but the later will have. So for audio output preview, trying to set
sink id on mount will no-op because it does not have a ref yet to
Audio.js, possibly leading to audio output previews playing on
the default speaker device. This generally has not been a user
visible problem due to coincidence; other re-renders necessary
by the parent of audio output preview will have triggered
componentDidUpdates on the audio out preview, which would then
set the sink id on the Audio.js ref it should have received
by then.
2019-04-08 10:38:06 -07:00
virtuacoplenny
e7812c7d84 fix(device-selection): search for device by label and kind (#4064)
Searching for a device (id) by label alone can result in
false results when devices share labels, such as a mic
and speaker having the same label. To prevent such,
specify the device kind to be found instead of iterating
over all device kinds.
2019-04-08 10:03:45 -07:00
damencho
ea54713f9a Supports prosody 0.11 when configuring.
Doing few changes needed for general config and for tokens.
2019-04-05 17:18:17 +02:00
virtuacoplenny
5a99697ae2 fix(toolbox): fix typo in action type for hide timeout (#4069) 2019-04-04 10:53:14 -07:00
virtuacoplenny
ec09085a50 fix(device-selection): set audio output device on initial configuration
When the iFrame api is used to set a preferred audio output using
options passed into the JitsiMeetExternalAPI constructor, no logic
fires to actually change the audio output destination.
2019-04-04 08:10:01 -07:00
virtuacoplenny
b731459ea4 fix(device-selection): use device kind when getting current devices (#4059)
Devices of different kinds can have the same id, such as speaker
and mic both being default. Using id only can then lead to
incorrectly setting device descriptions in the current devices
object.
2019-04-03 08:06:41 -07:00
Saúl Ibarra Corretgé
f73d3a4063 ios: add SDK release script 2019-04-03 16:15:11 +02:00
Saúl Ibarra Corretgé
4c3cf8c14a android: add an improved SDK release script
It releases the SDK and all dependencies (including React Native) to the
specified Maven repo.
2019-04-03 16:15:11 +02:00
Saúl Ibarra Corretgé
1f371ab055 android: simplify qualifying dependencies when publishing
Use an ever increasing number so no manual updates are necessary.
2019-04-03 16:15:11 +02:00
Saúl Ibarra Corretgé
dfeb26597b android: make Maven repo used for publising configurable 2019-04-03 16:15:11 +02:00
Saúl Ibarra Corretgé
384f7d7890 ios: update Podfile.lock 2019-04-02 16:18:09 +02:00
Bettenbuk Zoltan
4d9dcf5d43 [RN] Add InfoDialogButton 2019-04-02 16:18:09 +02:00
Saúl Ibarra Corretgé
e217e10af5 android: update custom version for native dependencies 2019-04-02 14:17:45 +02:00
Saúl Ibarra Corretgé
7feec7c11d deps: react-native-sound€0.10.12 2019-04-02 14:17:45 +02:00
Saúl Ibarra Corretgé
36eb27e233 rn: add build information to SettingsView 2019-04-02 12:40:35 +02:00
Bettenbuk Zoltan
b791fc32fd [RN] Make BaseIndicator render simpler 2019-04-01 21:03:36 +02:00
Bettenbuk Zoltan
b1a70240fc Clear raise hand status on confidence leave 2019-04-01 21:03:36 +02:00
Bettenbuk Zoltan
50d7c1521f Remove legacy web raise hand code 2019-04-01 21:03:36 +02:00
Bettenbuk Zoltan
5d9762b429 Extract notification timeout to a constant 2019-04-01 21:03:36 +02:00
Bettenbuk Zoltan
4e78502c9e Generalize indicators 2019-04-01 21:03:36 +02:00
Bettenbuk Zoltan
6ff733dae0 Platform generic notification for raised hand 2019-04-01 21:03:36 +02:00
Bettenbuk Zoltan
2dc59b9ea0 [RN] Add button to toggle raised hand 2019-04-01 21:03:36 +02:00
Bettenbuk Zoltan
e65918564b [RN] Add UI for raised hand feature 2019-04-01 21:03:36 +02:00
Bettenbuk Zoltan
ce9744b9c3 Move participant event handler to a platform generic location 2019-04-01 21:03:36 +02:00
987 changed files with 48164 additions and 24370 deletions

View File

@@ -2,22 +2,27 @@
; We fork some components by platform
.*/*[.]android.js
; Ignore "BUCK" generated dirs
<PROJECT_ROOT>/\.buckd/
; Ignore unexpected extra "@providesModule"
.*/node_modules/.*/node_modules/fbjs/.*
node_modules/react-native/Libraries/react-native/React.js
; Ignore duplicate module providers
; For RN Apps installed via npm, "Libraries" folder is inside
; "node_modules/react-native" but in the source repo it is in the root
.*/Libraries/react-native/React.js
node_modules/react-native/Libraries/react-native/React.js
; Ignore polyfills
.*/Libraries/polyfills/.*
node_modules/react-native/Libraries/polyfills/.*
; Ignore metro
.*/node_modules/metro/.*
; These should not be required directly
; require from fbjs/lib instead: require('fbjs/lib/warning')
node_modules/warning/.*
; Flow doesn't support platforms
.*/Libraries/Utilities/HMRLoadingView.js
[untyped]
.*/node_modules/@react-native-community/cli/.*/.*
; Ignore packages in node_modules which we (i.e. the jitsi-meet project) have
; seen to cause errors and we have chosen not to fix.
@@ -40,6 +45,18 @@ emoji=true
esproposal.optional_chaining=enable
esproposal.nullish_coalescing=enable
; We (i.e. the jitsi-meet project) are using the haste module system on Web as
; well, not only on React Native. Unfortunately, Flow does not support .web.js
; by default. Override Flow's defaults to include .web.js as well. Technically,
; we have .native.js as well so the choice of .web.js may lead to errors.
; Practically though, it is a potential future problem that we do not have at
; the time of this writing.
module.file_ext=.web.js
; Flow's defaults:
module.file_ext=.js
module.file_ext=.json
module.file_ext=.ios.js
module.system=haste
module.system.haste.use_name_reducers=true
# get basename
@@ -52,8 +69,11 @@ module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1'
module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1'
module.system.haste.paths.blacklist=.*/__tests__/.*
module.system.haste.paths.blacklist=.*/__mocks__/.*
module.system.haste.paths.blacklist=<PROJECT_ROOT>/node_modules/react-native/Libraries/Animated/src/polyfills/.*
module.system.haste.paths.whitelist=<PROJECT_ROOT>/node_modules/react-native/Libraries/.*
module.system.haste.paths.whitelist=<PROJECT_ROOT>/node_modules/react-native/RNTester/.*
module.system.haste.paths.whitelist=<PROJECT_ROOT>/node_modules/react-native/IntegrationTests/.*
module.system.haste.paths.blacklist=<PROJECT_ROOT>/node_modules/react-native/Libraries/react-native/react-native-implementation.js
module.system.haste.paths.blacklist=<PROJECT_ROOT>/node_modules/react-native/Libraries/Animated/src/polyfills/.*
munge_underscores=true
@@ -64,22 +84,32 @@ suppress_type=$FlowFixMe
suppress_type=$FlowFixMeProps
suppress_type=$FlowFixMeState
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
; We (i.e. the jitsi-meet project) are using the haste module system on Web as
; well, not only on React Native. Unfortunately, Flow does not support .web.js
; by default. Override Flow's defaults to include .web.js as well. Technically,
; we have .native.js as well so the choice of .web.js may lead to errors.
; Practically though, it is a potential future problem that we do not have at
; the time of this writing.
module.file_ext=.web.js
; Flow's defaults:
module.file_ext=.js
module.file_ext=.jsx
module.file_ext=.json
[lints]
sketchy-null-number=warn
sketchy-null-mixed=warn
sketchy-number=warn
untyped-type-import=warn
nonstrict-import=warn
deprecated-type=warn
unsafe-getters-setters=warn
inexact-spread=warn
unnecessary-invariant=warn
signature-verification-failure=warn
deprecated-utility=error
[strict]
deprecated-type
nonstrict-import
sketchy-null
unclear-type
unsafe-getters-setters
untyped-import
untyped-type-import
[version]
^0.92.0
^0.98.0

1
.gitignore vendored
View File

@@ -73,6 +73,7 @@ buck-out/
# Build artifacts
*.jsbundle
*.framework
android/app/debug
android/app/release
# precommit-hook

View File

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

View File

@@ -45,6 +45,8 @@ deploy-appbundle:
$(OUTPUT_DIR)/analytics-ga.js \
$(BUILD_DIR)/analytics-ga.min.js \
$(BUILD_DIR)/analytics-ga.min.map \
$(BUILD_DIR)/video-blur-effect.min.js \
$(BUILD_DIR)/video-blur-effect.min.map \
$(DEPLOY_DIR)
deploy-lib-jitsi-meet:

View File

@@ -33,7 +33,7 @@ You can get our mobile versions from here:
## Building the sources
Node.js >= 8 and npm >= 6 are required.
Node.js >= 10 and npm >= 6 are required.
On Debian/Ubuntu systems, the required packages can be installed with:
```

View File

@@ -1,8 +1,15 @@
# Jitsi Meet SDK for Android
## Sample applications using the SDK
If you want to see how easy integrating the Jitsi Meet SDK into a native application is, take a look at the
[sample applications repository](https://github.com/jitsi/jitsi-meet-sdk-samples).
## Build your own, or use a pre-build SDK artifacts/binaries
Jitsi conveniently provides a pre-build SDK artifacts/binaries in its Maven repository. When you do not require any modification to the SDK itself, it's suggested to use the pre-build SDK. This avoids the complexity of building and installing your own SDK artifacts/binaries.
Jitsi conveniently provides a pre-build SDK artifacts/binaries in its Maven repository. When you do not require any
modification to the SDK itself or any of its dependencies, it's suggested to use the pre-build SDK. This avoids the
complexity of building and installing your own SDK artifacts/binaries.
### Use pre-build SDK artifacts/binaries
@@ -29,7 +36,7 @@ Dependency definitions belong in the individual module `build.gradle` files:
```gradle
dependencies {
// (other dependencies)
implementation ('org.jitsi.react:jitsi-meet-sdk:+') { transitive = true }
implementation ('org.jitsi.react:jitsi-meet-sdk:2.+') { transitive = true }
}
```
@@ -44,49 +51,20 @@ A note on dependencies: Apart from the SDK, Jitsi also publishes a binary Maven
If you want to use a SDK that is built from source, you will likely benefit from composing a local Maven repository that contains these dependencies. The text below describes how you create a repository that includes both the SDK as well as these dependencies. For illustration purposes, we'll define the location of this local Maven repository as `/tmp/repo`
In source code form, the Android SDK dependencies are locked/pinned by package.json and package-lock.json of the Jitsi Meet project. To obtain the data, execute NPM in the parent directory:
In source code form, the Android SDK dependencies are locked/pinned by package.json and package-lock.json of the Jitsi Meet project. To obtain the data, execute NPM in the jitsi-meet project directory:
$ (cd ..; npm install)
npm install
This will pull in the dependencies in either binary format, or in source code format, somewhere under /node_modules/
At the time of writing, there are two packages pulled in in binary format.
Third-party React Native _modules_, which Jitsi Meet SDK for Android depends on, are download by NPM in source code
or binary form. These need to be assembled into Maven artifacts, and then published to your local Maven repository.
A script is provided to facilitate this. From the root of the jitsi-meet project repository, run:
To copy React Native to your local Maven repository, you can simply copy part of the directory structure that was pulled in by NPM:
./android/scripts/release-sdk.sh /tmp/repo
$ cp -r ../node_modules/react-native/android/com /tmp/repo/
Alternatively, you can use the scripts located in the android/scripts directory to publish these dependencies to your Maven repo.
Third-party React Native _modules_, which Jitsi Meet SDK for Android depends on, are download by NPM in source code form. These need to be assembled into Maven artifacts, and then published to your local Maven repository. The SDK project facilitates this.
To prepare, Configure the Maven repositories in which you are going to publish the SDK artifacts/binaries. In `android/sdk/build.gradle` as well as in `android/build.gradle` modify the lines that contain:
"file:${rootProject.projectDir}/../../jitsi-maven-repository/releases"
Change this value (which represents the Maven repository location used internally by the Jitsi Developers) to the location of the repository that you'd like to use:
"file:/tmp/repo"
Make sure to do this in both files! Each file should require one line to be changed.
To prevent artifacts from previous builds affecting you're outcome, it's good to start with cleaning your work directories:
$ ./gradlew clean
To create the release assembly for any _specific_ third-party React Native module that you need, you can execture the following commands, replace the module name in the examples below.
$ ./gradlew :react-native-webrtc:assembleRelease
$ ./gradlew :react-native-webrtc:publish
You build and publish the SDK itself in the same way:
$ ./gradlew :sdk:assembleRelease
$ ./gradlew :sdk:publish
Alternatively, you can assemble and publish _all_ subprojects, which include the react-native modules, but also the SDK itself, with a single command:
$ ./gradlew clean assembleRelease publish
This will build and publish the SDK, and all of its dependencies to the specified Maven repository (`/tmp/repo`) in
this example.
You're now ready to use the artifacts. In _your_ project, add the Maven repository that you used above (`/tmp/repo`) into your top-level `build.gradle` file:
@@ -104,7 +82,8 @@ Then, define the dependency `org.jitsi.react:jitsi-meet-sdk` into the `build.gra
implementation ('org.jitsi.react:jitsi-meet-sdk:+') { transitive = true }
Note that there should not be a need to explicitly add the other dependencies, as they will be pulled in as transitive dependencies of `jitsi-meet-sdk`.
Note that there should not be a need to explicitly add the other dependencies, as they will be pulled in as transitive
dependencies of `jitsi-meet-sdk`.
</details>
@@ -228,24 +207,6 @@ public class MainActivity extends FragmentActivity implements JitsiMeetActivityI
</details>
Starting with SDK version 1.22, a Glide module must be provided by the host app.
This makes it possible to use the Glide image processing library from both the
SDK and the host app itself.
You can use the code in `JitsiGlideModule.java` and adjust the package name.
When building, add the following code in your `app/build.gradle` file, adjusting
the Glide version to match the one in https://github.com/jitsi/jitsi-meet/blob/master/android/build.gradle
```
// Glide
implementation("com.github.bumptech.glide:glide:${glideVersion}") {
exclude group: "com.android.support", module: "glide"
}
implementation("com.github.bumptech.glide:annotations:${glideVersion}") {
exclude group: "com.android.support", module: "annotations"
}
```
### JitsiMeetActivity
This class encapsulates a high level API in the form of an Android `FragmentActivity`

6
android/app/.classpath Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/>
</classpath>

23
android/app/.project Normal file
View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>app</name>
<comment>Project app created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,2 @@
connection.project.dir=..
eclipse.preferences.version=1

View File

@@ -1,6 +1,7 @@
apply plugin: 'com.android.application'
boolean googleServicesEnabled = project.file('google-services.json').exists()
boolean googleServicesEnabled \
= project.file('google-services.json').exists() && !rootProject.ext.libreBuild
// Crashlytics integration is done as part of Firebase now, so it gets
// automagically activated with google-services.json
@@ -33,14 +34,25 @@ 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}"
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-release.pro'
buildConfigField "boolean", "GOOGLE_SERVICES_ENABLED", "${googleServicesEnabled}"
buildConfigField "boolean", "LIBRE_BUILD", "${rootProject.ext.libreBuild}"
}
}
sourceSets {
main {
java {
if (rootProject.ext.libreBuild) {
srcDir "src"
exclude "**/GoogleServicesHelper.java"
}
}
}
}
@@ -56,30 +68,24 @@ repositories {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "com.android.support:support-v4:${rootProject.ext.supportLibVersion}"
implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
implementation 'com.google.android.gms:play-services-auth:16.0.1'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.appcompat:appcompat:1.0.2'
if (!rootProject.ext.libreBuild) {
implementation 'com.google.android.gms:play-services-auth:16.0.1'
// Firebase
// - Crashlytics
// - Dynamic Links
implementation 'com.google.firebase:firebase-core:16.0.6'
implementation 'com.crashlytics.sdk.android:crashlytics:2.9.8'
implementation 'com.google.firebase:firebase-dynamic-links:16.1.5'
}
implementation project(':sdk')
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.1'
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.1'
// Glide
implementation("com.github.bumptech.glide:glide:${rootProject.ext.glideVersion}") {
exclude group: "com.android.support", module: "glide"
}
implementation("com.github.bumptech.glide:annotations:${rootProject.ext.glideVersion}") {
exclude group: "com.android.support", module: "annotations"
}
annotationProcessor "com.github.bumptech.glide:compiler:${rootProject.ext.glideVersion}"
// Firebase
// - Crashlytics
// - Dynamic Links
implementation 'com.google.firebase:firebase-core:16.0.6'
implementation 'com.crashlytics.sdk.android:crashlytics:2.9.8'
implementation 'com.google.firebase:firebase-dynamic-links:16.1.5'
}
gradle.projectsEvaluated {

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

@@ -9,13 +9,6 @@
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# React Native
# Keep our interfaces so they can be used by other ProGuard rules.
@@ -60,19 +53,9 @@
-keep class sun.misc.Unsafe { *; }
-dontwarn java.nio.file.*
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-keep class okio.** { *; }
-dontwarn okio.**
# FastImage + Glide
-keep public class com.dylanvann.fastimage.* {*;}
-keep public class com.dylanvann.fastimage.** {*;}
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.module.AppGlideModule
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
# WebRTC
-keep class org.webrtc.** { *; }
@@ -80,6 +63,7 @@
# Jisti Meet SDK
-keep class org.jitsi.meet.** { *; }
-keep class org.jitsi.meet.sdk.** { *; }
# We added the following when we switched minifyEnabled on. Probably because we
@@ -99,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

@@ -25,6 +25,7 @@
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:host="alpha.jitsi.net" android:scheme="https" />
<data android:host="beta.meet.jit.si" android:scheme="https" />
<data android:host="meet.jit.si" android:scheme="https" />
</intent-filter>

View File

@@ -0,0 +1,40 @@
package org.jitsi.meet;
import android.net.Uri;
import android.util.Log;
import com.crashlytics.android.Crashlytics;
import com.google.firebase.dynamiclinks.FirebaseDynamicLinks;
import io.fabric.sdk.android.Fabric;
import org.jitsi.meet.sdk.JitsiMeetActivity;
/**
* Helper class to initialize Google related services and functionality.
* This functionality is compiled conditionally and called via reflection, that's why it was
* extracted here.
*
* "Libre builds" (builds with the LIBRE_BUILD flag set) will not include this file.
*/
final class GoogleServicesHelper {
public static void initialize(JitsiMeetActivity activity) {
if (BuildConfig.GOOGLE_SERVICES_ENABLED) {
Log.d(activity.getClass().getSimpleName(), "Initializing Google Services");
Fabric.with(activity, new Crashlytics());
FirebaseDynamicLinks.getInstance().getDynamicLink(activity.getIntent())
.addOnSuccessListener(activity, pendingDynamicLinkData -> {
Uri dynamicLink = null;
if (pendingDynamicLinkData != null) {
dynamicLink = pendingDynamicLinkData.getLink();
}
if (dynamicLink != null) {
activity.join(dynamicLink.toString());
}
});
}
}
}

View File

@@ -1,16 +0,0 @@
package org.jitsi.meet;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.AppGlideModule;
/**
* An AppGlideModule needs to be present for image loading events to work in
* react-native-fast-image. However, if this is defined by the SDK it will cause trouble with
* apps which are using Glide themselves.
*
* In order to avoid the problem, define a Jitsi Glide module here, so applications already using
* it are not in trouble.
*/
@GlideModule
public final class JitsiGlideModule extends AppGlideModule {
}

View File

@@ -21,18 +21,15 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.KeyEvent;
import androidx.annotation.Nullable;
import org.jitsi.meet.sdk.JitsiMeet;
import org.jitsi.meet.sdk.JitsiMeetActivity;
import org.jitsi.meet.sdk.JitsiMeetConferenceOptions;
import com.crashlytics.android.Crashlytics;
import com.google.firebase.dynamiclinks.FirebaseDynamicLinks;
import io.fabric.sdk.android.Fabric;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
@@ -57,22 +54,16 @@ public class MainActivity extends JitsiMeetActivity {
@Override
protected boolean extraInitialize() {
Log.d(this.getClass().getSimpleName(), "LIBRE_BUILD="+BuildConfig.LIBRE_BUILD);
// Setup Crashlytics and Firebase Dynamic Links
if (BuildConfig.GOOGLE_SERVICES_ENABLED) {
Fabric.with(this, new Crashlytics());
FirebaseDynamicLinks.getInstance().getDynamicLink(getIntent())
.addOnSuccessListener(this, pendingDynamicLinkData -> {
Uri dynamicLink = null;
if (pendingDynamicLinkData != null) {
dynamicLink = pendingDynamicLinkData.getLink();
}
if (dynamicLink != null) {
join(dynamicLink.toString());
}
});
// Here we are using reflection since it may have been disabled at compile time.
try {
Class<?> cls = Class.forName("org.jitsi.meet.GoogleServicesHelper");
Method m = cls.getMethod("initialize", JitsiMeetActivity.class);
m.invoke(null, this);
} catch (Exception e) {
// Ignore any error, the module is not compiled when LIBRE_BUILD is enabled.
}
// In Debug builds React needs permission to write over other apps in
@@ -115,7 +106,7 @@ public class MainActivity extends JitsiMeetActivity {
//
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == OVERLAY_PERMISSION_REQUEST_CODE
&& canRequestOverlayPermission()) {
if (Settings.canDrawOverlays(this)) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 960 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#66A8DD</color>
</resources>

View File

@@ -2,5 +2,6 @@
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="android:navigationBarColor">#1081B2</item>
</style>
</resources>

View File

@@ -25,9 +25,10 @@ allprojects {
repositories {
google()
jcenter()
// React Native (JS, Obj-C sources, Android binaries) is installed from
// npm.
// React Native (JS, Obj-C sources, Android binaries) is installed from npm.
maven { url "$rootDir/../node_modules/react-native/android" }
// Android JSC is installed from npm.
maven { url("$rootDir/../node_modules/jsc-android/dist") }
}
// Make sure we use the react-native version in node_modules and not the one
@@ -55,56 +56,40 @@ allprojects {
publishing {
publications {}
repositories {
maven { url "file:${rootProject.projectDir}/../../jitsi-maven-repository/releases" }
maven {
url rootProject.ext.mavenRepo
if (!rootProject.ext.mavenRepo.startsWith("file")) {
credentials {
username rootProject.ext.mavenUser
password rootProject.ext.mavenPassword
}
}
}
}
}
}
// Use the number of seconds/10 since Jan 1 2019 as the version qualifier number.
// This will last for the next ~680 years.
// https://stackoverflow.com/a/38643838
def versionQualifierNumber = (int)(((new Date().getTime()/1000) - 1546297200) / 10)
afterEvaluate { project ->
if (project.plugins.hasPlugin('android') || project.plugins.hasPlugin('android-library')) {
project.android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
}
}
if (project.name.startsWith('react-native-')) {
def npmManifest = project.file('../package.json')
def json = new JsonSlurper().parseText(npmManifest.text)
// React Native modules have an npm peer dependency on react-native,
// they do not have an npm dependency on it. Further below though we
// choose a react-native version (range) when we represent them as
// Maven artifacts. Effectively, we are forking the projects by not
// complying with the full range of their npm peer dependency and,
// consequently, we should qualify their version.
def versionQualifier = '-jitsi-1'
if ('react-native-background-timer' == project.name)
versionQualifier = '-jitsi-3' // 2.0.0 + react-native 0.57
else if ('react-native-calendar-events' == project.name)
versionQualifier = '-jitsi-2' // 1.6.4 + react-native 0.57
else if ('react-native-fast-image' == project.name)
versionQualifier = '-jitsi-2' // 5.1.1 + react-native 0.57
else if ('react-native-google-signin' == project.name)
versionQualifier = '-jitsi-2' // 1.0.2 + react-native 0.57
else if ('react-native-immersive' == project.name)
versionQualifier = '-jitsi-5' // 2.0.0 + react-native 0.57
else if ('react-native-keep-awake' == project.name)
versionQualifier = '-jitsi-4' // 4.0.0 + react-native 0.57
else if ('react-native-linear-gradient' == project.name)
versionQualifier = '-jitsi-1' // 2.4.0 + react-native 0.57
else if ('react-native-sound' == project.name)
versionQualifier = '-jitsi-2' // 0.10.9 + react-native 0.57
else if ('react-native-vector-icons' == project.name)
versionQualifier = '-jitsi-3' // 6.0.2 + react-native 0.57
else if ('react-native-webrtc' == project.name)
versionQualifier = '-jitsi-9' // 6322a9b5a38ce590cfaea4041072ea87c8dbf558 + react-native 0.57
// Release every dependency the SDK has with a -jitsi-XXX qualified version. This allows
// us to pin the dependencies and make sure they are always updated, no matter what.
project.version = "${json.version}${versionQualifier}"
project.android {
compileSdkVersion rootProject.ext.compileSdkVersion
if (rootProject.ext.has('buildToolsVersion')) {
buildToolsVersion rootProject.ext.buildToolsVersion
}
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
}
}
project.version = "${json.version}-jitsi-${versionQualifierNumber}"
task androidSourcesJar(type: Jar) {
classifier = 'sources'
@@ -171,9 +156,13 @@ ext {
// of ours.
moduleGroupId = 'com.facebook.react'
// Glide
excludeAppGlideModule = true
glideVersion = "4.7.1" // keep in sync with react-native-fast-image
// Maven repo where artifacts will be published
mavenRepo = System.env.MVN_REPO ?: ""
mavenUser = System.env.MVN_USER ?: ""
mavenPassword = System.env.MVN_PASSWORD ?: ""
// Libre build
libreBuild = (System.env.LIBRE_BUILD ?: "false").toBoolean()
}
// If Android SDK is not installed, accept its license so that it

View File

@@ -17,5 +17,8 @@
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
appVersion=19.1.0
sdkVersion=2.0.0
android.useAndroidX=true
android.enableJetifier=true
appVersion=19.3.1
sdkVersion=2.3.2

View File

@@ -1,19 +0,0 @@
#!/bin/bash
CWD=$(dirname $0)
MVN_REPO=$(realpath $1)
RN_VERSION=$(jq -r '.dependencies."react-native"' ${CWD}/../../package.json)
pushd ${CWD}/../../node_modules/react-native/android/com/facebook/react/react-native/${RN_VERSION}
mvn \
deploy:deploy-file \
-Durl=file://${MVN_REPO} \
-Dfile=react-native-${RN_VERSION}.aar \
-Dpackaging=aar \
-Dsources=react-native-${RN_VERSION}-sources.jar \
-Djavadoc=react-native-${RN_VERSION}-javadoc.jar \
-DgeneratePom=false \
-DpomFile=react-native-${RN_VERSION}.pom
popd

107
android/scripts/release-sdk.sh Executable file
View File

@@ -0,0 +1,107 @@
#!/bin/bash
set -e -u
THIS_DIR=$(cd -P "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOURCE[0]}")")" && pwd)
DEFAULT_MVN_REPO="${THIS_DIR}/../../../jitsi-maven-repository/releases"
THE_MVN_REPO=${MVN_REPO:-${1:-$DEFAULT_MVN_REPO}}
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)
DO_GIT_TAG=${GIT_TAG:-0}
if [[ $THE_MVN_REPO == http* ]]; then
MVN_HTTP=1
else
MVN_REPO_PATH=$(realpath $THE_MVN_REPO)
THE_MVN_REPO="file:${MVN_REPO_PATH}"
fi
export MVN_REPO=$THE_MVN_REPO
echo "Releasing Jitsi Meet SDK ${SDK_VERSION}"
echo "Using ${MVN_REPO} as the Maven repo"
if [[ $MVN_HTTP == 1 ]]; then
# Push React Native
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}
mvn \
deploy:deploy-file \
-Durl=${MVN_REPO} \
-DrepositoryId=${MVN_REPO_ID} \
-Dfile=react-native-${RN_VERSION}.aar \
-Dpackaging=aar \
-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
# 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}
mvn \
deploy:deploy-file \
-Durl=${MVN_REPO} \
-Dfile=react-native-${RN_VERSION}.aar \
-Dpackaging=aar \
-DgeneratePom=false \
-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
echo "Building and publishing the Jitsi Meet SDK"
pushd ${THIS_DIR}/../
./gradlew clean assembleRelease publish
popd
if [[ $DO_GIT_TAG == 1 ]]; then
# The artifacts are now on the Maven repo, commit them
pushd ${MVN_REPO_PATH}
git add -A .
git commit -m "Jitsi Meet SDK + dependencies: ${SDK_VERSION}"
popd
# Tag the release
git tag android-sdk-${SDK_VERSION}
fi
# Done!
echo "Finished! Don't forget to push the tag and the Maven repo artifacts."

View File

@@ -8,6 +8,8 @@ THIS_DIR=$(cd -P "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOUR
export RCT_METRO_PORT="${RCT_METRO_PORT:=8081}"
echo "export RCT_METRO_PORT=${RCT_METRO_PORT}" > "${THIS_DIR}/../../node_modules/react-native/scripts/.packager.env"
adb reverse tcp:8081 tcp:8081
if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then
if ! curl -s "http://localhost:${RCT_METRO_PORT}/status" | grep -q "packager-status:running" ; then
echo "Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly"

6
android/sdk/.classpath Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/>
</classpath>

23
android/sdk/.project Normal file
View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>sdk</name>
<comment>Project sdk created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,2 @@
connection.project.dir=..
eclipse.preferences.version=1

View File

@@ -10,10 +10,25 @@ android {
}
buildTypes {
debug {}
debug {
buildConfigField "boolean", "LIBRE_BUILD", "${rootProject.ext.libreBuild}"
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField "boolean", "LIBRE_BUILD", "${rootProject.ext.libreBuild}"
}
}
sourceSets {
main {
java {
if (rootProject.ext.libreBuild) {
srcDir "src"
exclude "**/AmplitudeModule.java"
}
exclude "test/"
}
}
}
}
@@ -21,28 +36,35 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "com.android.support:support-v4:${rootProject.ext.supportLibVersion}"
implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.fragment:fragment:1.0.0'
implementation 'com.amplitude:android-sdk:2.14.1'
implementation 'com.dropbox.core:dropbox-core-sdk:3.0.8'
api 'com.facebook.react:react-native:+'
implementation 'org.webkit:android-jsc:+'
implementation 'com.dropbox.core:dropbox-core-sdk:3.0.8'
implementation 'com.jakewharton.timber:timber:4.7.1'
if (!rootProject.ext.libreBuild) {
implementation 'com.amplitude:android-sdk:2.14.1'
implementation(project(":react-native-google-signin")) {
exclude group: 'com.google.android.gms'
exclude group: 'androidx'
}
}
implementation project(':react-native-background-timer')
implementation project(':react-native-calendar-events')
implementation(project(':react-native-fast-image')) {
exclude group: 'com.android.support'
}
implementation(project(":react-native-google-signin")) {
exclude group: 'com.google.android.gms'
exclude group: 'com.android.support'
}
implementation project(':react-native-community-async-storage')
implementation project(':react-native-community_netinfo')
implementation project(':react-native-immersive')
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')
testImplementation 'junit:junit:4.12'
}
@@ -118,19 +140,14 @@ 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 {
from("${projectDir}/../../sounds/incomingMessage.wav")
from("${projectDir}/../../sounds/joined.wav")
from("${projectDir}/../../sounds/left.wav")
from("${projectDir}/../../sounds/liveStreamingOn.mp3")
from("${projectDir}/../../sounds/liveStreamingOff.mp3")
from("${projectDir}/../../sounds/outgoingRinging.wav")
from("${projectDir}/../../sounds/outgoingStart.wav")
from("${projectDir}/../../sounds/recordingOn.mp3")
@@ -167,7 +184,7 @@ publishing {
aarArchive(MavenPublication) {
groupId 'org.jitsi.react'
artifactId 'jitsi-meet-sdk'
version project.sdkVersion
version System.env.OVERRIDE_SDK_VERSION ?: project.sdkVersion
artifact("${project.buildDir}/outputs/aar/${project.name}-release.aar") {
extension "aar"
@@ -186,8 +203,7 @@ publishing {
def groupId = it.moduleGroup
def artifactId = it.moduleName
if (artifactId.startsWith('react-native-')
&& groupId.equals('jitsi-meet')) {
if (artifactId.startsWith('react-native-') && groupId.equals('jitsi-meet')) {
groupId = rootProject.ext.moduleGroupId
}
@@ -201,6 +217,14 @@ publishing {
}
repositories {
maven { url "file:${rootProject.projectDir}/../../jitsi-maven-repository/releases" }
maven {
url rootProject.ext.mavenRepo
if (!rootProject.ext.mavenRepo.startsWith("file")) {
credentials {
username rootProject.ext.mavenUser
password rootProject.ext.mavenPassword
}
}
}
}
}

View File

@@ -12,6 +12,7 @@
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-feature
android:glEsVersion="0x00020000"
@@ -44,6 +45,8 @@
<action android:name="android.telecom.ConnectionService" />
</intent-filter>
</service>
<service android:name="org.jitsi.meet.sdk.JitsiMeetOngoingConferenceService" />
</application>
</manifest>

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;
@@ -52,6 +53,17 @@ class AmplitudeModule
Amplitude.getInstance(instanceName).initialize(getCurrentActivity(), apiKey);
}
/**
* Sets the user ID for an Amplitude instance.
*
* @param instanceName The name of the Amplitude instance.
* @param userId The new value for the user ID.
*/
@ReactMethod
public void setUserId(String instanceName, String userId) {
Amplitude.getInstance(instanceName).setUserId(userId);
}
/**
* Sets the user properties for an Amplitude instance.
*
@@ -79,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

@@ -64,6 +64,9 @@ class AppInfoModule
Map<String, Object> constants = new HashMap<>();
constants.put(
"buildNumber",
packageInfo == null ? "" : String.valueOf(packageInfo.versionCode));
constants.put(
"name",
applicationInfo == null
@@ -72,6 +75,7 @@ class AppInfoModule
constants.put(
"version",
packageInfo == null ? "" : packageInfo.versionName);
constants.put("LIBRE_BUILD", BuildConfig.LIBRE_BUILD);
return constants;
}

View File

@@ -25,8 +25,7 @@ import android.content.pm.PackageManager;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.Log;
import androidx.annotation.RequiresApi;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
@@ -37,6 +36,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;
@@ -121,7 +122,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
case DEVICE_SPEAKER:
return android.telecom.CallAudioState.ROUTE_SPEAKER;
default:
Log.e(TAG, "Unsupported device name: " + audioDevice);
JitsiMeetLogger.e(TAG + " Unsupported device name: " + audioDevice);
return android.telecom.CallAudioState.ROUTE_EARPIECE;
}
}
@@ -218,7 +219,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
}
availableDevices = devices;
Log.d(TAG, "Available audio devices: " +
JitsiMeetLogger.i(TAG + " Available audio devices: " +
availableDevices.toString());
// Reset user selection
@@ -230,19 +231,6 @@ class AudioModeModule extends ReactContextBaseJavaModule
}
};
/**
* {@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);
}
}
};
/**
* Audio mode currently in use.
*/
@@ -256,6 +244,11 @@ class AudioModeModule extends ReactContextBaseJavaModule
private static final String DEVICE_HEADPHONES = "HEADPHONES";
private static final String DEVICE_SPEAKER = "SPEAKER";
/**
* Device change event.
*/
private static final String DEVICE_CHANGE_EVENT = "org.jitsi.meet:features/audio-mode#devices-update";
/**
* List of currently available audio devices.
*/
@@ -303,7 +296,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Do an initial detection on Android >= M.
runInAudioThread(onAudioDeviceChangeRunner);
onAudioDeviceChange();
} else {
// On Android < M, detect if we have an earpiece.
PackageManager pm = reactContext.getPackageManager();
@@ -327,6 +320,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
public Map<String, Object> getConstants() {
Map<String, Object> constants = new HashMap<>();
constants.put("DEVICE_CHANGE_EVENT", DEVICE_CHANGE_EVENT);
constants.put("AUDIO_CALL", AUDIO_CALL);
constants.put("DEFAULT", DEFAULT);
constants.put("VIDEO_CALL", VIDEO_CALL);
@@ -335,31 +329,26 @@ class AudioModeModule extends ReactContextBaseJavaModule
}
/**
* Gets the list of available audio device categories, i.e. 'bluetooth',
* 'earpiece ', 'speaker', 'headphones'.
*
* @param promise a {@link Promise} which will be resolved with an object
* containing a 'devices' key with a list of devices, plus a
* 'selected' key with the selected one.
* Notifies JS land that the devices list has changed.
*/
@ReactMethod
public void getAudioDevices(final Promise promise) {
private void notifyDevicesChanged() {
runInAudioThread(new Runnable() {
@Override
public void run() {
WritableMap map = Arguments.createMap();
map.putString("selected", selectedDevice);
WritableArray devices = Arguments.createArray();
WritableArray data = Arguments.createArray();
final boolean hasHeadphones = availableDevices.contains(DEVICE_HEADPHONES);
for (String device : availableDevices) {
if (mode == VIDEO_CALL && device.equals(DEVICE_EARPIECE)) {
// Skip earpiece when in video call mode.
if (hasHeadphones && device.equals(DEVICE_EARPIECE)) {
// Skip earpiece when headphones are plugged in.
continue;
}
devices.pushString(device);
WritableMap deviceInfo = Arguments.createMap();
deviceInfo.putString("type", device);
deviceInfo.putBoolean("selected", device.equals(selectedDevice));
data.pushMap(deviceInfo);
}
map.putArray("devices", devices);
promise.resolve(map);
ReactInstanceManagerHolder.emitEvent(DEVICE_CHANGE_EVENT, data);
JitsiMeetLogger.i(TAG + " Updating audio device list");
}
});
}
@@ -442,8 +431,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
if (audioDevicesChanged) {
supportedRouteMask = newSupportedRoutes;
availableDevices = routesToDeviceNames(supportedRouteMask);
Log.d(TAG,
"Available audio devices: "
JitsiMeetLogger.i(TAG + " Available audio devices: "
+ availableDevices.toString());
}
@@ -477,7 +465,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN: {
Log.d(TAG, "Audio focus gained");
JitsiMeetLogger.d(TAG + " Audio focus gained");
// Some other application potentially stole our audio focus
// temporarily. Restore our mode.
if (audioFocusLost) {
@@ -489,7 +477,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
case AudioManager.AUDIOFOCUS_LOSS:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: {
Log.d(TAG, "Audio focus lost");
JitsiMeetLogger.d(TAG + " Audio focus lost");
audioFocusLost = true;
break;
}
@@ -516,13 +504,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);
}
@@ -584,7 +572,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
return;
}
Runnable r = new Runnable() {
runInAudioThread(new Runnable() {
@Override
public void run() {
boolean success;
@@ -593,10 +581,7 @@ 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;
@@ -607,8 +592,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
"Failed to set audio mode to " + mode);
}
}
};
runInAudioThread(r);
});
}
/**
@@ -633,14 +617,14 @@ class AudioModeModule extends ReactContextBaseJavaModule
@Override
public void onAudioDevicesAdded(
AudioDeviceInfo[] addedDevices) {
Log.d(TAG, "Audio devices added");
JitsiMeetLogger.d(TAG + " Audio devices added");
onAudioDeviceChange();
}
@Override
public void onAudioDevicesRemoved(
AudioDeviceInfo[] removedDevices) {
Log.d(TAG, "Audio devices removed");
JitsiMeetLogger.d(TAG + " Audio devices removed");
onAudioDeviceChange();
}
};
@@ -659,7 +643,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
BroadcastReceiver wiredHeadsetReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Wired headset added / removed");
JitsiMeetLogger.d(TAG + " Wired headset added / removed");
onHeadsetDeviceChange();
}
};
@@ -677,7 +661,7 @@ 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 (mode == DEFAULT) {
if (!useConnectionService()) {
@@ -690,6 +674,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
selectedDevice = null;
userSelectedDevice = null;
notifyDevicesChanged();
return true;
}
@@ -702,13 +687,12 @@ class AudioModeModule extends ReactContextBaseJavaModule
AudioManager.STREAM_VOICE_CALL,
AudioManager.AUDIOFOCUS_GAIN)
== AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
Log.d(TAG, "Audio focus request failed");
JitsiMeetLogger.w(TAG + " Audio focus request failed");
return false;
}
}
boolean bluetoothAvailable = availableDevices.contains(DEVICE_BLUETOOTH);
boolean earpieceAvailable = availableDevices.contains(DEVICE_EARPIECE);
boolean headsetAvailable = availableDevices.contains(DEVICE_HEADPHONES);
// Pick the desired device based on what's available and the mode.
@@ -717,8 +701,6 @@ class AudioModeModule extends ReactContextBaseJavaModule
audioDevice = DEVICE_BLUETOOTH;
} else if (headsetAvailable) {
audioDevice = DEVICE_HEADPHONES;
} else if (mode == AUDIO_CALL && earpieceAvailable) {
audioDevice = DEVICE_EARPIECE;
} else {
audioDevice = DEVICE_SPEAKER;
}
@@ -736,7 +718,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
}
selectedDevice = audioDevice;
Log.d(TAG, "Selected audio device: " + audioDevice);
JitsiMeetLogger.i(TAG + " Selected audio device: " + audioDevice);
if (useConnectionService()) {
setAudioRoute(audioDevice);
@@ -744,6 +726,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
setAudioRoutePreO(audioDevice);
}
notifyDevicesChanged();
return true;
}
}

View File

@@ -20,15 +20,16 @@ package org.jitsi.meet.sdk;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.facebook.react.ReactRootView;
import com.facebook.react.bridge.ReadableMap;
import com.rnimmersive.RNImmersiveModule;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -77,6 +78,15 @@ public abstract class BaseReactView<ListenerT>
return null;
}
/**
* Gets all registered React views.
*
* @return An {@link ArrayList} containing all views currently held by React.
*/
static ArrayList<BaseReactView> getViews() {
return new ArrayList<>(views);
}
/**
* The unique identifier of this {@code BaseReactView} within the process
* for the purposes of {@link ExternalAPIModule}. The name scope was
@@ -101,8 +111,7 @@ public abstract class BaseReactView<ListenerT>
setBackgroundColor(BACKGROUND_COLOR);
ReactInstanceManagerHolder.initReactInstanceManager(
((Activity) context).getApplication());
ReactInstanceManagerHolder.initReactInstanceManager((Activity)context);
// Hook this BaseReactView into ExternalAPI.
externalAPIScope = UUID.randomUUID().toString();

View File

@@ -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
@@ -77,7 +78,7 @@ class BluetoothHeadsetMonitor {
= (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
if (!audioManager.isBluetoothScoAvailableOffCall()) {
Log.w(AudioModeModule.TAG, "Bluetooth SCO is not available");
JitsiMeetLogger.w(AudioModeModule.TAG + " Bluetooth SCO is not available");
return;
}
@@ -93,7 +94,7 @@ class BluetoothHeadsetMonitor {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter == null) {
Log.w(AudioModeModule.TAG, "Device doesn't support Bluetooth");
JitsiMeetLogger.w(AudioModeModule.TAG + " Device doesn't support Bluetooth");
return false;
}
@@ -148,9 +149,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(AudioModeModule.TAG + " BT headset connection state changed: " + state);
updateDevices();
break;
}
@@ -164,9 +163,7 @@ class BluetoothHeadsetMonitor {
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(AudioModeModule.TAG + " BT SCO connection state changed: " + state);
updateDevices();
break;
}

View File

@@ -5,7 +5,6 @@ import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.telecom.CallAudioState;
import android.telecom.Connection;
import android.telecom.ConnectionRequest;
@@ -14,12 +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;
@@ -63,6 +64,16 @@ public class ConnectionService extends android.telecom.ConnectionService {
static private final HashMap<String, Promise> startCallPromises
= new HashMap<>();
/**
* Aborts all ongoing connections. This is a last resort mechanism which forces all resources to
* be freed on the system in case of fatal error.
*/
static void abortConnections() {
for (ConnectionImpl connection: getConnections()) {
connection.onAbort();
}
}
/**
* Adds {@link ConnectionImpl} to the list.
*
@@ -119,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);
}
}
@@ -152,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);
}
}
@@ -184,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);
}
}
@@ -228,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;
@@ -258,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);
@@ -268,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);
@@ -285,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");
}
}
@@ -347,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(
@@ -367,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(
@@ -385,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();
}
@@ -400,7 +402,7 @@ public class ConnectionService extends android.telecom.ConnectionService {
*/
@Override
public void onCallAudioStateChanged(CallAudioState state) {
Log.d(TAG, "onCallAudioStateChanged: " + state);
JitsiMeetLogger.d(TAG + " onCallAudioStateChanged: " + state);
AudioModeModule audioModeModule
= ReactInstanceManagerHolder
.getNativeModule(AudioModeModule.class);
@@ -416,10 +418,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.
*/
@@ -67,16 +67,20 @@ class ExternalAPIModule
*/
@ReactMethod
public void sendEvent(String name, ReadableMap data, String scope) {
// Keep track of the current ongoing conference.
OngoingConferenceTracker.getInstance().onExternalAPIEvent(name, data);
// The JavaScript App needs to provide uniquely identifying information
// to the native ExternalAPI module so that the latter may match the
// former to the native BaseReactView which hosts it.
BaseReactView view = BaseReactView.findViewByExternalAPIScope(scope);
if (view != null) {
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

@@ -36,6 +36,15 @@ public class JitsiMeet {
defaultConferenceOptions = options;
}
/**
* Returns the current conference URL as a string.
*
* @return the current conference URL.
*/
public static String getCurrentConference() {
return OngoingConferenceTracker.getInstance().getCurrentConference();
}
/**
* Helper to get the default conference options as a {@link Bundle}.
*

View File

@@ -20,12 +20,13 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
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;
@@ -38,8 +39,8 @@ public class JitsiMeetActivity extends FragmentActivity
protected static final String TAG = JitsiMeetActivity.class.getSimpleName();
public static final String ACTION_JITSI_MEET_CONFERENCE = "org.jitsi.meet.CONFERENCE";
public static final String JITSI_MEET_CONFERENCE_OPTIONS = "JitsiMeetConferenceOptions";
private static final String ACTION_JITSI_MEET_CONFERENCE = "org.jitsi.meet.CONFERENCE";
private static final String JITSI_MEET_CONFERENCE_OPTIONS = "JitsiMeetConferenceOptions";
// Helpers for starting the activity
//
@@ -71,9 +72,27 @@ public class JitsiMeetActivity extends FragmentActivity
}
}
@Override
public void onDestroy() {
// Here we are trying to handle the following corner case: an application using the SDK
// is using this Activity for displaying meetings, but there is another "main" Activity
// with other content. If this Activity is "swiped out" from the recent list we will get
// Activity#onDestroy() called without warning. At this point we can try to leave the
// current meeting, but when our view is detached from React the JS <-> Native bridge won't
// be operational so the external API won't be able to notify the native side that the
// conference terminated. Thus, try our best to clean up.
leave();
if (AudioModeModule.useConnectionService()) {
ConnectionService.abortConnections();
}
JitsiMeetOngoingConferenceService.abort(this);
super.onDestroy();
}
@Override
public void finish() {
getJitsiView().leave();
leave();
super.finish();
}
@@ -87,7 +106,7 @@ public class JitsiMeetActivity extends FragmentActivity
return fragment.getJitsiView();
}
protected void join(@Nullable String url) {
public void join(@Nullable String url) {
JitsiMeetConferenceOptions options
= new JitsiMeetConferenceOptions.Builder()
.setRoom(url)
@@ -95,10 +114,14 @@ public class JitsiMeetActivity extends FragmentActivity
join(options);
}
protected void join(JitsiMeetConferenceOptions options) {
public void join(JitsiMeetConferenceOptions options) {
getJitsiView().join(options);
}
public void leave() {
getJitsiView().leave();
}
private @Nullable JitsiMeetConferenceOptions getConferenceOptions(Intent intent) {
String action = intent.getAction();
@@ -139,6 +162,11 @@ public class JitsiMeetActivity extends FragmentActivity
// Activity lifecycle methods
//
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
JitsiMeetActivityDelegate.onActivityResult(this, requestCode, resultCode, data);
}
@Override
public void onBackPressed() {
JitsiMeetActivityDelegate.onBackPressed();
@@ -146,6 +174,8 @@ public class JitsiMeetActivity extends FragmentActivity
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
JitsiMeetConferenceOptions options;
if ((options = getConferenceOptions(intent)) != null) {
@@ -179,17 +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

@@ -25,6 +25,7 @@ import android.os.Build;
import com.calendarevents.CalendarEventsPackage;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.modules.core.PermissionListener;
/**
@@ -40,6 +41,15 @@ public class JitsiMeetActivityDelegate {
private static PermissionListener permissionListener;
private static Callback permissionsCallback;
/**
* Tells whether or not the permissions request is currently in progress.
*
* @return {@code true} if the permssions are being requested or {@code false} otherwise.
*/
static boolean arePermissionsBeingRequested() {
return permissionListener != null;
}
/**
* {@link Activity} lifecycle method which should be called from
* {@code Activity#onActivityResult} so we are notified about results of external intents
@@ -108,7 +118,13 @@ public class JitsiMeetActivityDelegate {
= ReactInstanceManagerHolder.getReactInstanceManager();
if (reactInstanceManager != null) {
reactInstanceManager.onHostPause(activity);
// Try to avoid a crash because some devices trip on this assert:
// 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 (reactContext != null && activity == reactContext.getCurrentActivity()) {
reactInstanceManager.onHostPause(activity);
}
}
}

View File

@@ -1,6 +1,6 @@
package org.jitsi.meet.sdk;
import android.support.v4.app.ActivityCompat;
import androidx.core.app.ActivityCompat;
import com.facebook.react.modules.core.PermissionAwareActivity;

View File

@@ -40,6 +40,10 @@ public class JitsiMeetConferenceOptions implements Parcelable {
* Room name.
*/
private String room;
/**
* Conference subject.
*/
private String subject;
/**
* JWT token used for authentication.
*/
@@ -50,6 +54,11 @@ public class JitsiMeetConferenceOptions implements Parcelable {
*/
private Bundle colorScheme;
/**
* Feature flags. See: https://github.com/jitsi/jitsi-meet/blob/master/react/features/base/flags/constants.js
*/
private Bundle featureFlags;
/**
* Set to {@code true} to join the conference with audio / video muted or to start in audio
* only mode respectively.
@@ -59,10 +68,9 @@ public class JitsiMeetConferenceOptions implements Parcelable {
private Boolean videoMuted;
/**
* Set to {@code true} to enable the welcome page. Typically SDK users won't need this enabled
* since the host application decides which meeting to join.
* USer information, to be used when no token is specified.
*/
private Boolean welcomePageEnabled;
private JitsiMeetUserInfo userInfo;
/**
* Class used to build the immutable {@link JitsiMeetConferenceOptions} object.
@@ -70,17 +78,20 @@ public class JitsiMeetConferenceOptions implements Parcelable {
public static class Builder {
private URL serverURL;
private String room;
private String subject;
private String token;
private Bundle colorScheme;
private Bundle featureFlags;
private Boolean audioMuted;
private Boolean audioOnly;
private Boolean videoMuted;
private Boolean welcomePageEnabled;
private JitsiMeetUserInfo userInfo;
public Builder() {
featureFlags = new Bundle();
}
/**\
@@ -105,6 +116,17 @@ public class JitsiMeetConferenceOptions implements Parcelable {
return this;
}
/**
* Sets the conference subject.
* @param subject - Subject for the conference.
* @return - The {@link Builder} object itself so the method calls can be chained.
*/
public Builder setSubject(String subject) {
this.subject = subject;
return this;
}
/**
* Sets the JWT token to be used for authentication when joining a conference.
* @param token - The JWT token to be used for authentication.
@@ -170,7 +192,31 @@ public class JitsiMeetConferenceOptions implements Parcelable {
* @return - The {@link Builder} object itself so the method calls can be chained.
*/
public Builder setWelcomePageEnabled(boolean enabled) {
this.welcomePageEnabled = enabled;
this.featureFlags.putBoolean("welcomepage.enabled", enabled);
return this;
}
public Builder setFeatureFlag(String flag, boolean value) {
this.featureFlags.putBoolean(flag, value);
return this;
}
public Builder setFeatureFlag(String flag, String value) {
this.featureFlags.putString(flag, value);
return this;
}
public Builder setFeatureFlag(String flag, int value) {
this.featureFlags.putInt(flag, value);
return this;
}
public Builder setUserInfo(JitsiMeetUserInfo userInfo) {
this.userInfo = userInfo;
return this;
}
@@ -185,12 +231,14 @@ public class JitsiMeetConferenceOptions implements Parcelable {
options.serverURL = this.serverURL;
options.room = this.room;
options.subject = this.subject;
options.token = this.token;
options.colorScheme = this.colorScheme;
options.featureFlags = this.featureFlags;
options.audioMuted = this.audioMuted;
options.audioOnly = this.audioOnly;
options.videoMuted = this.videoMuted;
options.welcomePageEnabled = this.welcomePageEnabled;
options.userInfo = this.userInfo;
return options;
}
@@ -201,32 +249,33 @@ public class JitsiMeetConferenceOptions implements Parcelable {
private JitsiMeetConferenceOptions(Parcel in) {
room = in.readString();
subject = in.readString();
token = in.readString();
colorScheme = in.readBundle();
featureFlags = in.readBundle();
userInfo = new JitsiMeetUserInfo(in.readBundle());
byte tmpAudioMuted = in.readByte();
audioMuted = tmpAudioMuted == 0 ? null : tmpAudioMuted == 1;
byte tmpAudioOnly = in.readByte();
audioOnly = tmpAudioOnly == 0 ? null : tmpAudioOnly == 1;
byte tmpVideoMuted = in.readByte();
videoMuted = tmpVideoMuted == 0 ? null : tmpVideoMuted == 1;
byte tmpWelcomePageEnabled = in.readByte();
welcomePageEnabled = tmpWelcomePageEnabled == 0 ? null : tmpWelcomePageEnabled == 1;
}
Bundle asProps() {
Bundle props = new Bundle();
// Android always has the PiP flag set by default.
if (!featureFlags.containsKey("pip.enabled")) {
featureFlags.putBoolean("pip.enabled", true);
}
props.putBundle("flags", featureFlags);
if (colorScheme != null) {
props.putBundle("colorScheme", colorScheme);
}
if (welcomePageEnabled != null) {
props.putBoolean("welcomePageEnabled", welcomePageEnabled);
}
// TODO: get rid of this.
props.putBoolean("pictureInPictureEnabled", true);
Bundle config = new Bundle();
if (audioMuted != null) {
@@ -238,6 +287,9 @@ public class JitsiMeetConferenceOptions implements Parcelable {
if (videoMuted != null) {
config.putBoolean("startWithVideoMuted", videoMuted);
}
if (subject != null) {
config.putString("subject", subject);
}
Bundle urlProps = new Bundle();
@@ -257,6 +309,10 @@ public class JitsiMeetConferenceOptions implements Parcelable {
urlProps.putString("jwt", token);
}
if (token == null && userInfo != null) {
props.putBundle("userInfo", userInfo.asBundle());
}
urlProps.putBundle("config", config);
props.putBundle("url", urlProps);
@@ -281,12 +337,14 @@ public class JitsiMeetConferenceOptions implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(room);
dest.writeString(subject);
dest.writeString(token);
dest.writeBundle(colorScheme);
dest.writeBundle(featureFlags);
dest.writeBundle(userInfo != null ? userInfo.asBundle() : new Bundle());
dest.writeByte((byte) (audioMuted == null ? 0 : audioMuted ? 1 : 2));
dest.writeByte((byte) (audioOnly == null ? 0 : audioOnly ? 1 : 2));
dest.writeByte((byte) (videoMuted == null ? 0 : videoMuted ? 1 : 2));
dest.writeByte((byte) (welcomePageEnabled == null ? 0 : welcomePageEnabled ? 1 : 2));
}
@Override

View File

@@ -19,15 +19,14 @@ package org.jitsi.meet.sdk;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.net.URL;
/**
* Base {@link Fragment} for applications integrating Jitsi Meet at a higher level. It
* contains all the required wiring between the {@code JitsiMeetView} and

View File

@@ -0,0 +1,121 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jitsi.meet.sdk;
import android.app.Notification;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
/**
* This class implements an Android {@link Service}, a foreground one specifically, and it's
* responsible for presenting an ongoing notification when a conference is in progress.
* The service will help keep the app running while in the background.
*
* See: https://developer.android.com/guide/components/services
*/
public class JitsiMeetOngoingConferenceService extends Service
implements OngoingConferenceTracker.OngoingConferenceListener {
private static final String TAG = JitsiMeetOngoingConferenceService.class.getSimpleName();
static final class Actions {
static final String START = TAG + ":START";
static final String HANGUP = TAG + ":HANGUP";
}
static void launch(Context context) {
OngoingNotification.createOngoingConferenceNotificationChannel();
Intent intent = new Intent(context, JitsiMeetOngoingConferenceService.class);
intent.setAction(Actions.START);
ComponentName componentName;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
componentName = context.startForegroundService(intent);
} else {
componentName = context.startService(intent);
}
if (componentName == null) {
JitsiMeetLogger.w(TAG + " Ongoing conference service not started");
}
}
static void abort(Context context) {
Intent intent = new Intent(context, JitsiMeetOngoingConferenceService.class);
context.stopService(intent);
}
@Override
public void onCreate() {
super.onCreate();
OngoingConferenceTracker.getInstance().addListener(this);
}
@Override
public void onDestroy() {
OngoingConferenceTracker.getInstance().removeListener(this);
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
final String action = intent.getAction();
if (action.equals(Actions.START)) {
Notification notification = OngoingNotification.buildOngoingConferenceNotification();
if (notification == null) {
stopSelf();
JitsiMeetLogger.w(TAG + " Couldn't start service, notification is null");
} else {
startForeground(OngoingNotification.NOTIFICATION_ID, notification);
JitsiMeetLogger.i(TAG + " Service started");
}
} else if (action.equals(Actions.HANGUP)) {
JitsiMeetLogger.i(TAG + " Hangup requested");
// Abort all ongoing calls
if (AudioModeModule.useConnectionService()) {
ConnectionService.abortConnections();
}
stopSelf();
} else {
JitsiMeetLogger.w(TAG + " Unknown action received: " + action);
stopSelf();
}
return START_NOT_STICKY;
}
@Override
public void onCurrentConferenceChanged(String conferenceUrl) {
if (conferenceUrl == null) {
stopSelf();
JitsiMeetLogger.i(TAG + "Service stopped");
}
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright @ 2018-present 8x8, Inc.
* Copyright @ 2017-2018 Atlassian Pty Ltd
*
* 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 org.jitsi.meet.sdk.log.JitsiMeetLogger;
class JitsiMeetUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
private final Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler;
public static void register() {
Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
JitsiMeetUncaughtExceptionHandler uncaughtExceptionHandler
= new JitsiMeetUncaughtExceptionHandler(defaultUncaughtExceptionHandler);
Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);
}
private JitsiMeetUncaughtExceptionHandler(Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler) {
this.defaultUncaughtExceptionHandler = defaultUncaughtExceptionHandler;
}
@Override
public void uncaughtException(Thread t, Throwable e) {
JitsiMeetLogger.e(e, this.getClass().getSimpleName() + " FATAL ERROR");
// Abort all ConnectionService ongoing calls
if (AudioModeModule.useConnectionService()) {
ConnectionService.abortConnections();
}
if (defaultUncaughtExceptionHandler != null) {
defaultUncaughtExceptionHandler.uncaughtException(t, e);
}
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jitsi.meet.sdk;
import android.os.Bundle;
import java.net.MalformedURLException;
import java.net.URL;
/**
* This class represents user information to be passed to {@link JitsiMeetConferenceOptions} for
* identifying a user.
*/
public class JitsiMeetUserInfo {
/**
* User's display name.
*/
private String displayName;
/**
* User's email address.
*/
private String email;
/**
* User's avatar URL.
*/
private URL avatar;
public JitsiMeetUserInfo() {}
public JitsiMeetUserInfo(Bundle b) {
super();
if (b.containsKey("displayName")) {
displayName = b.getString("displayName");
}
if (b.containsKey("email")) {
email = b.getString("email");
}
if (b.containsKey("avatarURL")) {
String avatarURL = b.getString("avatarURL");
try {
avatar = new URL(avatarURL);
} catch (MalformedURLException e) {
}
}
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public URL getAvatar() {
return avatar;
}
public void setAvatar(URL avatar) {
this.avatar = avatar;
}
Bundle asBundle() {
Bundle b = new Bundle();
if (displayName != null) {
b.putString("displayName", displayName);
}
if (email != null) {
b.putString("email", email);
}
if (avatar != null) {
b.putString("avatarURL", avatar.toString());
}
return b;
}
}

View File

@@ -19,17 +19,19 @@ package org.jitsi.meet.sdk;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
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;
public class JitsiMeetView extends BaseReactView<JitsiMeetViewListener> {
public class JitsiMeetView extends BaseReactView<JitsiMeetViewListener>
implements OngoingConferenceTracker.OngoingConferenceListener {
/**
* The {@code Method}s of {@code JitsiMeetViewListener} by event name i.e.
@@ -38,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.
*/
@@ -106,6 +102,14 @@ public class JitsiMeetView extends BaseReactView<JitsiMeetViewListener> {
if (!(context instanceof JitsiMeetActivityInterface)) {
throw new RuntimeException("Enclosing Activity must implement JitsiMeetActivityInterface");
}
OngoingConferenceTracker.getInstance().addListener(this);
}
@Override
public void dispose() {
OngoingConferenceTracker.getInstance().removeListener(this);
super.dispose();
}
/**
@@ -123,11 +127,12 @@ public class JitsiMeetView extends BaseReactView<JitsiMeetViewListener> {
PictureInPictureModule.class);
if (pipModule != null
&& PictureInPictureModule.isPictureInPictureSupported()
&& !JitsiMeetActivityDelegate.arePermissionsBeingRequested()
&& this.url != null) {
try {
pipModule.enterPictureInPicture();
} catch (RuntimeException re) {
Log.e(TAG, "failed to enter PiP mode", re);
JitsiMeetLogger.e(re, "Failed to enter PiP mode");
}
}
}
@@ -172,27 +177,17 @@ public class JitsiMeetView extends BaseReactView<JitsiMeetViewListener> {
}
/**
* The internal processing for the URL of the current conference set on the
* associated {@link JitsiMeetView}.
*
* @param eventName the name of the external API event to be processed
* @param eventData the details/specifics of the event to process determined
* by/associated with the specified {@code eventName}.
* Handler for {@link OngoingConferenceTracker} events.
* @param conferenceUrl
*/
private void maybeSetViewURL(String eventName, ReadableMap eventData) {
String url = eventData.getString("url");
switch(eventName) {
case "CONFERENCE_WILL_JOIN":
this.url = url;
break;
case "CONFERENCE_TERMINATED":
if (url != null && url.equals(this.url)) {
this.url = null;
}
break;
}
@Override
public void onCurrentConferenceChanged(String conferenceUrl) {
// This property was introduced in order to address
// an exception in the Picture-in-Picture functionality which arose
// because of delays related to bridging between JavaScript and Java. To
// reduce these delays do not wait for the call to be transferred to the
// UI thread.
this.url = conferenceUrl;
}
/**
@@ -204,13 +199,6 @@ public class JitsiMeetView extends BaseReactView<JitsiMeetViewListener> {
*/
@Override
protected void onExternalAPIEvent(String name, ReadableMap data) {
// XXX The JitsiMeetView property URL was introduced in order to address
// an exception in the Picture-in-Picture functionality which arose
// because of delays related to bridging between JavaScript and Java. To
// reduce these delays do not wait for the call to be transferred to the
// UI thread.
maybeSetViewURL(name, data);
onExternalAPIEvent(LISTENER_METHODS, name, data);
}
}

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

@@ -0,0 +1,99 @@
/*
* 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.ReadableMap;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
/**
* Helper class to keep track of what the current conference is.
*/
class OngoingConferenceTracker {
private static final OngoingConferenceTracker instance = new OngoingConferenceTracker();
private static final String CONFERENCE_WILL_JOIN = "CONFERENCE_WILL_JOIN";
private static final String CONFERENCE_TERMINATED = "CONFERENCE_TERMINATED";
private final Collection<OngoingConferenceListener> listeners =
Collections.synchronizedSet(new HashSet<OngoingConferenceListener>());
private String currentConference;
public OngoingConferenceTracker() {
}
public static OngoingConferenceTracker getInstance() {
return instance;
}
/**
* Gets the current active conference URL.
*
* @return - The current conference URL as a String.
*/
synchronized String getCurrentConference() {
return currentConference;
}
synchronized void onExternalAPIEvent(String name, ReadableMap data) {
if (!data.hasKey("url")) {
return;
}
String url = data.getString("url");
if (url == null) {
return;
}
switch(name) {
case CONFERENCE_WILL_JOIN:
currentConference = url;
updateListeners();
break;
case CONFERENCE_TERMINATED:
if (url.equals(currentConference)) {
currentConference = null;
updateListeners();
}
break;
}
}
void addListener(OngoingConferenceListener listener) {
listeners.add(listener);
}
void removeListener(OngoingConferenceListener listener) {
listeners.remove(listener);
}
private void updateListeners() {
synchronized (listeners) {
for (OngoingConferenceListener listener : listeners) {
listener.onCurrentConferenceChanged(currentConference);
}
}
}
public interface OngoingConferenceListener {
void onCurrentConferenceChanged(String conferenceUrl);
}
}

View File

@@ -0,0 +1,119 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jitsi.meet.sdk;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import androidx.core.app.NotificationCompat;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.Random;
/**
* Helper class for creating the ongoing notification which is used with
* {@link JitsiMeetOngoingConferenceService}. It allows the user to easily get back to the app
* and to hangup from within the notification itself.
*/
class OngoingNotification {
private static final String TAG = OngoingNotification.class.getSimpleName();
private static final String CHANNEL_ID = "JitsiNotificationChannel";
private static final String CHANNEL_NAME = "Ongoing Conference Notifications";
static final int NOTIFICATION_ID = new Random().nextInt(99999) + 10000;
static void createOngoingConferenceNotificationChannel() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return;
}
Context context = ReactInstanceManagerHolder.getCurrentActivity();
if (context == null) {
JitsiMeetLogger.w(TAG + " Cannot create notification channel: no current context");
return;
}
NotificationManager notificationManager
= (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel
= notificationManager.getNotificationChannel(CHANNEL_ID);
if (channel != null) {
// The channel was already created, no need to do it again.
return;
}
channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
channel.enableLights(false);
channel.enableVibration(false);
channel.setShowBadge(false);
notificationManager.createNotificationChannel(channel);
}
static Notification buildOngoingConferenceNotification() {
Context context = ReactInstanceManagerHolder.getCurrentActivity();
if (context == null) {
JitsiMeetLogger.w(TAG + " Cannot create notification: no current context");
return null;
}
Intent notificationIntent = new Intent(context, context.getClass());
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
NotificationCompat.Builder builder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder = new NotificationCompat.Builder(context, CHANNEL_ID);
} else {
builder = new NotificationCompat.Builder(context);
}
builder
.setCategory(NotificationCompat.CATEGORY_CALL)
.setContentTitle(context.getString(R.string.ongoing_notification_title))
.setContentText(context.getString(R.string.ongoing_notification_text))
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setOngoing(true)
.setAutoCancel(false)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setUsesChronometer(true)
.setOnlyAlertOnce(true)
.setSmallIcon(context.getResources().getIdentifier("ic_notification", "drawable", context.getPackageName()));
// Add a "hang-up" action only if we are using ConnectionService.
if (AudioModeModule.useConnectionService()) {
Intent hangupIntent = new Intent(context, JitsiMeetOngoingConferenceService.class);
hangupIntent.setAction(JitsiMeetOngoingConferenceService.Actions.HANGUP);
PendingIntent hangupPendingIntent
= PendingIntent.getService(context, 0, hangupIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action hangupAction = new NotificationCompat.Action(0, "Hang up", hangupPendingIntent);
builder.addAction(hangupAction);
}
return builder.build();
}
}

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

@@ -5,13 +5,12 @@ import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.telecom.DisconnectCause;
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.ReactApplicationContext;
@@ -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.
@@ -74,11 +75,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 +119,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 +132,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 +144,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

View File

@@ -17,17 +17,32 @@
package org.jitsi.meet.sdk;
import android.app.Application;
import android.support.annotation.Nullable;
import android.app.Activity;
import androidx.annotation.Nullable;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.common.LifecycleState;
import com.facebook.react.devsupport.DevInternalSettings;
import com.facebook.react.jscexecutor.JSCExecutorFactory;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.uimanager.ViewManager;
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;
import org.webrtc.VideoEncoderFactory;
import org.webrtc.audio.AudioDeviceModule;
import org.webrtc.audio.JavaAudioDeviceModule;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -44,17 +59,16 @@ class ReactInstanceManagerHolder {
*/
private static ReactInstanceManager reactInstanceManager;
private static List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
private static List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> nativeModules
= new ArrayList<>(Arrays.<NativeModule>asList(
new AmplitudeModule(reactContext),
new AndroidSettingsModule(reactContext),
new AppInfoModule(reactContext),
new AudioModeModule(reactContext),
new DropboxModule(reactContext),
new ExternalAPIModule(reactContext),
new LocaleDetector(reactContext),
new LogBridgeModule(reactContext),
new PictureInPictureModule(reactContext),
new ProximityModule(reactContext),
new WiFiStatsModule(reactContext),
@@ -64,9 +78,39 @@ class ReactInstanceManagerHolder {
nativeModules.add(new RNConnectionService(reactContext));
}
// Initialize the WebRTC module by hand, since we want to override some
// initialization options.
WebRTCModule.Options options = new WebRTCModule.Options();
AudioDeviceModule adm = JavaAudioDeviceModule.builder(reactContext)
.createAudioDeviceModule();
VideoDecoderFactory videoDecoderFactory = new SoftwareVideoDecoderFactory();
VideoEncoderFactory videoEncoderFactory = new SoftwareVideoEncoderFactory();
options.setAudioDeviceModule(adm);
options.setVideoDecoderFactory(videoDecoderFactory);
options.setVideoEncoderFactory(videoEncoderFactory);
nativeModules.add(new WebRTCModule(reactContext, options));
try {
Class<?> amplitudeModuleClass = Class.forName("org.jitsi.meet.sdk.AmplitudeModule");
Constructor constructor = amplitudeModuleClass.getConstructor(ReactApplicationContext.class);
nativeModules.add((NativeModule)constructor.newInstance(reactContext));
} catch (Exception e) {
// Ignore any error, the module is not compiled when LIBRE_BUILD is enabled.
}
return nativeModules;
}
private static List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList(
// WebRTC, see createNativeModules for details.
new RTCVideoViewManager()
);
}
/**
* Helper function to send an event to JavaScript.
*
@@ -111,6 +155,18 @@ class ReactInstanceManagerHolder {
? reactContext.getNativeModule(nativeModuleClass) : null;
}
/**
* Gets the current {@link Activity} linked to React Native.
*
* @return An activity attached to React Native.
*/
static Activity getCurrentActivity() {
ReactContext reactContext
= reactInstanceManager != null
? reactInstanceManager.getCurrentReactContext() : null;
return reactContext != null ? reactContext.getCurrentActivity() : null;
}
static ReactInstanceManager getReactInstanceManager() {
return reactInstanceManager;
}
@@ -121,38 +177,59 @@ class ReactInstanceManagerHolder {
* time. All {@code ReactRootView} instances will be tied to the one and
* only {@code ReactInstanceManager}.
*
* @param application {@code Application} instance which is running.
* @param activity {@code Activity} current running Activity.
*/
static void initReactInstanceManager(Application application) {
static void initReactInstanceManager(Activity activity) {
if (reactInstanceManager != null) {
return;
}
SoLoader.init(activity, /* native exopackage */ false);
List<ReactPackage> packages
= new ArrayList<>(Arrays.asList(
new com.BV.LinearGradient.LinearGradientPackage(),
new com.calendarevents.CalendarEventsPackage(),
new com.corbt.keepawake.KCKeepAwakePackage(),
new com.facebook.react.shell.MainReactPackage(),
new com.horcrux.svg.SvgPackage(),
new com.ocetnik.timer.BackgroundTimerPackage(),
new com.reactnativecommunity.asyncstorage.AsyncStoragePackage(),
new com.reactnativecommunity.netinfo.NetInfoPackage(),
new com.reactnativecommunity.webview.RNCWebViewPackage(),
new com.rnimmersive.RNImmersivePackage(),
new com.zmxv.RNSound.RNSoundPackage(),
new ReactPackageAdapter() {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
return ReactInstanceManagerHolder.createNativeModules(reactContext);
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return ReactInstanceManagerHolder.createViewManagers(reactContext);
}
}));
try {
Class<?> googlePackageClass = Class.forName("co.apptailor.googlesignin.RNGoogleSigninPackage");
Constructor constructor = googlePackageClass.getConstructor();
packages.add((ReactPackage)constructor.newInstance());
} catch (Exception e) {
// Ignore any error, the module is not compiled when LIBRE_BUILD is enabled.
}
// Keep on using JSC, the jury is out on Hermes.
JSCExecutorFactory jsFactory
= new JSCExecutorFactory("", "");
reactInstanceManager
= ReactInstanceManager.builder()
.setApplication(application)
.setApplication(activity.getApplication())
.setCurrentActivity(activity)
.setBundleAssetName("index.android.bundle")
.setJSMainModulePath("index.android")
.addPackage(new co.apptailor.googlesignin.RNGoogleSigninPackage())
.addPackage(new com.BV.LinearGradient.LinearGradientPackage())
.addPackage(new com.calendarevents.CalendarEventsPackage())
.addPackage(new com.corbt.keepawake.KCKeepAwakePackage())
.addPackage(new com.dylanvann.fastimage.FastImageViewPackage())
.addPackage(new com.facebook.react.shell.MainReactPackage())
.addPackage(new com.oblador.vectoricons.VectorIconsPackage())
.addPackage(new com.ocetnik.timer.BackgroundTimerPackage())
.addPackage(new com.oney.WebRTCModule.WebRTCModulePackage())
.addPackage(new com.rnimmersive.RNImmersivePackage())
.addPackage(new com.zmxv.RNSound.RNSoundPackage())
.addPackage(new ReactPackageAdapter() {
@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
return
ReactInstanceManagerHolder.createNativeModules(
reactContext);
}
})
.setJavaScriptExecutorFactory(jsFactory)
.addPackages(packages)
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
@@ -163,5 +240,8 @@ class ReactInstanceManagerHolder {
if (devSettings != null) {
devSettings.setBundleDeltasEnabled(false);
}
// Register our uncaught exception handler.
JitsiMeetUncaughtExceptionHandler.register();
}
}

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;
@@ -144,8 +144,7 @@ class WiFiStatsModule
JSONObject result = new JSONObject();
result.put("rssi", rssi)
.put("signal", signalLevel)
.put("timestamp",
String.valueOf(System.currentTimeMillis()));
.put("timestamp", System.currentTimeMillis());
JSONArray addresses = new JSONArray();
@@ -185,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

@@ -16,7 +16,7 @@
package org.jitsi.meet.sdk.incoming_call;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
public class IncomingCallInfo {
/**

View File

@@ -18,7 +18,7 @@ package org.jitsi.meet.sdk.incoming_call;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
import com.facebook.react.bridge.ReadableMap;

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;
/**
@@ -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

@@ -1,4 +1,6 @@
<resources>
<string name="app_name">Jitsi Meet SDK</string>
<string name="dropbox_app_key"></string>
<string name="ongoing_notification_title">Ongoing meeting</string>
<string name="ongoing_notification_text">You are currently in a meeting. Tap to return to it.</string>
</resources>

View File

@@ -3,8 +3,12 @@ rootProject.name = 'jitsi-meet'
include ':app', ':sdk'
include ':react-native-background-timer'
project(':react-native-background-timer').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-background-timer/android')
include ':react-native-fast-image'
project(':react-native-fast-image').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fast-image/android')
include ':react-native-calendar-events'
project(':react-native-calendar-events').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-calendar-events/android')
include ':react-native-community-async-storage'
project(':react-native-community-async-storage').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/async-storage/android')
include ':react-native-community_netinfo'
project(':react-native-community_netinfo').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/netinfo/android')
include ':react-native-google-signin'
project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-google-signin/android')
include ':react-native-immersive'
@@ -15,9 +19,9 @@ 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-calendar-events'
project(':react-native-calendar-events').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-calendar-events/android')
include ':react-native-webview'
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')

View File

@@ -16,13 +16,15 @@ import * as JitsiMeetConferenceEvents from './ConferenceEvents';
import {
createDeviceChangedEvent,
createStartSilentEvent,
createScreenSharingEvent,
createStreamSwitchDelayEvent,
createTrackMutedEvent,
sendAnalytics
} from './react/features/analytics';
import {
redirectWithStoredParams,
maybeRedirectToWelcomePage,
redirectToStaticPage,
reloadWithStoredParams
} from './react/features/app';
@@ -42,6 +44,7 @@ import {
conferenceWillJoin,
conferenceWillLeave,
dataChannelOpened,
kickedOut,
lockStateChanged,
onStartMutedPolicyChanged,
p2pStatusChanged,
@@ -49,7 +52,10 @@ import {
setDesktopSharingEnabled
} from './react/features/base/conference';
import {
checkAndNotifyForNewDevice,
getAvailableDevices,
notifyCameraError,
notifyMicError,
setAudioOutputDeviceId,
updateDeviceList
} from './react/features/base/devices';
@@ -75,13 +81,14 @@ import {
import { showNotification } from './react/features/notifications';
import {
dominantSpeakerChanged,
getAvatarURLByParticipantId,
getLocalParticipant,
getNormalizedDisplayName,
getParticipantById,
localParticipantConnectionStatusChanged,
localParticipantRoleChanged,
participantConnectionStatusChanged,
participantKicked,
participantMutedUs,
participantPresenceChanged,
participantRoleChanged,
participantUpdated
@@ -91,14 +98,12 @@ import {
createLocalTracksF,
destroyLocalTracks,
isLocalTrackMuted,
isUserInteractionRequiredForUnmute,
replaceLocalTrack,
trackAdded,
trackRemoved
} from './react/features/base/tracks';
import {
getLocationContextRoot,
getJitsiMeetGlobalNS
} from './react/features/base/util';
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';
@@ -106,10 +111,8 @@ import {
maybeOpenFeedbackDialog,
submitFeedback
} from './react/features/feedback';
import {
mediaPermissionPromptVisibilityChanged,
suspendDetected
} from './react/features/overlay';
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';
@@ -205,77 +208,6 @@ function muteLocalVideo(muted) {
APP.store.dispatch(setVideoMuted(muted));
}
/**
* Check if the welcome page is enabled and redirects to it.
* If requested show a thank you dialog before that.
* If we have a close page enabled, redirect to it without
* showing any other dialog.
*
* @param {object} options used to decide which particular close page to show
* or if close page is disabled, whether we should show the thankyou dialog
* @param {boolean} options.showThankYou - whether we should
* show thank you dialog
* @param {boolean} options.feedbackSubmitted - whether feedback was submitted
*/
function maybeRedirectToWelcomePage(options) {
// if close page is enabled redirect to it, without further action
if (config.enableClosePage) {
const { isGuest } = APP.store.getState()['features/base/jwt'];
// save whether current user is guest or not, before navigating
// to close page
window.sessionStorage.setItem('guest', isGuest);
redirectToStaticPage(`static/${
options.feedbackSubmitted ? 'close.html' : 'close2.html'}`);
return;
}
// else: show thankYou dialog only if there is no feedback
if (options.showThankYou) {
APP.store.dispatch(showNotification({
titleArguments: { appName: interfaceConfig.APP_NAME },
titleKey: 'dialog.thankYou'
}));
}
// if Welcome page is enabled redirect to welcome page after 3 sec, if
// there is a thank you message to be shown, 0.5s otherwise.
if (config.enableWelcomePage) {
setTimeout(
() => {
APP.store.dispatch(redirectWithStoredParams('/'));
},
options.showThankYou ? 3000 : 500);
}
}
/**
* Assigns a specific pathname to window.location.pathname taking into account
* the context root of the Web app.
*
* @param {string} pathname - The pathname to assign to
* window.location.pathname. If the specified pathname is relative, the context
* root of the Web app will be prepended to the specified pathname before
* assigning it to window.location.pathname.
* @return {void}
*/
function redirectToStaticPage(pathname) {
const windowLocation = window.location;
let newPathname = pathname;
if (!newPathname.startsWith('/')) {
// A pathname equal to ./ specifies the current directory. It will be
// fine but pointless to include it because contextRoot is the current
// directory.
newPathname.startsWith('./')
&& (newPathname = newPathname.substring(2));
newPathname = getLocationContextRoot(windowLocation) + newPathname;
}
windowLocation.pathname = newPathname;
}
/**
* A queue for the async replaceLocalTrack action so that multiple audio
* replacements cannot happen simultaneously. This solves the issue where
@@ -341,7 +273,7 @@ class ConferenceConnector {
case JitsiConferenceErrors.NOT_ALLOWED_ERROR: {
// let's show some auth not allowed page
redirectToStaticPage('static/authError.html');
APP.store.dispatch(redirectToStaticPage('static/authError.html'));
break;
}
@@ -372,13 +304,6 @@ class ConferenceConnector {
APP.UI.notifyGracefulShutdown();
break;
case JitsiConferenceErrors.JINGLE_FATAL_ERROR: {
const [ error ] = params;
APP.UI.notifyInternalError(error);
break;
}
case JitsiConferenceErrors.CONFERENCE_DESTROYED: {
const [ reason ] = params;
@@ -400,6 +325,7 @@ class ConferenceConnector {
case JitsiConferenceErrors.FOCUS_LEFT:
case JitsiConferenceErrors.VIDEOBRIDGE_NOT_AVAILABLE:
case JitsiConferenceErrors.OFFER_ANSWER_FAILED:
APP.store.dispatch(conferenceWillLeave(room));
// FIXME the conference should be stopped by the library and not by
@@ -437,8 +363,8 @@ class ConferenceConnector {
hasRead: true,
error: code,
message: msg,
timestamp: Date.now(),
type: 'error'
messageType: 'error',
timestamp: Date.now()
}));
}
break;
@@ -485,10 +411,13 @@ class ConferenceConnector {
* call in hangup() to resolve when all operations are finished.
*/
function disconnect() {
connection.disconnect();
APP.API.notifyConferenceLeft(APP.conference.roomName);
const onDisconnected = () => {
APP.API.notifyConferenceLeft(APP.conference.roomName);
return Promise.resolve();
return Promise.resolve();
};
return connection.disconnect().then(onDisconnected, onDisconnected);
}
/**
@@ -626,8 +555,7 @@ export default {
// Resolve with no tracks
tryCreateLocalTracks = Promise.resolve([]);
} else {
tryCreateLocalTracks = createLocalTracksF(
{ devices: initialDevices }, true)
tryCreateLocalTracks = createLocalTracksF({ devices: initialDevices }, true)
.catch(err => {
if (requestedAudio && requestedVideo) {
@@ -693,13 +621,14 @@ export default {
// If both requests for 'audio' + 'video' and 'audio'
// only failed, we assume that there are some problems
// with user's microphone and show corresponding dialog.
APP.UI.showMicErrorNotification(audioOnlyError);
APP.UI.showCameraErrorNotification(videoOnlyError);
APP.store.dispatch(notifyMicError(audioOnlyError));
APP.store.dispatch(notifyCameraError(videoOnlyError));
} else {
// If request for 'audio' + 'video' failed, but request
// for 'audio' only was OK, we assume that we had
// problems with camera and show corresponding dialog.
APP.UI.showCameraErrorNotification(audioAndVideoError);
APP.store.dispatch(
notifyCameraError(audioAndVideoError));
}
}
@@ -717,13 +646,25 @@ export default {
this.roomName = options.roomName;
return (
this.createInitialLocalTracksAndConnect(
// Initialize the device list first. This way, when creating tracks
// based on preferred devices, loose label matching can be done in
// cases where the exact ID match is no longer available, such as
// when the camera device has switched USB ports.
// when in startSilent mode we want to start with audio muted
this._initDeviceList()
.catch(error => logger.warn(
'initial device list initialization failed', error))
.then(() => this.createInitialLocalTracksAndConnect(
options.roomName, {
startAudioOnly: config.startAudioOnly,
startScreenSharing: config.startScreenSharing,
startWithAudioMuted: config.startWithAudioMuted,
startWithAudioMuted: config.startWithAudioMuted
|| config.startSilent
|| isUserInteractionRequiredForUnmute(APP.store.getState()),
startWithVideoMuted: config.startWithVideoMuted
})
|| isUserInteractionRequiredForUnmute(APP.store.getState())
}))
.then(([ tracks, con ]) => {
tracks.forEach(track => {
if ((track.isAudioTrack() && this.isLocalAudioMuted())
@@ -768,12 +709,23 @@ export default {
this.setVideoMuteStatus(true);
}
this._initDeviceList();
// Initialize device list a second time to ensure device labels
// get populated in case of an initial gUM acceptance; otherwise
// they may remain as empty strings.
this._initDeviceList(true);
if (config.iAmRecorder) {
this.recorder = new Recorder();
}
if (config.startSilent) {
sendAnalytics(createStartSilentEvent());
APP.store.dispatch(showNotification({
descriptionKey: 'notify.startSilentDescription',
titleKey: 'notify.startSilentTitle'
}));
}
// XXX The API will take care of disconnecting from the XMPP
// server (and, thus, leaving the room) on unload.
return new Promise((resolve, reject) => {
@@ -812,6 +764,13 @@ export default {
* dialogs in case of media permissions error.
*/
muteAudio(mute, showUI = true) {
if (!mute
&& isUserInteractionRequiredForUnmute(APP.store.getState())) {
logger.error('Unmuting audio requires user interaction');
return;
}
// Not ready to modify track's state yet
if (!this._localTracksInitialized) {
// This will only modify base/media.audio.muted which is then synced
@@ -827,7 +786,7 @@ export default {
if (!this.localAudio && !mute) {
const maybeShowErrorDialog = error => {
showUI && APP.UI.showMicErrorNotification(error);
showUI && APP.store.dispatch(notifyMicError(error));
};
createLocalTracksF({ devices: [ 'audio' ] }, false)
@@ -875,6 +834,13 @@ export default {
* dialogs in case of media permissions error.
*/
muteVideo(mute, showUI = true) {
if (!mute
&& isUserInteractionRequiredForUnmute(APP.store.getState())) {
logger.error('Unmuting video requires user interaction');
return;
}
// If not ready to modify track's state yet adjust the base/media
if (!this._localTracksInitialized) {
// This will only modify base/media.video.muted which is then synced
@@ -890,7 +856,7 @@ export default {
if (!this.localVideo && !mute) {
const maybeShowErrorDialog = error => {
showUI && APP.UI.showCameraErrorNotification(error);
showUI && APP.store.dispatch(notifyCameraError(error));
};
// Try to create local video if there wasn't any.
@@ -994,17 +960,15 @@ export default {
* Returns the connection times stored in the library.
*/
getConnectionTimes() {
return this._room.getConnectionTimes();
return room.getConnectionTimes();
},
// used by torture currently
isJoined() {
return this._room
&& this._room.isJoined();
return room && room.isJoined();
},
getConnectionState() {
return this._room
&& this._room.getConnectionState();
return room && room.getConnectionState();
},
/**
@@ -1013,8 +977,7 @@ export default {
* P2P connection
*/
getP2PConnectionState() {
return this._room
&& this._room.getP2PConnectionState();
return room && room.getP2PConnectionState();
},
/**
@@ -1023,7 +986,7 @@ export default {
*/
_startP2P() {
try {
this._room && this._room.startP2PSession();
room && room.startP2PSession();
} catch (error) {
logger.error('Start P2P failed', error);
throw error;
@@ -1036,7 +999,7 @@ export default {
*/
_stopP2P() {
try {
this._room && this._room.stopP2PSession();
room && room.stopP2PSession();
} catch (error) {
logger.error('Stop P2P failed', error);
throw error;
@@ -1051,7 +1014,7 @@ export default {
* false otherwise.
*/
isConnectionInterrupted() {
return this._room.isConnectionInterrupted();
return room.isConnectionInterrupted();
},
/**
@@ -1112,7 +1075,7 @@ export default {
},
getMyUserId() {
return this._room && this._room.myUserId();
return room && room.myUserId();
},
/**
@@ -1135,7 +1098,7 @@ export default {
* least one track.
*/
getNumberOfParticipantsWithTracks() {
return this._room.getParticipants()
return room.getParticipants()
.filter(p => p.getTracks().length > 0)
.length;
},
@@ -1273,17 +1236,34 @@ export default {
const options = config;
const nick = APP.store.getState()['features/base/settings'].displayName;
const { locationURL } = APP.store.getState()['features/base/connection'];
if (nick) {
options.displayName = nick;
}
options.applicationName = interfaceConfig.APP_NAME;
options.getWiFiStatsMethod = getJitsiMeetGlobalNS().getWiFiStats;
options.getWiFiStatsMethod = this._getWiFiStatsMethod;
options.confID = `${locationURL.host}${locationURL.pathname}`;
return options;
},
/**
* Returns the result of getWiFiStats from the global NS or does nothing
* (returns empty result).
* Fixes a concurrency problem where we need to pass a function when creating
* JitsiConference, but that method is added to the context later.
*
* @returns {Promise}
* @private
*/
_getWiFiStatsMethod() {
const gloabalNS = getJitsiMeetGlobalNS();
return gloabalNS.getWiFiStats ? gloabalNS.getWiFiStats() : Promise.resolve('{}');
},
/**
* Start using provided video stream.
* Stops previous video stream.
@@ -1299,7 +1279,7 @@ export default {
this.localVideo = newStream;
this._setSharingScreen(newStream);
if (newStream) {
APP.UI.addLocalStream(newStream);
APP.UI.addLocalVideoStream(newStream);
}
this.setVideoMuteStatus(this.isLocalVideoMuted());
})
@@ -1350,9 +1330,6 @@ export default {
replaceLocalTrack(this.localAudio, newStream, room))
.then(() => {
this.localAudio = newStream;
if (newStream) {
APP.UI.addLocalStream(newStream);
}
this.setAudioMuteStatus(this.isLocalAudioMuted());
})
.then(resolve)
@@ -1368,8 +1345,7 @@ export default {
* @returns {boolean}
*/
isAudioOnly() {
return Boolean(
APP.store.getState()['features/base/conference'].audioOnly);
return Boolean(APP.store.getState()['features/base/audio-only'].enabled);
},
videoSwitchInProgress: false,
@@ -1481,7 +1457,9 @@ export default {
return this._switchToScreenSharing(options);
}
return this._untoggleScreenSharing();
return this._untoggleScreenSharing
? this._untoggleScreenSharing()
: Promise.resolve();
},
/**
@@ -1733,14 +1711,7 @@ export default {
return;
}
const displayName = user.getDisplayName();
logger.log(`USER ${id} connnected:`, user);
APP.API.notifyUserJoined(id, {
displayName,
formattedDisplayName: appendSuffix(
displayName || interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME)
});
APP.UI.addUser(user);
// check the roles for the new user and reflect them
@@ -1756,12 +1727,7 @@ export default {
}
logger.log(`USER ${id} LEFT:`, user);
APP.API.notifyUserLeft(id);
APP.UI.messageHandler.participantNotification(
user.getDisplayName(),
'notify.somebody',
'disconnected',
'notify.disconnected');
APP.UI.onSharedVideoStop(id);
});
@@ -1830,9 +1796,12 @@ export default {
APP.UI.setAudioLevel(id, newLvl);
});
room.on(JitsiConferenceEvents.TALK_WHILE_MUTED, () => {
APP.UI.showToolbar(6000);
room.on(JitsiConferenceEvents.TRACK_MUTE_CHANGED, (track, participantThatMutedUs) => {
if (participantThatMutedUs) {
APP.store.dispatch(participantMutedUs(participantThatMutedUs));
}
});
room.on(JitsiConferenceEvents.SUBJECT_CHANGED,
subject => APP.store.dispatch(conferenceSubjectChanged(subject)));
@@ -1919,21 +1888,6 @@ export default {
JitsiConferenceEvents.PARTICIPANT_PROPERTY_CHANGED,
(participant, name, oldValue, newValue) => {
switch (name) {
case 'features_screen-sharing': {
APP.store.dispatch(participantUpdated({
conference: room,
id: participant.getId(),
features: { 'screen-sharing': true }
}));
break;
}
case 'raisedHand':
APP.store.dispatch(participantUpdated({
conference: room,
id: participant.getId(),
raisedHand: newValue === 'true'
}));
break;
case 'remoteControlSessionStatus':
APP.UI.setRemoteControlActiveStatus(
participant.getId(),
@@ -1945,40 +1899,19 @@ export default {
}
});
room.on(JitsiConferenceEvents.KICKED, () => {
room.on(JitsiConferenceEvents.KICKED, participant => {
APP.UI.hideStats();
APP.UI.notifyKicked();
APP.store.dispatch(kickedOut(room, participant));
// FIXME close
});
room.on(JitsiConferenceEvents.PARTICIPANT_KICKED, (kicker, kicked) => {
APP.store.dispatch(participantKicked(kicker, kicked));
});
room.on(JitsiConferenceEvents.SUSPEND_DETECTED, () => {
APP.store.dispatch(suspendDetected());
// After wake up, we will be in a state where conference is left
// there will be dialog shown to user.
// We do not want video/audio as we show an overlay and after it
// user need to rejoin or close, while waking up we can detect
// camera wakeup as a problem with device.
// We also do not care about device change, which happens
// on resume after suspending PC.
if (this.deviceChangeListener) {
JitsiMeetJS.mediaDevices.removeEventListener(
JitsiMediaDevicesEvents.DEVICE_LIST_CHANGED,
this.deviceChangeListener);
}
// stop local video
if (this.localVideo) {
this.localVideo.dispose();
this.localVideo = null;
}
// stop local audio
if (this.localAudio) {
this.localAudio.dispose();
this.localAudio = null;
}
});
APP.UI.addListener(UIEvents.AUDIO_MUTED, muted => {
@@ -2109,12 +2042,10 @@ export default {
})
.then(() => {
logger.log('switched local video device');
APP.store.dispatch(updateSettings({
cameraDeviceId
}));
this._updateVideoDeviceId();
})
.catch(err => {
APP.UI.showCameraErrorNotification(err);
APP.store.dispatch(notifyCameraError(err));
});
}
);
@@ -2140,15 +2071,14 @@ export default {
return stream;
})
.then(stream => {
this.useAudioStream(stream);
.then(stream => this.useAudioStream(stream))
.then(() => {
logger.log('switched local audio device');
APP.store.dispatch(updateSettings({
micDeviceId
}));
this._updateAudioDeviceId();
})
.catch(err => {
APP.UI.showMicErrorNotification(err);
APP.store.dispatch(notifyMicError(err));
});
}
);
@@ -2237,6 +2167,27 @@ export default {
});
},
/**
* Cleanups local conference on suspend.
*/
onSuspendDetected() {
// After wake up, we will be in a state where conference is left
// there will be dialog shown to user.
// We do not want video/audio as we show an overlay and after it
// user need to rejoin or close, while waking up we can detect
// camera wakeup as a problem with device.
// We also do not care about device change, which happens
// on resume after suspending PC.
if (this.deviceChangeListener) {
JitsiMeetJS.mediaDevices.removeEventListener(
JitsiMediaDevicesEvents.DEVICE_LIST_CHANGED,
this.deviceChangeListener);
}
this.localVideo = null;
this.localAudio = null;
},
/**
* Callback invoked when the conference has been successfully joined.
* Initializes the UI and various other features.
@@ -2249,29 +2200,12 @@ export default {
APP.keyboardshortcut.init();
if (config.requireDisplayName
&& !APP.conference.getLocalDisplayName()) {
APP.UI.promptDisplayName();
}
APP.store.dispatch(conferenceJoined(room));
const displayName
= APP.store.getState()['features/base/settings'].displayName;
APP.UI.changeDisplayName('localVideoContainer', displayName);
APP.API.notifyConferenceJoined(
this.roomName,
this._room.myUserId(),
{
displayName,
formattedDisplayName: appendSuffix(
displayName,
interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME),
avatarURL: getAvatarURLByParticipantId(
APP.store.getState(), this._room.myUserId())
}
);
},
/**
@@ -2294,20 +2228,23 @@ export default {
},
/**
* Inits list of current devices and event listener for device change.
* Updates the list of current devices.
* @param {boolean} setDeviceListChangeHandler - Whether to add the deviceList change handlers.
* @private
* @returns {Promise}
*/
_initDeviceList() {
_initDeviceList(setDeviceListChangeHandler = false) {
const { mediaDevices } = JitsiMeetJS;
if (mediaDevices.isDeviceListAvailable()
&& mediaDevices.isDeviceChangeAvailable()) {
this.deviceChangeListener = devices =>
window.setTimeout(() => this._onDeviceListChanged(devices), 0);
mediaDevices.addEventListener(
JitsiMediaDevicesEvents.DEVICE_LIST_CHANGED,
this.deviceChangeListener);
if (setDeviceListChangeHandler) {
this.deviceChangeListener = devices =>
window.setTimeout(() => this._onDeviceListChanged(devices), 0);
mediaDevices.addEventListener(
JitsiMediaDevicesEvents.DEVICE_LIST_CHANGED,
this.deviceChangeListener);
}
const { dispatch } = APP.store;
@@ -2316,18 +2253,9 @@ export default {
// Ugly way to synchronize real device IDs with local
// storage and settings menu. This is a workaround until
// getConstraints() method will be implemented in browsers.
if (this.localAudio) {
dispatch(updateSettings({
micDeviceId: this.localAudio.getDeviceId()
}));
}
this._updateAudioDeviceId();
if (this.localVideo
&& this.localVideo.videoType === 'camera') {
dispatch(updateSettings({
cameraDeviceId: this.localVideo.getDeviceId()
}));
}
this._updateVideoDeviceId();
APP.UI.onAvailableDevicesChanged(devices);
});
@@ -2336,6 +2264,33 @@ export default {
return Promise.resolve();
},
/**
* Updates the settings for the currently used video device, extracting
* the device id from the used track.
* @private
*/
_updateVideoDeviceId() {
if (this.localVideo
&& this.localVideo.videoType === 'camera') {
APP.store.dispatch(updateSettings({
cameraDeviceId: this.localVideo.getDeviceId()
}));
}
},
/**
* Updates the settings for the currently used audio device, extracting
* the device id from the used track.
* @private
*/
_updateAudioDeviceId() {
if (this.localAudio) {
APP.store.dispatch(updateSettings({
micDeviceId: this.localAudio.getDeviceId()
}));
}
},
/**
* Event listener for JitsiMediaDevicesEvents.DEVICE_LIST_CHANGED to
* handle change of available media devices.
@@ -2344,6 +2299,8 @@ export default {
* @returns {Promise}
*/
_onDeviceListChanged(devices) {
const oldDevices = APP.store.getState()['features/base/devices'].availableDevices;
APP.store.dispatch(updateDeviceList(devices));
const newDevices
@@ -2355,6 +2312,10 @@ export default {
const promises = [];
const audioWasMuted = this.isLocalAudioMuted();
const videoWasMuted = this.isLocalVideoMuted();
const requestedInput = {
audio: Boolean(newDevices.audioinput),
video: Boolean(newDevices.videoinput)
};
if (typeof newDevices.audiooutput !== 'undefined') {
const { dispatch } = APP.store;
@@ -2366,6 +2327,46 @@ export default {
promises.push(setAudioOutputPromise);
}
// Handles the use case when the default device is changed (we are always stopping the streams because it's
// simpler):
// If the default device is changed we need to first stop the local streams and then call GUM. Otherwise GUM
// will return a stream using the old default device.
if (requestedInput.audio && this.localAudio) {
this.localAudio.stopStream();
}
if (requestedInput.video && this.localVideo) {
this.localVideo.stopStream();
}
// Let's handle unknown/non-preferred devices
const newAvailDevices
= APP.store.getState()['features/base/devices'].availableDevices;
let newAudioDevices = [];
let oldAudioDevices = [];
if (typeof newDevices.audiooutput === 'undefined') {
newAudioDevices = newAvailDevices.audioOutput;
oldAudioDevices = oldDevices.audioOutput;
}
if (!requestedInput.audio) {
newAudioDevices = newAudioDevices.concat(newAvailDevices.audioInput);
oldAudioDevices = oldAudioDevices.concat(oldDevices.audioInput);
}
// check for audio
if (newAudioDevices.length > 0) {
APP.store.dispatch(
checkAndNotifyForNewDevice(newAudioDevices, oldAudioDevices));
}
// check for video
if (!requestedInput.video) {
APP.store.dispatch(
checkAndNotifyForNewDevice(newAvailDevices.videoInput, oldDevices.videoInput));
}
promises.push(
mediaDeviceHelper.createLocalTracksAfterDeviceListChanged(
createLocalTracksF,
@@ -2384,8 +2385,25 @@ export default {
});
return Promise.all(muteSyncPromises)
.then(() => Promise.all(
this._setLocalAudioVideoStreams(tracks)));
.then(() =>
Promise.all(Object.keys(requestedInput).map(mediaType => {
if (requestedInput[mediaType]) {
const useStream
= mediaType === 'audio'
? this.useAudioStream.bind(this)
: this.useVideoStream.bind(this);
// Use the new stream or null if we failed to obtain it.
return useStream(tracks.find(track => track.getType() === mediaType) || null)
.then(() => {
mediaType === 'audio'
? this._updateAudioDeviceId()
: this._updateVideoDeviceId();
});
}
return Promise.resolve();
})));
})
.then(() => {
// Log and sync known mute state.
@@ -2510,7 +2528,7 @@ export default {
room = undefined;
APP.API.notifyReadyToClose();
maybeRedirectToWelcomePage(values[0]);
APP.store.dispatch(maybeRedirectToWelcomePage(values[0]));
});
},
@@ -2522,8 +2540,11 @@ export default {
leaveRoomAndDisconnect() {
APP.store.dispatch(conferenceWillLeave(room));
return room.leave()
.then(disconnect, disconnect);
if (room.isJoined()) {
return room.leave().then(disconnect, disconnect);
}
return disconnect();
},
/**
@@ -2652,14 +2673,6 @@ export default {
displayName: formattedNickname
}));
APP.API.notifyDisplayNameChanged(id, {
displayName: formattedNickname,
formattedDisplayName:
appendSuffix(
formattedNickname,
interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME)
});
if (room) {
APP.UI.changeDisplayName(id, formattedNickname);
}
@@ -2713,6 +2726,18 @@ export default {
*/
convertVideoToDesktop: true,
/**
* Callback invoked when the connection has been closed
* automatically. Triggers cleanup of screensharing if active.
*
* @returns {void}
*/
onConnectionClosed: () => {
if (this._untoggleScreenSharing) {
this._untoggleScreenSharing();
}
},
/**
* Callback invoked to pass messages from the local client back
* out to the external client.

View File

@@ -90,6 +90,10 @@ var config = {
// applied locally. FIXME: having these 2 options is confusing.
// startWithAudioMuted: false,
// Enabling it (with #params) will disable local audio output of remote
// participants and to enable it back a reload is needed.
// startSilent: false
// Video
// Sets the preferred resolution (height) for local video. Defaults to 720.
@@ -119,10 +123,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,
@@ -184,7 +184,11 @@ var config = {
// by enabling fileRecordingsServiceEnabled, we show both the integrations
// and the generic recording service (its configuration and storage type
// depends on jibri configuration)
// fileRecordingsServiceEnabled: false
// fileRecordingsServiceEnabled: false,
// Whether to show the possibility to share file recording with other people
// (e.g. meeting participants), based on the actual implementation
// on the backend.
// fileRecordingsServiceSharingEnabled: false,
// Whether to enable live streaming or not.
// liveStreamingEnabled: false,
@@ -193,6 +197,9 @@ var config = {
// subtitles and buttons can be configured)
// transcribingEnabled: false,
// Enables automatic turning on captions when recording is started
// autoCaptionOnRecord: false,
// Misc
// Default value for the channel "last N" attribute. -1 for unlimited.
@@ -262,6 +269,13 @@ var config = {
// Whether or not some features are checked based on token.
// enableFeaturesBasedOnToken: false,
// Enable lock room for all moderators, even when userRolesBasedOnToken is enabled and participants are guests.
// lockRoomGuestEnabled: false,
// When enabled the password used for locking a room is restricted to up to the number of digits specified
// roomPasswordNumberOfDigits: 10,
// default: roomPasswordNumberOfDigits: false,
// Message to show the users. Example: 'The service will be down for
// maintenance at 01:00 AM GMT,
// noticeMessage: '',
@@ -403,6 +417,14 @@ var config = {
// use only.
// _desktopSharingSourceDevice: 'sample-id-or-label'
// If true, any checks to handoff to another application will be prevented
// and instead the app will continue to display in the current browser.
// disableDeepLinking: false
// A property to disable the right click context menu for localVideo
// the menu has option to flip the locally seen video for local presentations
// disableLocalVideoFlip: false
// List of undocumented settings used in jitsi-meet
/**
_immediateReloadThreshold
@@ -417,7 +439,6 @@ var config = {
dialOutCodesUrl
disableRemoteControl
displayJids
enableLocalVideoFlip
etherpad_base
externalConnectUrl
firefox_fake_device

31
css/_avatar.scss Normal file
View File

@@ -0,0 +1,31 @@
.avatar {
align-items: center;
background-color: #AAA;
display: flex;
border-radius: 50%;
color: rgba(255, 255, 255, 0.6);
font-weight: 100;
justify-content: center;
object-fit: cover;
}
.avatar-foreign {
align-items: center;
bottom: 0;
display: flex;
font-size: 40pt;
justify-content: center;
left: 0;
position: absolute;
right: 0;
top: 0;
}
.avatar-svg {
height: 100%;
width: 100%;
}
.defaultAvatar {
opacity: 0.6
}

View File

@@ -33,6 +33,10 @@ body {
}
}
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

@@ -1,6 +1,9 @@
#sideToolbarContainer {
background-color: $newToolbarBackgroundColor;
box-sizing: border-box;
color: #FFF;
display: flex;
flex-direction: column;
/**
* Make the sidebar flush with the top of the toolbar. Take the size of
* the toolbar and subtract from 100%.
@@ -21,20 +24,6 @@
&.slideInExt {
left: 0;
}
.sideToolbarContainer__inner {
box-sizing: border-box;
color: #FFF;
display: flex;
flex-direction: column;
height: 100%;
width: $sidebarWidth;
}
}
#chat_container * {
-webkit-user-select: text;
user-select: text;
}
#chatconversation {
@@ -42,9 +31,8 @@
flex: 1;
font-size: 10pt;
line-height: 20px;
margin-top: 15px;
overflow: auto;
padding: 5px;
padding: 16px;
text-align: left;
width: $sidebarWidth;
word-wrap: break-word;
@@ -92,26 +80,41 @@
}
}
.chat-close {
background: gray;
border: 3px solid rgba(255, 255, 255, 0.1);
border-radius: 100%;
color: white;
cursor:pointer;
height: 10px;
line-height: 10px;
padding: 4px;
position: absolute;
right: 5px;
text-align: center;
top: 5px;
width: 10px;
.chat-header {
background-color: $chatHeaderBackgroundColor;
height: 70px;
position: relative;
width: 100%;
z-index: 1;
.chat-close {
align-items: center;
bottom: 8px;
color: white;
cursor: pointer;
display: flex;
font-size: 18px;
height: 40px;
justify-content: center;
line-height: 15px;
padding: 4px;
position: absolute;
right: 5px;
width: 40px;
&:hover {
color: rgba(255, 255, 255, 0.8);
}
}
}
#chat-input {
background-color: $newToolbarBackgroundColor;
border-top: 1px solid $chatInputSeparatorColor;
display: flex;
* {
background-color: transparent;
}
}
.remoteuser {
@@ -120,20 +123,16 @@
.usrmsg-form {
flex: 1;
margin-left: 5px;
}
#usermsg {
background-color: $newToolbarBackgroundColor;
border: 0px none;
border-radius:0;
box-shadow: none;
color: white;
font-size: 10pt;
font-size: 15px;
line-height: 30px;
padding: 5px 5px 5px 0px;
max-height:150px;
min-height:35px;
padding: 5px;
overflow-y: auto;
resize: none;
width: 100%;
@@ -146,61 +145,47 @@
}
#nickname {
position: absolute;
text-align: center;
color: #9d9d9d;
font-size: 18px;
top: 100px;
margin-top: 30px;
left: 5px;
right: 5px;
width: 95%;
}
#chat_container .display-name {
float: left;
padding-left: 5px;
font-weight: bold;
white-space: nowrap;
text-overflow: ellipsis;
width: 95%;
overflow: hidden;
}
.sideToolbarContainer {
* {
-webkit-user-select: text;
user-select: text;
}
#chat_container .timestamp {
float: right;
padding-right: 5px;
font-size: 11px;
}
.usermessage {
padding-top: 20px;
padding-left: 5px;
}
.chatArrow {
height: 15px;
left: -10px;
position: absolute;
.display-name {
font-size: 13px;
font-weight: bold;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
}
.chatmessage {
background-color: $newToolbarBackgroundColor;
width: 93%;
margin-left: 9px;
margin-right: auto;
border-radius: 5px;
border-top-left-radius: 0px;
margin-top: 3px;
background-color: $chatRemoteMessageBackgroundColor;
border-radius: 0px 6px 6px 6px;
box-sizing: border-box;
color: white;
margin-top: 3px;
max-width: 100%;
padding-bottom: 3px;
position: relative;
&.localuser .display-name {
color: #4C9AFF
&.localuser {
background-color: $chatLocalMessageBackgroundColor;
border-radius: 6px 0px 6px 6px;
}
&.error {
.chatArrow,
border-radius: 0px;
.timestamp,
.display-name {
display: none;
@@ -219,8 +204,6 @@
#smileys {
font-size: 20pt;
display: inline-block;
height: 26px;
margin: auto;
cursor: pointer;
}
@@ -231,33 +214,36 @@
}
#smileysarea {
background-color: $newToolbarBackgroundColor;
border: 0px none;
display: flex;
height: 70px;
max-height: 150px;
min-height: 35px;
min-width: 31px;
padding: 0px;
overflow: hidden;
width: 17%;
}
.smiley-input {
display: flex;
position: relative;
}
.smileys-panel {
bottom: 100%;
box-sizing: border-box;
height: 0;
height: auto;
max-height: 0;
overflow: hidden;
position: absolute;
transition: height 0.3s;
width: $sidebarWidth;
/**
* CSS transitions do not apply for auto dimensions. So to produce the css
* accordion effect for showing and hiding the smiley-panel, while allowing
* for variable panel, height, use a very large max-height and animate off
* of that.
*/
transition: max-height 0.3s;
&.show-smileys {
height: 146px;
max-height: 500%;
}
#smileysContainer {
@@ -291,3 +277,49 @@
#usermsg::-webkit-scrollbar-track-piece {
background: #3a3a3a;
}
.chat-message-group {
display: flex;
flex-direction: column;
&.local {
align-items: flex-end;
.chatmessage {
background-color: $chatLocalMessageBackgroundColor;
border-radius: 6px 0px 6px 6px;
}
.display-name {
display: none;
}
.timestamp {
text-align: right;
}
}
&.error {
.chatmessage {
border-radius: 0px;
color: red;
}
.display-name {
display: none;
}
}
.chatmessage-wrapper {
max-width: 100%;
}
.chatmessage {
background-color: $chatRemoteMessageBackgroundColor;
border-radius: 0px 6px 6px 6px;
display: inline-block;
margin-top: 3px;
color: white;
padding: 8px;
}
}

View File

@@ -1,210 +0,0 @@
@font-face {
font-family: 'jitsi';
src: url('../fonts/jitsi.eot?3vw865');
src: url('../fonts/jitsi.eot?3vw865#iefix') format('embedded-opentype'),
url('../fonts/jitsi.ttf?3vw865') format('truetype'),
url('../fonts/jitsi.woff?3vw865') format('woff'),
url('../fonts/jitsi.svg?3vw865#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-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";
}
.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";
}

View File

@@ -11,7 +11,7 @@
flex: 0;
flex-direction: row;
justify-content: space-between;
margin-top: 32px;
padding-top: 32px;
.recording-title {
display: inline-flex;
@@ -21,6 +21,14 @@
}
}
.recording-header-line {
border-top: 1px solid #5e6d7a;
}
.recording-switch-disabled {
opacity: 0.5;
}
.recording-icon-container {
display: inline-flex;
align-items: center;

View File

@@ -3,6 +3,7 @@
transition: top .3s ease-in;
height: 95px;
width: 100%;
pointer-events: none;
position: absolute;
padding: 25px 140px 0 140px;
text-align: center;

View File

@@ -48,6 +48,7 @@
height: 160px;
width: 100%;
bottom: -160px;
pointer-events: none;
position: absolute;
z-index: $toolbarBackgroundZ;
}
@@ -72,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;
}
}
}
}
}
@@ -81,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;
color: #fff;
background-color: #a4b8d1;
}
.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;
@@ -190,14 +176,6 @@
cursor: initial;
color: #3b475c;
}
i.toggled {
background: inherit;
}
i.toggled:hover {
background: inherit;
}
}
.beta-tag {
@@ -226,6 +204,10 @@
max-width: 24px;
max-height: 24px;
}
svg {
fill: #B8C7E0 !important;
}
}
.profile-text {
@@ -264,9 +246,26 @@
}
.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;
}
}
}
}
}
@@ -296,10 +295,6 @@
background-color: $AOTToolbarButtonHoverColor;
}
.icon-hangup {
color: $hangupColor;
}
.toolbox-button {
color: $toolbarButtonColor;
cursor: pointer;
@@ -324,10 +319,6 @@
width: $newToolbarSize;
}
.icon-hangup {
font-size: $newToolbarHangupFontSize;
}
.disabled {
cursor: initial;
}

View File

@@ -83,13 +83,22 @@ $modalMockAKInputBorder: 1px solid #f4f5f7;
$modalTextColor: #333;
/**
* Chat
*/
$chatHeaderBackgroundColor: rgba(42, 58, 75, 0.9);
$chatInputSeparatorColor: #A4B8D1;
$chatLocalMessageBackgroundColor: rgba(26, 108, 180, 1);
$chatRemoteMessageBackgroundColor: rgba(240, 243, 247, 0.15);
$sidebarWidth: 375px;
/**
* Misc.
*/
$borderRadius: 4px;
$defaultWatermarkLink: '../images/watermark.png';
$sidebarWidth: 220px;
$popoverMenuPadding: 13px;
$happySoftwareBackground: transparent;
$desktopAppDragBarHeight: 25px;
/**
* Z-indexes. TODO: Replace this by a function.

View File

@@ -23,14 +23,9 @@
top: 0;
width: 100%;
&.fit-full-height #largeVideoBackground {
height: 100%;
width: auto;
}
.fit-full-width #largeVideoBackground {
height: auto;
width: 100%;
#largeVideoBackground {
min-height: 100%;
min-width: 100%;
}
}
#largeVideoBackgroundContainer {
@@ -349,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;
}
/**
@@ -498,7 +496,6 @@
}
#dominantSpeakerAvatarContainer,
#dominantSpeakerAvatar,
.dynamic-shadow {
width: 200px;
height: 200px;
@@ -508,13 +505,9 @@
top: 50px;
margin: auto;
position: relative;
border-radius: 100px;
overflow: hidden;
visibility: inherit;
}
#dominantSpeakerAvatar {
background-color: #000000;
}
.dynamic-shadow {
border-radius: 50%;
@@ -525,24 +518,36 @@
transition: box-shadow 0.3s ease;
}
.userAvatar {
.avatar-container {
@include maxSize(60px);
@include absoluteAligning();
border-radius: 50%;
display: flex;
justify-content: center;
height: 50%;
overflow: hidden;
width: auto;
.userAvatar {
height: 100%;
object-fit: cover;
width: 100%;
}
}
#videoNotAvailableScreen {
text-align: center;
#avatarContainer {
border-radius: 50%;
display: inline-block;
height: 50vh;
display:inline-block;
margin-top: 25vh;
overflow: hidden;
width: 50vh;
#avatar {
border-radius: 50%;
height: 100%;
object-fit: cover;
width: 100%;
}
}
}

View File

@@ -6,7 +6,7 @@
/**
* Let the avatar grow with the tile.
*/
.userAvatar {
.avatar-container {
max-height: initial;
max-width: initial;
}

View File

@@ -25,7 +25,7 @@
display: flex;
flex-direction: column-reverse;
height: 100%;
padding: 10px 5px;
padding: ($desktopAppDragBarHeight - 5px) 5px 10px;
/**
* fixed positioning is necessary for remote menus and tooltips to pop
* out of the scrolling filmstrip. AtlasKit dialogs and tooltips use

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';
@@ -86,5 +80,6 @@ $flagsImagePath: "../images/";
@import 'navigate_section_list';
@import 'third-party-branding/google';
@import 'third-party-branding/microsoft';
@import 'avatar';
/* Modules END */

View File

@@ -185,6 +185,7 @@
font-size: 12px;
max-height: 100%;
overflow: auto;
padding: 15pt;
position: absolute;
transform: translateY(-50%);
top: 50%;

4
debian/control vendored
View File

@@ -36,7 +36,7 @@ Description: Configuration for web serving of Jitsi Meet
Package: jitsi-meet-prosody
Architecture: all
Depends: openssl, prosody | prosody-trunk
Depends: openssl, prosody | prosody-trunk | prosody-0.11
Description: Prosody configuration for Jitsi Meet
Jitsi Meet is a WebRTC JavaScript application that uses Jitsi
Videobridge to provide high quality, scalable video conferences.
@@ -50,6 +50,6 @@ Description: Prosody configuration for Jitsi Meet
Package: jitsi-meet-tokens
Architecture: all
Depends: ${misc:Depends}, prosody-trunk (>= 1nightly607), libssl-dev, luarocks, jitsi-meet-prosody
Depends: ${misc:Depends}, prosody-trunk (>= 1nightly747) | prosody-0.11 | prosody (>= 0.11.2), libssl-dev, luarocks, jitsi-meet-prosody
Description: Prosody token authentication plugin for Jitsi Meet

View File

@@ -125,6 +125,33 @@ case "$1" in
ln -sf /var/lib/prosody/$JVB_HOSTNAME.crt /etc/prosody/certs/$JVB_HOSTNAME.crt
fi
PR11_INSTALL_CHECK="$(dpkg-query -f '${Status}' -W 'prosody-0.11' 2>/dev/null | awk '{print $3}' || true)"
PR10_INSTALL_CHECK="$(dpkg-query -f '${Status}' -W 'prosody-0.10' 2>/dev/null | awk '{print $3}' || true)"
PR_VER_INSTALLED=$(dpkg-query -f='${Version}\n' --show prosody 2>/dev/null || true)
if [ "$PR11_INSTALL_CHECK" = "installed" ] \
|| [ "$PR11_INSTALL_CHECK" = "unpacked" ] \
|| dpkg --compare-versions "$PR_VER_INSTALLED" gt "0.11" ; then
if [ -f $PROSODY_HOST_CONFIG ]; then
sed -i 's/storage = \"null\"/storage = \"memory\"/g' $PROSODY_HOST_CONFIG
# trigger a restart
PROSODY_CONFIG_PRESENT="false"
fi
fi
if [ "$PR10_INSTALL_CHECK" = "installed" ] \
|| [ "$PR10_INSTALL_CHECK" = "unpacked" ] \
|| dpkg --compare-versions "$PR_VER_INSTALLED" gt "0.10" ; then
# if the version is 0.10.X (>0.10 and <0.11)
if [ -f $PROSODY_HOST_CONFIG ] \
&& dpkg --compare-versions "$PR_VER_INSTALLED" lt "0.11" ; then
sed -i 's/storage = \"null\"/storage = \"none\"/g' $PROSODY_HOST_CONFIG
# trigger a restart
PROSODY_CONFIG_PRESENT="false"
fi
fi
if [ ! -f /var/lib/prosody/$JICOFO_AUTH_DOMAIN.crt ]; then
# prosodyctl takes care for the permissions
# echo for using all default values

View File

@@ -69,14 +69,17 @@ case "$1" in
echo "Failed to install basexx - try installing it manually"
fi
PR11_INSTALL_CHECK="$(dpkg-query -f '${Status}' -W 'prosody-0.11' 2>/dev/null | awk '{print $3}' || true)"
PR_VER_INSTALLED=$(dpkg-query -f='${Version}\n' --show prosody 2>/dev/null || true)
if [ "$PR11_INSTALL_CHECK" = "installed" ] \
|| [ "$PR11_INSTALL_CHECK" = "unpacked" ] \
|| dpkg --compare-versions "$PR_VER_INSTALLED" gt "0.11" ; then
sed -i 's/module:hook/module:hook_global/g' /usr/share/jitsi-meet/prosody-plugins/mod_auth_token.lua
fi
if [ -x "/etc/init.d/prosody" ]; then
invoke-rc.d prosody restart
fi
echo "This package requires BOSH Prosody module to be patched !"
echo "Use the following command, after this package has been installed and"
echo "after every prosody-trunk upgrade:"
echo "sudo patch -N /usr/lib/prosody/modules/mod_bosh.lua /usr/share/jitsi-meet/prosody-plugins/mod_bosh.lua.patch"
fi
else
echo "Prosody config not found at $PROSODY_HOST_CONFIG - unable to auto-configure token authentication"

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