Compare commits

..

811 Commits
1908 ... 2425

Author SHA1 Message Date
ibauersachs
2b46c37077 Commit from translate.jitsi.org by user ibauersachs.: 105 of 399 strings translated (10 fuzzy). 2017-11-06 08:22:16 +00:00
ibauersachs
7a9aef874e Commit from translate.jitsi.org by user ibauersachs.: 361 of 399 strings translated (6 fuzzy). 2017-11-06 08:22:04 +00:00
ibauersachs
9bbb237ca8 Commit from translate.jitsi.org by user ibauersachs.: 315 of 399 strings translated (8 fuzzy). 2017-11-06 08:21:52 +00:00
ibauersachs
c3b52548af Commit from translate.jitsi.org by user ibauersachs.: 322 of 399 strings translated (9 fuzzy). 2017-11-06 08:21:40 +00:00
ibauersachs
2802b9721d Commit from translate.jitsi.org by user ibauersachs.: 361 of 399 strings translated (6 fuzzy). 2017-11-06 08:21:29 +00:00
ibauersachs
6a85563f2c Commit from translate.jitsi.org by user ibauersachs.: 361 of 399 strings translated (6 fuzzy). 2017-11-06 08:21:19 +00:00
ibauersachs
b35992077c Commit from translate.jitsi.org by user ibauersachs.: 360 of 399 strings translated (6 fuzzy). 2017-11-06 08:21:08 +00:00
ibauersachs
79b45ce1a0 Commit from translate.jitsi.org by user ibauersachs.: 177 of 399 strings translated (29 fuzzy). 2017-11-06 08:20:45 +00:00
ibauersachs
ff58237e5c Commit from translate.jitsi.org by user ibauersachs.: 398 of 399 strings translated (0 fuzzy). 2017-11-06 08:20:22 +00:00
virtuacoplenny
6cda93d3c1 fix(1080p): video quality label shows hd at 720 (#2131)
The minimum resolution needed to show the HD label should be
720, not 1080. However, the requested video quality for
high quality should be 1080.
2017-11-03 17:21:33 -07:00
virtuacoplenny
510334fa7f ref(notifications): convert some dialogs to error or warning notifica… (#1991)
* ref(notifications): convert some dialogs to error or warning notifications

- Expand the configurability of the Notification component so warnings
  and errors can be displayed.
- Allow Notification to take in arbitrary text for the body.
- Rename defaultTitleKey to titleKey for consistency with descriptionKey.

* ref(notifications): remove openReportDialog method

openReportDialog is a wrapper around showError that adds
a logger statement. It is being called in one place only
so remove the method and have that one place call logger.

* ref(notifications): UI.showTrackNotWorkingDialog takes a boolean

Change UI.showTrackNotWorkingDialog so it takes a boolean
arguments instead of the entire track. A small refactor so
the method needs to know less.

* [squash] Fixes eslint errors

* WiP: Fixes desktop sharing error strings and adds support button

* [squash] Fix icons appearances

* [squash] Fix translate titles and messages

* [squash] fix(translation): Fixes incorrect password string

* [squash] fix(recording): Fixes recording message

* [squash] fix(warning): Turns some warnings to errors and makes support link optional.

* [squash] fix(translation): Addressing language comments

* [squash] Fixes jsdoc and formatting

* [squash] fix(noopener): Fixes window.open noopener

* [squash] fix(constants): Extract constants and refactor NotificationWithToggle

* [squash] fix(lang): Fixes camera and mic error titles

* [squash] fix(supportLink): Renames addSupportLink to hideErrorSupportLink
2017-11-03 14:05:03 -05:00
hristoterezov
c3efa4f088 Add package-lock.json and lock lib-jitsi-meet 2017-11-02 19:17:40 -05:00
Leonard Kim
4a90e6dc71 fix(filmstrip): create a specific target for local video appending
Instead of targetting a div that contains multiple elements
and risking the elements appearing out of order, create a
specific div for local video to append to.
2017-11-02 14:24:29 -05:00
Дамян Минков
90070d9e9f Fixes a problem not showing remote video menu in case of all moderators. (#2130)
Removes hasRemoteVideoMenu from RemoteVideo.
In some cases where mod_muc_allowners is enabled we do not see the remote video menu. The problem was in the order of initialization of remote video component.
RemoteVideo#constructor -> Remotevideo#addaddRemoteVideoContainer -> Remotevideo#addRemoteVideoMenu  -> RemoteVideo#hasRemoteVideoMenu = true
Then in VideoLayout#showModeratorIndicator -> !remoteVideo.hasRemoteVideoMenu -> remoteVideo.addRemoteVideoMenu().
2017-11-02 12:07:31 -07:00
Saúl Ibarra Corretgé
922bbb1798 [iOS] use display: 'none' to hide elements (#2128)
* [iOS] use display: 'none' to hide elements

No, it still doesn't work properly on some Android devices, sigh.
2017-11-02 10:43:32 -05:00
Saúl Ibarra Corretgé
4943eabd1b Merge pull request #2105 from jitsi/react_native_49
Update to react 16 react-native 49
2017-11-02 15:02:49 +01:00
paweldomas
cbd2bb0140 fix(JitsiMeetView): fix rotation on iOS
The root view was not adjusting it's bounds after device rotation.
2017-11-02 14:32:35 +01:00
paweldomas
3f6f5e7eb9 fix(JitsiMeetView): use setAppProperties 2017-11-02 14:32:35 +01:00
paweldomas
b74bede0e7 feat(web/RN): update React to v16 and React Native to 0.49 2017-11-02 14:32:35 +01:00
paweldomas
e520319af2 fix(redux/functions): fix typo
The intention of the code is (1) to return target if none of the setters lead
to an actual change, (2) to not modify target, and (3) to do it with a 1
copyOnWrite at most.
2017-11-02 11:04:54 +01:00
paweldomas
dc24782a2c fix(external-api/middleware): invalid toString call
The intention was to override 'this' argument of 'Error.toString'.
2017-11-02 10:56:48 +01:00
virtuacoplenny
2d9ce2486e feat(1080p): pass new-style constraints to createLocalTracks (#2087)
The lib will accept new style constraints and use those
to capture audio/video. By defining the constraints in
config, there is greater flexibility for defining
and changing constraints.
2017-10-31 17:08:07 -07:00
Leonard Kim
92dbdade39 fix(filmstrip-only): set width for toolbar popovers
The popovers in filmstrip only are displaying thinly.
As a quick workaround, set a width on them. There
should only be one anyway, which shows up when
talking while muted.
2017-10-31 14:42:16 -05:00
Leonard Kim
c345c0d5e8 fix(filmstrip): do not apply flex on local video for horizontal mode
Firefox flex behaves differently from chrome. In firefox, flex
is not allowing the local video and invite button to exceed
the height of the parent, causing the local video to display
shorter than expected due to the invite button. Flex doesn't
need to be applied for local video in horizontal filmstrip
mode as it's only needed in vertical filmstrip mode to
flip the position of the invite button from above the local
video to below. Honestly, this could be better off done
declaratively in the html, but that's not as straigtforward
in this jquery+react world.
2017-10-31 14:42:16 -05:00
Leonard Kim
a8cc65ab9a fix(filmstrip-only): do not re-align local video for invite button
The bottom alignment of the local video container is adjusted
in horizontal filmstrip mode so that the videos remain evenly
aligned at the top but the invite button sticks out. With
the invite button hidden in filmstrip only, this only caused
misalignment. Re-adjust the local video container back down
and put transitions on the filmstrip wrapper itself, instead
of on the thumbnail wrapper level to avoid transitions
when re-adjusting.
2017-10-31 14:42:16 -05:00
Leonard Kim
9233a1026a fix(filmstrip-only): first and last toolbar buttons get rounded edges
All toolbar buttons (which have the class .button) got wrapped
in additional elements due to atlaskit tooltips. This changed
parent/child relationships within the html hierarchy, and the
filmstrip only toolbar selectors needed updating.
2017-10-31 14:42:16 -05:00
Lyubo Marinov
0550858653 [Android] Maven artifact publishing documentation 2017-10-30 16:04:37 -05:00
Lyubo Marinov
34f7e39148 Coding style: consistency
It seems to me that npm 5 starting adding github: as the protocol of
dependencies in package.json which are from GitHub. I personally don't
know which npm version supports these and whether we care about such a
support. Anyway, having some use github: and most not is not consistent.
2017-10-30 13:56:28 -05:00
hristoterezov
bade2ae719 chore(babel): Use babel-preset-env instead of babel-preset-es2015. 2017-10-30 13:41:05 -05:00
damencho
fda52f7160 Moves login state of dialog to be first, to be the initial state.
By default impromptu uses the first state as the default one to show.
2017-10-30 13:01:06 -05:00
Saúl Ibarra Corretgé
561d1909ca Revert "misc: remove duplicated declarations"
This reverts commit 7e831117b6.
2017-10-30 16:24:11 +01:00
Saúl Ibarra Corretgé
4845f80dc8 misc: fix order in package.json 2017-10-30 14:35:29 +01:00
Saúl Ibarra Corretgé
7e831117b6 misc: remove duplicated declarations 2017-10-30 14:07:05 +01:00
Saúl Ibarra Corretgé
b4b2d6f630 [iOS] Remove unneeded imports 2017-10-30 14:06:20 +01:00
hristoterezov
178235513b fix(DesktopPicker): Issues with selection (#2113) 2017-10-27 10:25:28 -07:00
damencho
98111c3593 On token verification failure return error, reason and stop processing.
This was broken with commit c1fb1a7def, which splits the result in order to print the error reason and in case of error was not returning the error and the message to prosody internals.
2017-10-26 14:01:21 -05:00
Saúl Ibarra Corretgé
5308f78c9a [Android] Fix Android Studio 3.0 (final) 2017-10-26 10:04:52 +02:00
bbaldino
e2b812a7bc use central jitsi eslint config (#2108) 2017-10-25 16:02:14 -07:00
Saúl Ibarra Corretgé
a14cc60e30 [Android] Specify build tools version
Android Studio won't build the app otherwise. Since the gradle plugin 3.0 beta7,
the minimum supported build tools version is 26.0.2, so set it to that. Also
bump compileSdkVersion to 26 since they need to match (in the major number, that
is).

The target API is still 25. Android Oreo (26) brought some changes in overlay
permissions which I haven't figured out yet.
2017-10-25 15:16:09 -05:00
Saúl Ibarra Corretgé
84fd7825c1 [iOS] Import React headers in a consistent way 2017-10-25 14:53:45 -05:00
Saúl Ibarra Corretgé
ae0e37be34 [Android] Fix Android Studio 3.0 RC2 2017-10-25 16:17:23 +02:00
Lyubo Marinov
499ee7985b [RN] Fix redux state cleanup
The preceding commit "fix(auth.native): trigger conference left on
cancel" did not correctly clean the redux state up on CONFERENCE_LEFT.
2017-10-24 13:58:08 -05:00
paweldomas
dedd10c62a fix(auth.native): trigger conference left on cancel
Triggering the 'conference left' action when the wait for owner dialog
is dismissed will let the Call Kit implementation end the call, after
a recoverable conference failed event was emitted.

Also fixes conference state reduction when 'conference left' is emitted
by room lock or auth features where the conference has not been joined
yet.
2017-10-24 12:38:37 -05:00
Saúl Ibarra Corretgé
f1cc057bde Merge pull request #2079 from jitsi/update_strophe
ref(strophe): Remove and cleanup all strophe related code.
2017-10-24 16:21:12 +02:00
hristoterezov
a4e7f3d992 ref(strophe): Remove and cleanup all strophe related code.
Everything strophe related is now handled in lib-jitsi-meet project.
2017-10-23 16:27:30 -05:00
paweldomas
6890414bad fix(LoginDialog.web): 'states' is passed as undefined 2017-10-23 15:25:00 -05:00
Saúl Ibarra Corretgé
23550d377e feat(dark-theme): fix breakage on mobile
e09949be9f introduced the dark theme globally, but
it only applies to web, so move the logic to App.web.js
2017-10-23 09:12:31 -05:00
virtuacoplenny
205822ac31 Merge pull request #2077 from jitsi/device-changes
Fixes few changes around changing devices
2017-10-20 15:55:43 -07:00
damencho
7f7200b599 Fixes stopping desktop sharing when changing video device to use. 2017-10-20 17:25:58 -05:00
damencho
ade5290013 Fixes changing device unmutes you in a conference. 2017-10-20 17:25:44 -05:00
damencho
beffdb1e9b Fixes unplugging unused device mutes local audio and video. 2017-10-20 16:59:09 -05:00
virtuacoplenny
cd68a97b95 Merge pull request #2095 from jitsi/change-conn-hide-config
fix(config): Auto hide connection indicators by default
2017-10-20 14:19:00 -07:00
virtuacoplenny
56887eb2fa Merge pull request #2038 from jitsi/apply-dark-theme
feat(dark-theme): Applies dark theme on inline-dialogs, tooltips, flags and more
2017-10-20 13:56:43 -07:00
yanas
47d72c64c1 fix(config): Auto hide connection indicators by default 2017-10-20 15:44:20 -05:00
yanas
e09949be9f feat(dark-theme): Applies dark theme on inline-dialogs, tooltips, flags and more 2017-10-20 15:29:16 -05:00
virtuacoplenny
d3e8856896 Merge pull request #2094 from jitsi/device_selection_popup_error
Fix device selection popup
2017-10-20 13:15:31 -07:00
hristoterezov
96efa7759b fix(analytics): analytics undefined error due to circular dependency 2017-10-20 14:39:02 -05:00
virtuacoplenny
20d140a3ce Merge pull request #2090 from jitsi/desktop_picker_dialog
feat(desktop-picker): Add spinner and disable button if sources aren't initialized.
2017-10-20 12:37:30 -07:00
hristoterezov
c7b0028652 feat(desktop-picker): Add spinner and disable button if sources aren't initialized. 2017-10-20 13:52:48 -05:00
virtuacoplenny
40377634f2 Merge pull request #2091 from jitsi/remote_control_disable
fix(desktop_sharing): if remote control is disabled
2017-10-20 09:45:51 -07:00
hristoterezov
b869e53713 fix(desktop_sharing): if remote control is disabled 2017-10-20 10:51:12 -05:00
Lyubo Marinov
6f0fe06ba6 [RN] No CallKit failure on recoverable errors 2017-10-19 13:29:25 -05:00
Lyubo Marinov
4f2346aac9 [RN] CONFERENCE_FAILED with AUTHENTICATION_REQUIRED is recoverable
The feature authentication affords recovery from CONFERENCE_FAILED
caused by AUTHENTICATION_REQUIRED. (Like the feature room-lock afforded
recovery from CONFERENCE_FAILED caused by PASSWORD_REQUIRED.)
2017-10-19 13:25:44 -05:00
Lyubo Marinov
8948c837d3 Coding style 2017-10-18 13:21:46 -05:00
Lyubo Marinov
ce1a8e7567 [RN] Don't tell everyone we're called "me"
Recently/as part of the work on taking into account the user defined by
JWT, the local participant (on mobile) started telling the remote
participants that he/she had the display name "me". Obviously, that's
incorrect. Do not store the default display name in redux. While it may
be argues that redux is the place for all states, base/participants and
the name property of Participant is not meant to be that display name
because that is being sent to remote participants, the default name
needs to be internationalized, etc. So it's better to not store the
default display name at this time at all because it's not used by mobile
anyway and Web already deals with remote participants who don't share
their display names.
2017-10-18 13:15:49 -05:00
virtuacoplenny
095e4d7aa6 Merge pull request #2078 from jitsi/contactlist_displayname
fix(ContactListPanel): default display name
2017-10-18 09:12:47 -07:00
Saúl Ibarra Corretgé
bbfb7b8f21 Merge pull request #2081 from jitsi/clean_deps
chore(deps): remove unused.
2017-10-18 04:19:39 -07:00
hristoterezov
0b50578de9 style(analytics): sendEvent -> sendAnalyticsEvent 2017-10-17 19:33:32 -05:00
Lyubo Marinov
5e01abf6fb Flow, coding style 2017-10-17 17:12:39 -05:00
Lyubo Marinov
0205b9f49a Remove obsolete source code 2017-10-17 17:12:39 -05:00
Lyubo Marinov
a561d4f302 [RN] CONFERENCE_LEFT upon canceling PasswordRequiredPrompt 2017-10-17 17:12:39 -05:00
hristoterezov
c0162dcd81 chore(deps): remove unused. 2017-10-17 15:11:59 -05:00
paweldomas
8bddaeb6d7 fix(ContactListPanel): default display name 2017-10-17 14:17:27 -05:00
virtuacoplenny
9135f654ba Merge pull request #2067 from jitsi/cs-applicationName
Adds application name to the initJitsiConference options.
2017-10-17 10:42:24 -07:00
damencho
c3e42e0162 Adds application name to the initJitsiConference options. 2017-10-16 16:35:26 -05:00
damencho
654c5c44f4 Adds the displayName if available to the conference options on create. 2017-10-16 16:20:09 -05:00
Lyubo Marinov
5d313a8cd8 Coding style
A few occurrences of coding style/formatting which I noticed while
reviewing 'feat(eslint): Enable for non react files'. These are
definitely not all occurrences I could've noticed during the review
but... we're talking about files outside react/ anyway.
2017-10-16 15:37:13 -05:00
hristoterezov
969f5d67ab feat(eslint): Enable for non react files 2017-10-16 14:36:29 -05:00
damencho
b1b3807e9b Fixes display name for incoming chat messages, sender doesn't have nick. 2017-10-15 18:35:55 -05:00
Lyubo Marinov
003eb68e28 Flow, coding style 2017-10-13 14:34:09 -05:00
paweldomas
8a4e6a7ec0 feat: override email, display name and avatar on mobile
Will override email, display name and avatar URL with the values
provided in 'context.user' structure of the JWT token.

Settings will no longer be used to retrieve local display name,
email and avatar URL. Now those values will be obtained from
the /features/base/participants Redux state.

fix(jwt/middleware): use const for default name

fix: wrong default display name on web

ref(base/participants): remove getDisplayName functions

ref(jwt): do not accept unknown user fields
2017-10-13 14:31:44 -05:00
hristoterezov
0eddef4d62 feat(mute): Add analytics and console logs for audio/video mutes 2017-10-13 09:50:48 -05:00
hristoterezov
df1437f018 ref(analytics): Use analytics from features/analytics 2017-10-13 09:50:48 -05:00
hristoterezov
a3a871d4b3 fix(lib-jitsi-meet): Use the exported constants 2017-10-13 09:50:48 -05:00
hristoterezov
f050e7026d fix(media_actions): remove unused actions 2017-10-13 09:50:48 -05:00
damencho
64b11b571f Fixes error in case prosody host config is missing in conf.d folder. 2017-10-13 08:43:00 -05:00
Saúl Ibarra Corretgé
3c3b05e3ea Add ability to disable h264 (#2061)
* doc: document disableH264 option

* [RN] Override disableH264 config option

We never want it disabled on mobile.
2017-10-12 15:42:55 -07:00
Lyubo Marinov
da03b49754 Flow, coding style 2017-10-12 14:59:11 -05:00
paweldomas
122be9e0e0 ref: move 'jwt' feature to 'base' 2017-10-12 14:43:09 -05:00
Leonard Kim
887e1b6828 ref(info): be explicit when opening the dialog with a timeout
Instead of assuming the initial info dialog open should auto
close, explicitly call opening of the dialog with a flag for
auto closing. This better facilitates the auto close timeout
being set at any time.

The changes led to refactoring out state in the InfoDialogButton
in preference for always clearing the timeout instead of
first checking for interaction before clearing.
2017-10-11 15:51:58 -05:00
Leonard Kim
f539240840 fix(info): show dialog after joining the conference
Delay showing the dialog until after joining the conference
instead of as soon as possible. This resolves a few issues.
One is the dialog displaying right before the permissions
overlay is shown. Another is that logically it does not
make sense to show the invite options when unable to invite.
It also sidesteps the initial react UI bootstrapping that
can cause race conditions with toolbar re-renders causing
misalignment. Lastly, it prepares prematurely for what I
assume will be changes for when the info dialog will
actually be shown automatically.
2017-10-11 15:51:58 -05:00
Leonard Kim
323d38ac94 ref(conference): move mousemove handler to react 2017-10-11 15:51:58 -05:00
damencho
90451a640c Fixes sending logs to callstats.
When _setLoggingConfig is invoked for the first time old and new config
are equal and _initLogging is not called. Currently, there is no way to
detect when the first time we call it is. We could use APP.logCollector
but it should go away at some point in the future.
2017-10-11 15:04:22 -05:00
Saúl Ibarra Corretgé
9452f06b27 [RN] Use JWT callee name in CallKit
Fallback to the room name otherwise. This allows us to have better entries in
the phone history.
2017-10-11 13:05:18 -05:00
Lyubo Marinov
af53a5c48c [iOS] Fix iOS 9 after CallKit
Revert "[RN] Remove unnecessary source code" (commit
a3441030a3). But since the project file
needs to explicitly mention the CallKit and Intents framework, do not
use the semantic @import as that's confusing in the case.
2017-10-11 12:20:11 -05:00
Saúl Ibarra Corretgé
20a6a61b45 [iOS] Add icon for CallKit in-call UI 2017-10-11 09:15:44 -05:00
Leonard Kim
fafffb519b fix(filmstrip-only): prevent stats display 2017-10-10 12:47:19 -05:00
Saúl Ibarra Corretgé
8e59660f33 [iOS] Update Xcode project file
CocoaPods has made some updates to the bundled resource files.
2017-10-09 15:38:31 -05:00
Saúl Ibarra Corretgé
e25c38d716 Merge pull request #2045 from saghul/fix-fullscreen
[RN] Fix setting full-screen when joining a conference
2017-10-09 13:14:17 -05:00
Saúl Ibarra Corretgé
d57b0547f3 [RN] Fix setting full-screen when joining a conference
HIDE_DIALOG happens between WILL_JOIN and JOINED so get the joining conference
from the state instead of the action.
2017-10-09 11:13:01 -05:00
Lyubo Marinov
2d73e9ace4 Flow, coding style 2017-10-09 10:39:31 -05:00
Saúl Ibarra Corretgé
bb39ffe562 [RN] Fix selecting the local participant in the large view
Never show the local participant in the large view unless it's the only
participant.

This fixes 2 issues:

- selecting the local participant when the camera permission wasn't granted
- selecting the other participant when they join a 1-1 call with video muted
2017-10-09 10:39:31 -05:00
bgrozev
8b0cd310e3 Merge pull request #2042 from jitsi/prosody-config-update
Updates prosody config to have certificates for the auth. domain.
2017-10-09 10:18:02 -05:00
virtuacoplenny
5c819c7ffd Merge pull request #2043 from jitsi/fix-shared-video-popup
fix(defaultToolbarButtons): Fixes mute popup warning
2017-10-06 21:56:16 -07:00
yanas
dfe4e5e3a1 fix(defaultToolbarButtons): Fixes mute popup warning
Fixes exception when trying to unmute in the scenario, where someone else is sharing a video with you.
2017-10-06 17:13:49 -05:00
damencho
3e1cd6151d Updates prosody config to have certificates for the auth. domain.
The certificates are generated on new install or upgrade and added to the current configuration and also to the trusted certificates on the local machine.
2017-10-06 16:51:30 -05:00
Lyubo Marinov
5a5f6816c6 [RN] Leave Conference on room-lock "Password required" cancellation 2017-10-06 15:38:00 -05:00
Lyubo Marinov
2eb36c4053 Flow, coding style 2017-10-06 15:26:49 -05:00
Lyubo Marinov
d4d2cb4aad [RN] No CONFERENCE_FAILED in SDK for recoverable errors 2017-10-05 13:25:17 -05:00
Lyubo Marinov
c98e7a204c CONFERENCE_FAILED error as object 2017-10-05 13:25:17 -05:00
Lyubo Marinov
3d32c2de89 [RN] Secure entry, no automatic correction for room-lock passwords 2017-10-05 13:25:17 -05:00
Lyubo Marinov
7a7abdac2f [RN] Fix the submission of room-lock Dialogs 2017-10-05 13:25:17 -05:00
Lyubo Marinov
f53c79ab24 Flow, coding style 2017-10-05 13:25:17 -05:00
Leonard Kim
4c00d39bf2 fix(info): use openDialog to open AddPeopleDialog
openAddPeopleDialog() got removed so instead call openDialog
with the AddPeopleDialog.
2017-10-04 09:58:02 -05:00
Lyubo Marinov
cb514b90e9 Update NPM dependencies/packages 2017-10-03 20:45:43 -05:00
Lyubo Marinov
e0b73fdd1c [Android] Fix Android Studio 3.0 Beta 7 2017-10-03 20:45:43 -05:00
Lyubo Marinov
c2ca345dec [RN] Fix TypeError that getDefaultButtons is not a function 2017-10-03 17:26:13 -05:00
Lyubo Marinov
1834fc63d2 Fix incorrect React Component state assignment 2017-10-03 14:43:05 -05:00
Lyubo Marinov
5561a9c031 Partially prepare for eslint-plugin-flowtype 2.37.0 2017-10-03 14:41:54 -05:00
Lyubo Marinov
8f97da3265 flow-typed 2017-10-03 14:25:39 -05:00
bbaldino
1ef3e4b7dc Merge pull request #2024 from virtuacoplenny/lenny/no-resolution
ref(stats): do not modify stats object from lib
2017-10-03 10:50:39 -07:00
yanas
86fcfcc535 WiP(invite-ui): Initial move of invite UI to invite button (#1950)
* WiP(invite-ui): Initial move of invite UI to invite button

* Adjusts styling to fit both horizontal and vertical filmstrip

* Removes comment and functions not needed

* [squash] Addressing various review comments

* [squash] Move invite options to a separate config

* [squash] Adjust invite button styles until we fix the whole UI theme

* [squash] Fix the remote videos scroll

* [squash]:Do not show popup menu when 1 option is available

* [squash]: Disable the invite button in filmstrip mode

* feat(connection-indicator): implement automatic hiding on good connection (#2009)

* ref(connection-stats): use PropTypes package

* feat(connection-stats): display a summary of the connection quality

* feat(connection-indicator): show empty bars for interrupted connection

* feat(connection-indicator): change background color based on status

* feat(connection-indicator): implement automatic hiding on good connection

* fix(connection-indicator): explicitly set font size

Currently non-react code will set an icon size on ConnectionIndicator.
This doesn't work on initial call join in vertical filmstrip after
some changes to support hiding the indicator. The chosen fix is
passing in the icon size to mirror what would happe with full
filmstrip reactification.

* ref(connection-stats): rename statuses

* feat(connection-indicator): make hiding behavior configurable

The original implementation made the auto hiding of the indicator
configured in interfaceConfig.

* fix(connection-indicator): readd class expected by torture tests

* fix(connection-indicator): change connection quality display styling

Bold the connection summary in the stats popover so it stands out.
Change the summaries so there are only three--strong, nonoptimal,
poor.

* fix(connection-indicator): gray background on lost connection

* feat(icons): add new gsm bars icon

* feat(connection-indicator): use new 3-bar icon

* ref(icons): remove icon-connection and icon-connection-lost

Both have been replaced by icon-gsm-bars so they are not
being referenced anymore. Mobile looks to have connect-lost
as a separate icon in font-icons/jitsi.json.

* fix(defaultToolbarButtons): Fixes unresolved InfoDialogButton component problem

* [squash]: Makes invite button fit the container

* [squash]:Addressing invite truncate, remote menu position and comment

* [squash]:Fix z-index in horizontal mode, z-index in lonely call

* [squash]: Fix filmstripOnly property, remove important from css
2017-10-03 11:30:42 -05:00
Lyubo Marinov
dfebd692f3 eslint 4.8.0
ESLint 4.8.0 discovers a lot of error related to formatting. While I
tried to fix as many of them as possible, a portion of them actually go
against our coding style. In such a case, I've disabled the indent rule
which effectively leaves it as it was before ESLint 4.8.0.

Additionally, remove jshint because it's becoming a nuisance with its
lack of understanding of ES2015+.
2017-10-02 18:12:38 -05:00
Lyubo Marinov
d280f90676 Update NPM dependencies/packages 2017-10-02 18:12:37 -05:00
virtuacoplenny
1996ac4e02 Merge pull request #2023 from jitsi/remote_menu_analytics
feat(remote_menu): Add analytics
2017-10-02 14:41:28 -07:00
Lyubo Marinov
4bf19d73fd [RN] Fix documentation comments
* Javadoc introduced @code as a replacement of <code> and <tt> which is
  better aligned with other javadoc tags such as @link. Use it in the
  Java source code. If we switch to Kotlin, then we'll definitely use
  Markdown.

* There are more uses of @code in the JavaScript source code than <tt>
  so use @code for the sake of consistency. Eventually, I'd rather we
  switch to Markdown because it's easier on my eyes.

* Xcode is plain confused by @code and @link. The Internet says that
  Xcode supports the backquote character to denote the beginning and end
  of a string of characters which should be formatted for display as
  code but it doesn't work for me. <tt> is not rendered at all. So use
  the backquote which is rendered itself. Hopefully, if we switch to
  Markdown, then it'll be common between JavaScript and Objective-C
  source code.
2017-10-01 01:35:19 -05:00
Lyubo Marinov
b3cef401f2 [Android] Fix Android Studio 3.0 Beta 6 2017-10-01 00:18:25 -05:00
Leonard Kim
eb1a44f5ba ref(stats): do not modify stats object from lib
This is more of a principle change than a necessary one.
In lib-jitsi-meet, when a getStats call finishes, the
stats are processed and first emitted (and received by
jitsi-meet) and then processed again for sending to
remote participants. Modifying the stats in place changes
the structure of stats before the second processing,
which maybe be unexpected.
2017-09-29 18:41:49 -07:00
hristoterezov
29d1d448f2 feat(remote_menu): Add analytics 2017-09-29 16:27:53 -05:00
virtuacoplenny
cfe4564ab3 feat(info): automatically show the info dialog (#2018)
* ref(info): be able to open dialog through store

* feat(info): automatically show the info dialog

Conditions:
- Lonely call
- Has not opened the info dialog yet

* squash: change to show on start, hide later

* squash: update naming and comment
2017-09-29 15:27:23 -05:00
virtuacoplenny
802d347574 ref(contact-list): remove invite functionality (#2017)
* ref(contact-list): remove invite functionality

Removing becuase there is already a toolbar button dedicated
to opening the invite dialog. Now the contact list focuses
on showing current participants.

* squash: remove unused strings and styling

* squash: add plural to panel title
2017-09-29 13:29:44 -05:00
Lyubo Marinov
a3441030a3 [RN] Remove unnecessary source code 2017-09-29 12:43:42 -05:00
Lyubo Marinov
3b5ee2d4c6 [iOS] Add initial CallKit support 2017-09-29 12:00:13 -05:00
Saúl Ibarra Corretgé
8d11b3024e [iOS] Add initial CallKit support
This commit adds initial support for CallKit on supported platforms: iOS >= 10.

Since the call flow in Jitsi Meet is basically making outgoing calls, only
outgoing call support is currently handled via CallKit.

Features:
 - "Green bar" when in a call.
 - Native CallKit view when tapping on the call label on the lock screen.
 - Support for audio muting from the native CallKit view.
 - Support for recent calls (audio-only calls logged as Audio calls, others show
   as Video calls).
 - Call display name is room name.
 - Graceful downgrade on systems without CallKit support.

Limitations:
 - Native CallKit view cannot be shown for audio-only calls (this is a CallKit
   limitaion).
 - The video button in the CallKit view will start a new video call to the same
   room, and terminate the previous one.
 - No support for call hold.
2017-09-28 16:36:39 -05:00
Lyubo Marinov
2e2129fa44 Import PropTypes from prop-types
Prepare for React 16.
2017-09-27 16:24:53 -05:00
ibauersachs
9834e8ac7b Commit from translate.jitsi.org by user ibauersachs.: 384 of 385 strings translated (0 fuzzy). 2017-09-27 20:25:04 +00:00
Lyubo Marinov
e1222e947b [RN] Documentation, comments 2017-09-27 13:08:37 -05:00
Saúl Ibarra Corretgé
341e7e01aa [RN] Add the ability to set the default URL in the SDK 2017-09-27 11:59:00 -05:00
Lyubo Marinov
964061fa5c [RN] Make it easier to disable yellow and red boxes in Debug 2017-09-27 11:23:35 -05:00
Saúl Ibarra Corretgé
b8a629ead6 [RN] Don't hardcode app name when sharing a room 2017-09-27 11:02:43 -05:00
Lyubo Marinov
b55faab33e Coding style 2017-09-27 11:01:27 -05:00
Saúl Ibarra Corretgé
3fdffa7497 [RN] Add AppInfo module
It provides access to the app's display name and version.
2017-09-27 10:32:07 -05:00
Lyubo Marinov
d521deecc4 Coding style 2017-09-26 23:39:30 -05:00
Saúl Ibarra Corretgé
d03a815572 [RN] Add ability to start a call in audio-only mode 2017-09-26 23:39:30 -05:00
Lyubo Marinov
41c6759a23 Coding style 2017-09-26 23:39:30 -05:00
Saúl Ibarra Corretgé
f62288ae17 feat(conference): add helper function to check for audio-only muted status 2017-09-26 23:39:30 -05:00
virtuacoplenny
98aa0b6ad9 Merge pull request #2019 from jitsi/local_storage_error
fix(JitsiLocalStorage): Handle local storage error
2017-09-26 15:10:59 -07:00
hristoterezov
01031ff0a7 fix(JitsiLocalStorage): Handle local storage error 2017-09-26 16:14:07 -05:00
Leonard Kim
eae3bead87 fix(toolbar): fix proptype warning
The implementation of ToolbarButtonWithDialog expects a
constructor function for now, not the object returned
from calling a constructor function.
2017-09-26 11:56:43 -05:00
virtuacoplenny
483e2ee202 feat(connection-indicator): implement automatic hiding on good connection (#2009)
* ref(connection-stats): use PropTypes package

* feat(connection-stats): display a summary of the connection quality

* feat(connection-indicator): show empty bars for interrupted connection

* feat(connection-indicator): change background color based on status

* feat(connection-indicator): implement automatic hiding on good connection

* fix(connection-indicator): explicitly set font size

Currently non-react code will set an icon size on ConnectionIndicator.
This doesn't work on initial call join in vertical filmstrip after
some changes to support hiding the indicator. The chosen fix is
passing in the icon size to mirror what would happe with full
filmstrip reactification.

* ref(connection-stats): rename statuses

* feat(connection-indicator): make hiding behavior configurable

The original implementation made the auto hiding of the indicator
configured in interfaceConfig.

* fix(connection-indicator): readd class expected by torture tests

* fix(connection-indicator): change connection quality display styling

Bold the connection summary in the stats popover so it stands out.
Change the summaries so there are only three--strong, nonoptimal,
poor.

* fix(connection-indicator): gray background on lost connection

* feat(icons): add new gsm bars icon

* feat(connection-indicator): use new 3-bar icon

* ref(icons): remove icon-connection and icon-connection-lost

Both have been replaced by icon-gsm-bars so they are not
being referenced anymore. Mobile looks to have connect-lost
as a separate icon in font-icons/jitsi.json.
2017-09-26 11:55:09 -05:00
Lyubo Marinov
e08d240a89 [RN] Render bold text in WaitForOwnerDialog 2017-09-25 14:42:15 -05:00
Lyubo Marinov
f9f194d6fe Coding style 2017-09-25 12:46:22 -05:00
Lyubo Marinov
cfd6209a20 [Android] Work around fetch-induced app breakage 2017-09-25 12:46:22 -05:00
Lyubo Marinov
03d337612b [Android] Hardware back in Conference and Dialog 2017-09-25 12:33:35 -05:00
Leonard Kim
46b75e5178 ref(info): new component for showing meeting info 2017-09-25 08:42:00 -05:00
Lyubo Marinov
266d8f72c5 [RN] Reduce authentication actions 2017-09-25 00:23:15 -05:00
paweldomas
9ae26a087e feat(auth): add UPGRADE_ROLE_LOGIN_OK action 2017-09-25 00:09:25 -05:00
hristoterezov
66da77bcf5 fix(profile_button): unclickable 2017-09-24 21:50:30 -05:00
Lyubo Marinov
70de9a683f [RN] Prepare for LoadingIndicator in LoginDialog 2017-09-24 17:25:58 -05:00
Lyubo Marinov
4e0761a46a CONNECTION_FAILED error as object
Gradually, we exploded the error of CONNECTION_FAILED in multiple
redux state properties. The explosion makes maintenance harder because
the properties have to be updated in sync. Collect them in an object
resembling an Error instance.
2017-09-24 16:51:43 -05:00
paweldomas
f8b607e92e fix(LoginDialog.native): no 'password incorrect' initially
Do not show the 'Password is incorrect' message when the LoginDialog
opens for the first time.
2017-09-24 14:25:03 -05:00
jitsi-pootle
da3e59571e New files added from translate.jitsi.org based on templates 2017-09-24 13:42:12 +00:00
virtuacoplenny
c196f8007b Merge pull request #2008 from jitsi/videoquality_label
fix(videoquality_label): tooltip text for audio only mode
2017-09-22 16:14:44 -07:00
hristoterezov
c5436428e5 fix(videoquality_label): tooltip text for audio only mode 2017-09-22 17:18:14 -05:00
paweldomas
628dc99bfe fix(conference/reducer): clear 'authRequired' on connection will connect
It is required to clear the flag, before the connection attempt.
Otherwise the app may confuse deployments without guest access with
a one with guess access if it was visited previously and
the WaitForOwnerDialog was canceled. That's because there will be no
conference related event that clears the flag.
2017-09-22 16:47:59 -05:00
Lyubo Marinov
a12984ed6f [RN] Power to Dialog
* Implement disabling buttons (like Web had the ability).
* Use consistent colors (e.g. for the buttons) like the rest of the app
  (e.g. WelcomePage).
* Enable AbstractDialog to await a thenable from onSubmit and Dialog to
  render a LoadingIndicator in place of the OK/submit button text.
2017-09-22 15:09:15 -05:00
Lyubo Marinov
1ea62215f6 [RN] Increase contrast and consistency in LoadingIndicator use cases 2017-09-22 15:07:06 -05:00
Lyubo Marinov
6fb5c4bc29 Fix jsdocs 2017-09-22 15:01:51 -05:00
paweldomas
b5212bb6cd fix(WaitForOwnerDialog): undefined method and reg expr 2017-09-22 09:29:17 -05:00
Lyubo Marinov
ec58aa9959 [Android] Implement DefaultHardwareBackBtnHandler
* Regardless of whether the SDK client/consumer employs
  JitsiMeetActivity or JitsiMeetView, default to finishing the
  associated Activity upon invoking the back button (which is what
  Activity#onBackPressed() is documented to do).

* Do not break the public API of JitsiMeetView and, thus, Jitsi Meet SDK
  for Android.
2017-09-21 23:57:16 -05:00
paweldomas
35dab19b30 [Android] Implement DefaultHardwareBackBtnHandler
If the JS side chooses to not handle the back button press call
'super.onBackPressed()' to close the app.
2017-09-21 23:56:43 -05:00
Saúl Ibarra Corretgé
720ae18194 [RN] LoadingIndicator while joining a conference 2017-09-21 16:15:14 -05:00
Paweł Domas
e553e61f04 feat(AddPeopleDialog): invite rooms (#2001)
* feat(AddPeopleDialog): invite rooms

Distinguish between 'user' and 'videosipgw' search result items and
invite them with using different method.

* squash: fix typo in AddPeopleDialog.web.js
2017-09-21 13:24:56 -07:00
Emil Ivov
a0a4fbf566 Instructions for Let's encrypt 2017-09-21 00:36:38 -05:00
Saúl Ibarra Corretgé
ca13a9b914 [RN] LoadingIndicator on WelcomePage
It will replace the "Join" text button while appNavigate lasts.

Note about the implementation: when appNavigate completes the component
may have been unmounted and thus we cannot touch its state. In order to
avoid this problem I added a 'mounted' instance variable which gets set
and reset in componentWillMount / Unmount respectively. This is to avoid
using isMounted, which is highly discouraged.
2017-09-20 16:01:49 -05:00
Saúl Ibarra Corretgé
35da39becf [RN] NetworkActivityIndicator
The basic indicator is extracted into a LoadingIndicator component,
which then NetworkActivityIndicator displays (or not) based on network
activity.
2017-09-20 15:59:56 -05:00
Leonard Kim
21d419e517 fix(pinning): bind the callback for contact list clicking 2017-09-20 10:35:29 -07:00
Lyubo Marinov
6a1eff917c Adds os and version to react-native userAgent. 2017-09-20 10:05:07 -05:00
damencho
6d62e91ff1 Adds os and version to react-native userAgent. 2017-09-20 09:08:21 -05:00
Lyubo Marinov
241dc3b147 [RN] Support XMPP authentication 2017-09-19 23:04:45 -05:00
paweldomas
141acea194 [RN] Support XMPP authentication 2017-09-19 14:38:45 -05:00
paweldomas
80329e8ffe [RN] CONFERENCE_FAILED error message in redux
In order to support XMPP authentication, we'll need the message
accompanying the error and carried by lib-jitsi-meet's
CONFERENCE_FAILED in the redux store. We already carry the message in
the redux action and we've got the error in the redux store.
2017-09-19 14:37:09 -05:00
paweldomas
9621ba03f3 feat(overlay): Clear redux state on CONNECTION_WILL_CONNECT 2017-09-19 14:36:31 -05:00
virtuacoplenny
04a1da2cea Merge pull request #1995 from jitsi/fix-local-thumbnail
fix(Filmstrip.js): Make sure the local thumbnail is there
2017-09-19 12:24:26 -07:00
virtuacoplenny
bd24135d76 Merge pull request #1990 from jitsi/fix-chat-disabled
fix(conference.js): Add message listeners only when chat is enabled
2017-09-18 19:58:09 -07:00
yanas
0c08f96755 fix(Filmstrip.js):Make sure the local thumbnail is there before getting the height 2017-09-18 17:26:24 -05:00
yanas
984085ac54 fix(conference.js): Add message listeners only when chat is enabled 2017-09-18 16:29:03 -05:00
Lyubo Marinov
9c47a7e972 Add Dialog utilities
In order to accommodate the requirements of the work on supporting XMPP
authentication on mobile/react-native, make dealing with Dialog a
little more generic and a little easier.
2017-09-18 16:00:00 -05:00
Leonard Kim
088fe87e31 fix(dominant-speaker): update dominant speaker in redux
Without dominant speaker in redux, the wrong user will be
selected after an unpin event.
2017-09-18 15:00:00 -05:00
Leonard Kim
f3783efc48 squash: remove unused prop, update comment 2017-09-18 13:22:15 -05:00
Leonard Kim
1e84f993b4 fix(device-selection): use non-connect video preview
Filmstrip only mode displays a device selection dialog that
does not have access to the redux/connect. However, the current
VideoTrack extends from AbstractVideoTrack, which assumes a
redux connection. The fix is to move video display logic into
a separate component and have device selection use that, while
the existing VideoTrack remains connected to redux but
uses the new video display component.
2017-09-18 13:22:15 -05:00
Lyubo Marinov
03b4a32dd7 Coding style 2017-09-18 11:21:45 -05:00
paweldomas
70fc727b92 [RN] Prevent a possible TypeError 2017-09-18 09:48:53 -05:00
Lyubo Marinov
d0476991a6 [RN] Support children in Dialog 2017-09-18 02:12:27 -05:00
Lyubo Marinov
2496b3ec02 [Android] Don't require camera, autofocus
Don't require autofocus because that prevents the app from appearing in
Google Play Store for some devices.

Don't require camera for the same reason but also because camera/video
is not a mandatory feature of the app, it's merely likely very
desirable.
2017-09-14 12:16:46 -05:00
Lyubo Marinov
bf915fe886 Coding style, formatting 2017-09-14 12:14:54 -05:00
Saúl Ibarra Corretgé
46ccefdfe9 feat(external_api): set permissions for cross-origin iframe
In Chrome M63 a warning is shown, permissions won't be automatically allowed
afterwards. Reference:
https://sites.google.com/a/chromium.org/dev/Home/chromium-security/deprecating-permissions-in-cross-origin-iframes

Setting this early makes us future proof, while working with current versions
too: Chrome < 63 gives an error because it doesn't understand the option and
Firefox seems to ignore it, so both continue to work as before.
2017-09-13 15:38:30 -05:00
Lyubo Marinov
f86f21beb2 [Android] Fix VerifyError on Android 4
The class ReflectiveOperationException used in ExternalAPIModule was
introduced in API level 19.
2017-09-13 14:32:32 -05:00
Saúl Ibarra Corretgé
fe8f383a41 [Android] Update gradle plugin version for Android Studio 3 beta 5 2017-09-13 14:35:21 +02:00
Lyubo Marinov
72c9933e73 [RN] SDK building, installing, and publishing
Based on work authored by Shuai Li <sli@atlassian.com>, Daniel Ornelas
<dornelas@atlassian.com>, and Lyubo Marinov <lmarinov@atlassian.com>.
2017-09-11 20:12:56 -05:00
Leonard Kim
4b2795502c fix(contact-list): call getAvatarURL directly
Instead of going through the Avatar object, call the getAvatarURL
directly so that the code flows consistently use the participant
representation within redux.
2017-09-11 11:33:22 -05:00
Leonard Kim
082fe711f2 fix(contact-list): enable avatars by default 2017-09-11 11:33:22 -05:00
Saúl Ibarra Corretgé
ba49c7955a [Android] Fix gradle and plugin versions with Android Studio 3.0 Beta 4 2017-09-08 10:47:08 +02:00
Lyubo Marinov
354fa36f44 Update npm dependencies/package versions 2017-09-07 20:11:45 -05:00
Lyubo Marinov
2a75d67be9 Webpack with scope hoisting 2017-09-07 20:06:34 -05:00
Lyubo Marinov
5e6cea63fb [RN] Polyfill sessionStorage via Storage 2017-09-07 12:49:35 -05:00
Lyubo Marinov
0d3927fed1 Coding style 2017-09-07 12:49:35 -05:00
Lyubo Marinov
9049f52402 [RN] Allow share-room ToolbarButton to not be rendered 2017-09-07 12:49:35 -05:00
Lyubo Marinov
c2ae7999ef Coding style
In certain scenarios we do need to import files instead of features but
even then it is our coding style to not write the file extension.
2017-09-07 12:49:35 -05:00
Leonard Kim
5a50932174 fix(contact-list): fix typo in empty file name 2017-09-07 10:54:22 -05:00
Lyubo Marinov
53e1160a1c [webpack-dev-server] Serve more local resources/files 2017-09-07 09:34:53 -05:00
Lyubo Marinov
15ab7a292c Reduce the dependencies of the Web ExternalAPI
We broke external_api.min.js by importing react/features/util which
imported react/features/base/lib-jitsi-meet.

1. To reduce the risks of such a breakage until we add
   external_api.min.js to the torture tests, import as little as
   possible in modules/API/external/external_api.js.
2. Use the global JitsiMeetJS on Web in react/features/base/util.
2017-09-06 23:20:04 -05:00
Lyubo Marinov
fce0e4c22c [RN] Report loadConfigError with locationURL to the SDK consumers 2017-09-06 20:34:46 -05:00
Lyubo Marinov
4dc78ce458 [RN] Increase the coverage of JitsiMeetViewListener
JitsiMeetViewListener is an integral part of the public API of Jitsi
Meet SDK for Android. Utilize it in the Debug configuration of the Jitsi
Meet app for Android in order to increase (1) awareness of API breakages
and (2) API coverage.

The same goes for JitsiMeetViewDelegate in Jitsi Meet SDK and app for
iOS.
2017-09-06 16:31:15 -05:00
Lyubo Marinov
67edaac1c9 [RN] Coding style 2017-09-06 16:31:15 -05:00
Lyubo Marinov
e830b80b6b [RN] Fix documentation 2017-09-06 16:31:15 -05:00
Saúl Ibarra Corretgé
284e4e543e [RN] Detect errors when loading the configuration
The error is stored in the redux store in base/config so other components can
consult it. It is also broadcasted as a new event in the external API for the
SDK.
2017-09-06 16:31:14 -05:00
Lyubo Marinov
1d8ee9d32f [RN] Reduce maintenance
JitsiMeetViewListener currently has methods of one and the same pattern
so adding new methods i.e. events i.e. redux action types is a question
of repetition in the Java source code. Speed up the support of new
events by trying to deal with them in a generic way.

The same goes for JitsiMeetViewDelegate.
2017-09-06 15:57:00 -05:00
Lyubo Marinov
6982506acc [RN] Remove duplication 2017-09-06 14:48:53 -05:00
Lyubo Marinov
d818436645 [RN] Fix import breakage caused by Web 2017-09-06 14:39:34 -05:00
Leonard Kim
31729d7949 feat(contact-list): convert to react
- Remove references to the model ContactList.
- Replace ContactListView with an empty element for attaching
  the React Component ContactListPanel, which has the same
  features as the old ContactListView.
- Create new selector for getting non-fake participants for
  ContactListPanel's props.
- Create a ParticipantCounter component to place in the contact
  list button. Previously ContactListView updated that but now
  it's a react component hooked into the participant state.
- Remove pub/sub that was used only by ContactListView.
2017-09-06 12:11:33 -05:00
Lyubo Marinov
ed53f54628 [RN] Fix the visibility of the local video on the WelcomePage 2017-09-06 08:22:39 -05:00
Saúl Ibarra Corretgé
9833965a27 [RN] Extract a function 2017-09-05 22:49:22 -05:00
Lyubo Marinov
8cdd73b987 [RN] Reverts to own properties for Storage 2017-09-05 18:55:54 -05:00
Lyubo Marinov
a7ee632f43 [RN] LocalVideoTrackUnderlay
Implement a React Component which displays children as an overlay of
local video. The WelcomePage implemented such a component inside of it
among other WelcomePage-specific logic so I split
LocalVideoTrackUnderlay out of it. The new Component is used on the
BlankPage which may be displayed in the future not only when the
WelcomePage is disabled but also when there are long running network
requests, for example.
2017-09-05 17:45:20 -05:00
Lyubo Marinov
b304ad5808 [RN] Weaken the coupling between WelcomePage and AbstractWelcomePage 2017-09-05 16:27:12 -05:00
Lyubo Marinov
86e4876df2 Coding style 2017-09-05 15:56:59 -05:00
Saúl Ibarra Corretgé
034518a6a0 [RN] Cache configurations in localStorage
This only helps iff there is a short transient network error which prevents the
configuration from being loaded. In such case, use the cached version in
localStorage, which may not match the shard, but it's (probably!) better than
nothing.

In case there is no Internet connectivity, an error will be produced as soon as
the XMPP connection is attempted anyway.
2017-09-05 14:58:26 -05:00
Lyubo Marinov
bf523711df [RN] Prepare to polyfill sessionStorage 2017-09-05 13:56:33 -05:00
Saúl Ibarra Corretgé
bfeaf329e1 [RN] Add polyfill for localStorage
It's built on top of React Native's AsyncStorage. They have differing APIs, so
we implement a synchronous API on top of an asynchronous one. This is done by
being optimistic and hoping that operations will happen asynchronously. If one
such operation fails, the error is ignored and life goes on, since operations
are performed in the in-memory cache first.

Note to reviewers: LocalStorage.js lacks Flow annotations because indexable
class declarations are not yet supported:
https://github.com/facebook/flow/issues/1323 and yours truly couldn't find a way
to make the required syntax work without making it unnecessarily complex.
2017-09-05 10:42:42 -05:00
Saúl Ibarra Corretgé
0e234bfd82 doc: mention "npm install" is required on mobile
Specially prior to pod install.
2017-09-05 11:00:40 +02:00
Saúl Ibarra Corretgé
8fc095039e analytics: lower log severity when we fail to create a handler
It'snot the end of the world, we can move on.
2017-09-05 10:48:57 +02:00
Saúl Ibarra Corretgé
eca04de348 Simplified code 2017-09-04 11:35:09 +02:00
Saúl Ibarra Corretgé
18d1572dab [RN] Load config.js only when the room is known
This patch loads the config later than we used to, that is, only once we
know the room the user is about to join.

Due to architectural limitations in lib-jitsi-meet, it needs to be
initialized with a configuration in order to properly function. This is
unfortunate because we need to create a video track in the welcome page,
but don't know the room (hence no config) yet. In order to circumvent
this problem an empty configuration is used, which is later swapped with
the appropriate one, once loaded.

Some interesting side-effects of this change are a perceived speed
increase when the app starts or a conference is hangup. They are both
due to the fact that no config needs to be fetched from a remote server
in those cases.
2017-09-02 13:26:07 -05:00
Lyubo Marinov
45a1ae26ca [RN] Prepare to display BlankPage more
For example, while config.js and other files are being loaded before the
navigation to Conference is feasible.
2017-09-02 13:26:06 -05:00
Lyubo Marinov
6545a7a1bb Remove duplication 2017-09-01 23:55:25 -05:00
Lyubo Marinov
ec9c05e401 [RN] Load config.js with ?room=
In order to load the configuration from the shard that will actually
host the conference, it's imperative that we add the room= query
parameter:

https://meet.jit.si/config.js?room=example

This implies a departure from our current model, where the config is
discarded if the domain for the next conference is different, but kept
otherwise.
2017-09-01 23:55:25 -05:00
virtuacoplenny
bf03e73876 feat(filmstrip): show thumbnails with toolbar and on hover (#1944)
* feat(filmstrip): show thumbnails with toolbar and on hover

* squash: reduce verbosity of logic for when to display

* squash: remove check for fake participant

Before fake participant (youtube video) would make the filmstrip
always displayed. However, youtube videos already dock the
toolbar, so filmstrip will remain displayed, so the check is
redundant.

* squash: change mouse hover listener targets
2017-09-01 16:40:05 -05:00
Дамян Минков
6682543691 Moves analytics loading to react. (#1945)
* feat(analytics): move to React

The analytics handlers have been moved to JitsiMeetGlobalNS, so now they are
stored in `window.JitsiMeetJS.app.analyticsHandlers`.

The analytics handlers are re-downloaded and re-initialized on every
lib-jitsi-meet initialization, which happens every time the config is changed
(moving between deployments in the mobile app).

* Adds legacy support for old analytics location.
2017-09-01 14:14:03 -05:00
Lyubo Marinov
8d81f1d69f Update npm dependencies/package versions 2017-08-31 20:08:12 -05:00
Lyubo Marinov
8436f23e05 Comments 2017-08-31 19:31:46 -05:00
Leonard Kim
2ae354530e fix(contact-list): remove parens from member count string 2017-08-31 16:21:31 -05:00
Leonard Kim
4938d1b6de fix(contact-list): update avatar sizing
With interfaceConfig.SHOW_CONTACTLIST_AVATARS, the avatars in the
contact list are too big and will overlap each other. Constrain
the avatar sizes and make each contact a little taller to better
space each out.
2017-08-31 16:21:31 -05:00
hristoterezov
cd3dad956b fix(peopleSearch): queryTypes are defined in config.js 2017-08-31 15:04:29 -05:00
Saúl Ibarra Corretgé
328da08b3a [RN] Remove obsolete comment
We have already made the implicit decision not to pursue what the
comment describes. If we ever revisit it, it probably won't be handled
where the comment is anyway.
2017-08-31 11:50:18 -05:00
virtuacoplenny
a94e38e890 Merge pull request #1951 from jitsi/watermark-config
Make watermark size configurable
2017-08-30 13:01:37 -07:00
yanas
b9f2ab7692 Make watermark size configurable 2017-08-30 14:01:41 -05:00
Leonard Kim
05f8c69fe6 ref(toolbar): add wrapper around buttons for torture tests
The torture tests were looking for the anchor tag within each
button. However, that anchor could get blown away from a react
re-render. So instead, expose a way for the torture tests
to find the root node of the button.
2017-08-30 11:31:15 -05:00
Leonard Kim
7063f144ef feat(tooltips): add for video quality label and feedback button 2017-08-30 11:10:28 -05:00
Leonard Kim
af92ba5e86 fix(toolbar): push buttons further from top of side toolbar 2017-08-30 11:10:28 -05:00
Leonard Kim
5e4f921e1b ref(video-quality-label): do not show quality dialog 2017-08-30 11:10:28 -05:00
Leonard Kim
126f8e6d88 ref(strings): change user-facing references of "participant" to "member" 2017-08-30 11:10:28 -05:00
Lyubo Marinov
7f8e8177d0 [RN] Refactor "Keep track of ongoing network requests" and "Show a progress indicator in the BlankPage"
I'm not saying that the two commits in question were wrong or worse than
what I'm offering. Anyway, I think what I'm offering brings:

* Compliance with expectations i.e. the middleware doesn't compute the
next state from the current state, the reducer does;

* Clarity and/or simplicity i.e. there's no global variable (reqIndex),
there's no need for the term "index" (a.k.a "reqIndex") in the redux
store.

* By renaming net-interceptor to network-activity feels like it's
preparing the feature to implement a NetworkActivityIndicator React
Component which will take on more of the knowledge about the specifics
of what is the network activity redux state exactly, is it maintained by
interception or some other mechanism, and abstracts it in the feature
itself allowing outsiders to merely render a React Component.
2017-08-29 18:54:04 -05:00
Saúl Ibarra Corretgé
e33030582f [RN] Show a progress indicator in the BlankPage
It will only be shown when there are ongoing network requests.
2017-08-29 18:54:04 -05:00
Saúl Ibarra Corretgé
d669a6c73c [RN] Keep track of ongoing network requests
Works only for XHR requests, which is the only network request mobile performs
(WebRTC traffic aside). The fetch API is implemented on top of XHR, so that's
covered too.

Requests are kept in the redux store until they complete, at which point they
are removed.
2017-08-29 18:54:04 -05:00
Saúl Ibarra Corretgé
8eebfcad72 [RN] Add support for callstats on mobile
The global.performance.now polyfill is removed since it's polyfilled by
react-native-callstats.
2017-08-29 18:47:35 -05:00
virtuacoplenny
ef1b8fdb77 ref(1-on-1): move remote video visibility to a selector (#1922)
* ref(1-on-1): move remote visibility to a selector

Derive whether or not remote videos should display using a selector
to look across different states. A selector was chosen over using
memoized selectors (reselect) or subscribers as a first step
approach, avoiding additional mutations caused by a subscriber
updating the filmstrip state and avoiding additional api overhead
introduced by reselect.

* rename selector
2017-08-29 10:08:16 -05:00
Saúl Ibarra Corretgé
c0f648b1ab [RN] Remove no longer needed fetch API fallback 2017-08-29 10:30:09 +01:00
Saúl Ibarra Corretgé
531b638a8a [RN] Switch default avatars to meeples 2017-08-29 09:27:28 +01:00
Saúl Ibarra Corretgé
4e3d033ff2 deps: use latest jsSHA
callstats no longer depends on it and it doesn't break when we use the latest.
2017-08-28 18:52:51 -05:00
virtuacoplenny
77e8c75795 Merge pull request #1939 from bbaldino/edge_fixes
few tweaks to fix some exceptions in edge
2017-08-28 15:56:04 -07:00
Saúl Ibarra Corretgé
9559df1b13 Merge pull request #1940 from jitsi/fix_aot
fix(external_api): isAudioMuted and isVideoMuted
2017-08-29 00:26:21 +02:00
hristoterezov
f93c1b5748 fix(external_api): isAudioMuted and isVideoMuted 2017-08-28 16:56:27 -05:00
bbaldino
f616b0b71b few tweaks to fix some exceptions in edge 2017-08-28 21:52:52 +00:00
hristoterezov
70422f4a47 fix(alwaysontop): change the size of the toolbar 2017-08-28 14:52:31 -05:00
virtuacoplenny
735a596afe ref(recording): convert recording label to react (#1915)
* ref(recording): convert recording label to react

- Create a RecordingLabel component for displaying the current
  recording state, as reflected in the redux store. This is
  needed for 1-on-1 mode to be completely in redux.
- Update the store with the recording state so RecordingLabel
  can update itself.
- Remove previous logic for updating the non-react label, which
  includes event emitting for filmstrip visibility changes,
  as RecordingLabel is hooked into redux updates.

* ref(recording): use status and type constants from lib

* make label really dumb, move logic back to Recording
2017-08-25 11:45:30 -05:00
Saúl Ibarra Corretgé
e04129bf4d Merge pull request #1916 from virtuacoplenny/lenny/no-custom-debounce
ref(toolbar): replace custom debounce with lodash throttle
2017-08-25 15:31:16 +02:00
Leonard Kim
85f0ad2791 feat(popover): create a wrapper around InlineDialog 2017-08-24 22:00:14 -05:00
Leonard Kim
c54879d605 fix(video-quality-label): push around z-indexes for firefox 2017-08-24 22:00:14 -05:00
Leonard Kim
fdee6dc360 fix(inline-dialog): reimplement popover display on mouse move
Create empty elements within InlineDialog content that can be
used to bridge mouse movement from the InlineDialog trigger to
the InlineDialog content. The empty elements are positioned
absolute so they can break out of the InlineDialog container
and not affect popper's position calculations.
2017-08-24 22:00:14 -05:00
Saúl Ibarra Corretgé
5f55b3198c [Android] Update gradle plugin version for Android Studio 3 beta 2 2017-08-24 15:04:31 +02:00
Дамян Минков
5b6d7a3040 Skips creating duplicate poltergeists for the same user. (#1925) 2017-08-23 16:14:44 -05:00
virtuacoplenny
1ca485f1a8 Merge pull request #1924 from jitsi/status-message-clear
Skips showing empty statuses. Updates poltergeist to report connected.
2017-08-23 14:12:02 -07:00
damencho
6e37fe175d Skips showing empty statuses. Updates poltergeist to report connected. 2017-08-23 14:10:10 -05:00
Lyubo Marinov
24db52ef0f [RN] Remove denied permission alert from WelcomePage 2017-08-22 16:38:14 -05:00
Lyubo Marinov
0b8c12de0e Simplify route navigation
I see it as the first step in simplifying the route navigate of the
JavaScript app by removing BlankWelcomePage from _getRouteToRender. From
a faraway point of view, the app is at the route at which it is not in a
conference. Historically, the route was known as the Welcome page. But
mobile complicated the route by saying that actually it may not want to
see the room name input and join button.

Additionally, I renamed BlankWelcomePage to BlankPage because I don't
think of it as a WelcomePage alternative but rather as a more generic
BlankPage which may be utilized elsewhere in the future.

I plan for the next steps to:
* Merge Entryway, _interceptComponent, and _getRouteToRender in one
React Component rendered by AbstractApp so that the whole logic is in
one file;
* Get rid of RouteRegistry and routes.
2017-08-22 16:38:14 -05:00
Lyubo Marinov
cb5b93fb6e Switch to prop-types 2017-08-22 16:38:14 -05:00
Lyubo Marinov
7114614697 Remove obsolete workaround 2017-08-22 16:38:14 -05:00
Aaron van Meerten
45b8693a3e Merge pull request #1921 from jitsi/rayo_filter_subdomains_support
Adds multidomain support to rayo filter module.
2017-08-22 15:22:08 -05:00
damencho
360283aa34 Adds multidomain support to rayo filter module. 2017-08-22 15:00:40 -05:00
ibauersachs
fb556edb9d Commit from translate.jitsi.org by user ibauersachs.: 339 of 379 strings translated (1 fuzzy). 2017-08-22 19:40:36 +00:00
ibauersachs
28e5230472 Commit from translate.jitsi.org by user ibauersachs.: 117 of 379 strings translated (19 fuzzy). 2017-08-22 19:40:30 +00:00
ibauersachs
73ea42f49f Commit from translate.jitsi.org by user ibauersachs.: 297 of 379 strings translated (7 fuzzy). 2017-08-22 19:40:24 +00:00
ibauersachs
255ddbd344 Commit from translate.jitsi.org by user ibauersachs.: 307 of 379 strings translated (6 fuzzy). 2017-08-22 19:40:18 +00:00
ibauersachs
df1b2c41cf Commit from translate.jitsi.org by user ibauersachs.: 126 of 379 strings translated (15 fuzzy). 2017-08-22 19:40:11 +00:00
ibauersachs
8752cc40e2 Commit from translate.jitsi.org by user ibauersachs.: 136 of 379 strings translated (15 fuzzy). 2017-08-22 19:40:05 +00:00
ibauersachs
e42d209401 Commit from translate.jitsi.org by user ibauersachs.: 285 of 379 strings translated (7 fuzzy). 2017-08-22 19:39:59 +00:00
ibauersachs
cd31aad2fd Commit from translate.jitsi.org by user ibauersachs.: 339 of 379 strings translated (1 fuzzy). 2017-08-22 19:39:53 +00:00
ibauersachs
81d7a3147b Commit from translate.jitsi.org by user ibauersachs.: 230 of 379 strings translated (20 fuzzy). 2017-08-22 19:39:47 +00:00
ibauersachs
ac909dce4c Commit from translate.jitsi.org by user ibauersachs.: 378 of 379 strings translated (0 fuzzy). 2017-08-22 19:39:39 +00:00
ibauersachs
6a040d2e67 Commit from translate.jitsi.org by user ibauersachs.: 0 of 379 strings translated (0 fuzzy). 2017-08-22 19:39:33 +00:00
ibauersachs
3ab9765e6b Commit from translate.jitsi.org by user ibauersachs.: 137 of 379 strings translated (16 fuzzy). 2017-08-22 19:39:27 +00:00
ibauersachs
1025ce75bd Commit from translate.jitsi.org by user ibauersachs.: 348 of 379 strings translated (1 fuzzy). 2017-08-22 19:39:20 +00:00
ibauersachs
2e0faa8715 Commit from translate.jitsi.org by user ibauersachs.: 296 of 379 strings translated (7 fuzzy). 2017-08-22 19:39:14 +00:00
ibauersachs
0f6541c07b Commit from translate.jitsi.org by user ibauersachs.: 2 of 379 strings translated (1 fuzzy). 2017-08-22 19:39:07 +00:00
ibauersachs
7466a03a7d Commit from translate.jitsi.org by user ibauersachs.: 347 of 379 strings translated (1 fuzzy). 2017-08-22 19:39:00 +00:00
ibauersachs
e781f4f02d Commit from translate.jitsi.org by user ibauersachs.: 194 of 379 strings translated (24 fuzzy). 2017-08-22 19:38:52 +00:00
ibauersachs
08d9f28cc4 Commit from translate.jitsi.org by user ibauersachs.: 297 of 379 strings translated (7 fuzzy). 2017-08-22 19:38:43 +00:00
ibauersachs
a5b94e5534 Commit from translate.jitsi.org by user ibauersachs.: 378 of 379 strings translated (0 fuzzy). 2017-08-22 19:37:18 +00:00
Leonard Kim
7cea557416 ref(shared-video): move SharedVideoThumb to own file 2017-08-22 10:27:34 -05:00
Leonard Kim
52ee8fd473 ref(small-video): remove some global jquery dom querying
Create a reference to the jquery element instead of querying for
it globally. This is to better encapsulate the small video
component.
2017-08-22 10:27:34 -05:00
Leonard Kim
670d575bcb ref(remote-video): set inner html instead of creating elements
This better mimics declarative jsx.
2017-08-22 10:27:34 -05:00
Leonard Kim
16fbf90a00 ref(local-audio): remove rendering of local audio
The local audio stream is attached to an audio element that is
always muted. As such, local audio is not being rendered and
the attaching may just not be needed at all.
2017-08-22 10:27:34 -05:00
Leonard Kim
ec22329408 ref(local-video): generate html instead of hardcoding in filmstrip
This would better mimic React behavior where each component has
its own markup, instead of relying on markup existing elsewhere.
2017-08-22 10:27:34 -05:00
Saúl Ibarra Corretgé
26f0f7f89c [RN] Alert the user when they need to manually grant a permission 2017-08-22 07:28:19 -05:00
Saúl Ibarra Corretgé
9bca0e3b3d [RN] Create tracks right when they are required
When do we need tracks?

- Welcome page (only the video track)
- Conference (depends if starting with audio / video muted is requested)

When do we need to destroy the tracks?

- When we are not in a conference and there is no welcome page

In order to accommodate all the above use cases, a new component is introduced:
BlankWelcomePage. Its purpose is to take the place of the welcome page when it
is disabled. When this component is mounted local tracks are destroyed.

Analogously, a video track is created when the (real) welcome page is created,
and all the desired tracks are created then the Conference component is created.
What are desired tracks? These are the tracks we'd like to use for the
conference that is about to happen. By default both audio and video are desired.
It's possible, however, the user requested to start the call with no
video/audio, in which case it's muted in base/media and a track is not created.

The first time the app starts (with the welcome page) it will request permission
for video only, since there is no need for audio in the welcome page. Later,
when a conference is joined permission for audio will be requested when an audio
track is to be created. The audio track is not destroyed when the conference
ends. Yours truly thinks this is not needed since it's a stopped track which is
not using system resources.
2017-08-22 07:28:19 -05:00
Saúl Ibarra Corretgé
3102ea6818 [RN] Try to create local tracks when unmuting, if track is missing
This is only desired when the unmuting action took place due to a manual user
intervention or the audio-only mode being disengaged.
2017-08-22 07:28:19 -05:00
Leonard Kim
ec7c10c99b ref(toolbar): replace custom debounce with lodash throttle
The current custom debounce function sets a timeout and ensures
additional calls are not executed while the timeout is pending.
Regulating the call of a function while also ensuring it gets
called at a certain time is a throttle.
2017-08-21 17:20:52 -07:00
Leonard Kim
28b4595561 ref(tooltips): remove old tooltips 2017-08-21 15:16:09 -05:00
Leonard Kim
e3361e2f3b feat(tooltips): convert popup tooltips to InlineDialog 2017-08-21 15:16:09 -05:00
Leonard Kim
c3a4a38414 feat(toolbar): use AtlasKit tooltip 2017-08-21 15:16:09 -05:00
Leonard Kim
38e2443ab7 feat(small-video): use AtlasKit tooltip 2017-08-21 15:16:09 -05:00
Lyubo Marinov
2356238887 [Android] Reduce boilerplate/duplication 2017-08-21 13:58:13 -05:00
Saúl Ibarra Corretgé
c42f1704ff [RN] Rename createInitialLocalTracks to createLocalTracks
The name better suits its purpose, since it can be called at any time.
2017-08-21 08:15:55 -05:00
Leonard Kim
5358f022ff fix(config): override config values instead of merging
Iterate over objects and copy over primitives and arrays
instead of using _.merge, as merge will not replace a config
entry completely. For arrays in a target object, the arrays
will have its indices replaced. This means if a source array
is empty, the target array will be left alone. Similarly,
if the target array is longer than a source array, there
will be indices not touched in the target array.
2017-08-21 07:07:18 -05:00
hristoterezov
5ef914602f fix(remotecontrol): Handle screen sharing cancel 2017-08-21 10:41:24 +01:00
Lyubo Marinov
2818520c8f [RN] Make react-native-img-cache optional at bundle time 2017-08-18 14:54:25 -05:00
Lyubo Marinov
131e5af01e [RN] Fix a strange import of a feature by itself 2017-08-18 14:52:41 -05:00
Lyubo Marinov
90e7804834 Coding style 2017-08-18 14:47:15 -05:00
Lyubo Marinov
c0de88ba8c [RN] Remove unnecessary import 2017-08-18 14:45:00 -05:00
Paweł Domas
99ce46cfa8 feat(conference, toolbox, API) get rid of {audio,video}Muted' flags
* ref: video muted state

Get rid of 'videoMuted' flag in conference.js

* ref: audio muted state

Get rid of 'audioMuted' flag in conference.js

* fix(conference.js|API): early audio/video muted updates

* ref(conference.js): rename isVideoMuted

Rename isVideoMuted to isLocalVideoMuted to be consistent with
isLocalAudioMuted.

* doc|style(conference.js): comments and space after if

* ref: move 'setTrackMuted' to functions

* fix(tracks/middleware): no-lonely-if

* ref(features/toolbox): get rid of last argument

* ref(defaultToolbarButtons): rename var
2017-08-18 13:30:30 +02:00
George Politis
e0e3e873b8 Update turn.md 2017-08-18 13:21:02 +02:00
George Politis
e4f959e400 Create turn.md 2017-08-18 13:18:28 +02:00
Leonard Kim
27deb97c5c ref(filmstrip): hook filmstrip to redux for 1-on-1 mode
- Remove non-redux paths for hiding and showing remote videos.
- Hook web filmstrip to redux to know when to hide remote videos.
  This works, even though VideoLayout is handling RemoteVideo
  appending, because react is only monitoring filmstrip's declared
  JSX which does not change except for attributes (css classes).
2017-08-17 17:27:30 -05:00
Leonard Kim
20379da236 ref(css): remove unused popover.scss 2017-08-17 17:22:38 -05:00
hristoterezov
378a8d014e feat(remotecontrol): Prevent multiple remote control sessions (#1875) 2017-08-17 09:43:22 -07:00
Lyubo Marinov
31dd3da2b6 Remove obsolete file 2017-08-16 17:07:38 -05:00
Lyubo Marinov
ba61876b13 Log an error using less scary words 2017-08-16 16:38:07 -05:00
Lyubo Marinov
f54e87d975 Coding style 2017-08-16 16:36:46 -05:00
Lyubo Marinov
c1fbbc4571 Reduce duplication 2017-08-16 16:28:39 -05:00
yanas
3d397a28e6 Updates default avatar image 2017-08-16 14:42:41 -05:00
Lyubo Marinov
6003b560ae [RN] Fix opening the same URL multiple times
Deep/universal linking now utilizes loadURL (when possible). But loadURL
is imperative in the native source code while its JavaScript counterpart
i.e. React App Component prop url is declarative. So there's the
following bug: open a URL, leave the conference (by tapping the hangup
button, for example), and then opening the same URL actually leaves you
on the Welcome page (if enabled; otherwise, a black screen).

The implementation has a flow though: opening the same URL twice in a
row without an intervening leave will leave the first opening and join
the new opening. Which can be improved by not leaving and joining if the
conference is joined, joining, an not leaving. But that can be done
separately as an improvement independent of the current implementation
details.
2017-08-15 17:32:37 -05:00
Lyubo Marinov
207393d98e [RN] Coding style 2017-08-15 17:32:37 -05:00
Lyubo Marinov
571958cf26 Start the switch to prop-types
As https://facebook.github.io/react/docs/typechecking-with-proptypes.html
says, React.PropTypes have moved into the npm package prop-types since
React v15.5. I've already failed to update certain devDependencies
because they mandate the use of prop-types so I'd rather we (gradually
at least) move to prop-types rather than face a lot of work later on.
2017-08-15 17:32:37 -05:00
Lyubo Marinov
4a39a630a4 Update npm dependencies 2017-08-15 17:32:37 -05:00
virtuacoplenny
3e3577766d fix(quality-slider): prevent resizing by making p2p warning hidden (#1890)
* fix(quality-slider): prevent resizing by making p2p warning hidden

Instead of removing and appending the p2p warning, make it always
appended but toggle visibility so it always takes up space. This
should prevent resizing when the warning appears. Margin and
padding were adjusted to account for the empty space displayed
by a hidden p2p warning.

* let vertical size change
2017-08-15 15:22:32 -05:00
Leonard Kim
5e4d3de8fd fix(filmstrip): re-adjust z-indexes for tooltip display 2017-08-15 14:36:53 -05:00
virtuacoplenny
1b7973a28e ref(invite): use AtlasKit for invite modal buttons and inputs (#1868)
* ref(invite): use AtlasKit for invite modal buttons and inputs

- Convert button to AK Button.
- Convert inputs to AK FieldText.

* remove noop, replace with custom empty func
2017-08-15 14:30:57 -05:00
Leonard Kim
830ec3d097 fix(video-quality): change click handler location on label
This will prevent the quality dialog from closing when changing
desired quality level.
2017-08-14 15:13:29 -05:00
Leonard Kim
995a25ee15 fix(video-quality-label): adjust z-indexing clashes with filmstrip
With AtlasKit InlineDialog, the filmstrip z-index in vertical
filmstrip mode was adjusted as it had to be set to fixed position
for the dialogs to automagically be position fixed. This left
behind a regression where the filmstrip z-index was the same as
the video quality label, but came later in the dom, so the label
was not clickable. This commit modifies the z-index of the
vertical filmstrip to account for clicking of the video quality
label.
2017-08-14 15:12:06 -05:00
virtuacoplenny
725d39ddcd feat(jitsipopover): convert to InlineDialog (#1804)
* feat(small-video): use InlineDialog for stats and remote menu

- Remove JitsiPopover and use InlineDialog instead.
- Bring the remote menu icon into react.
- Make vertical filmstrip position:fixed so popper (AtlasKit
  dependency) sets InlineDialogs and eventually tooltips to
  position:fixed.

* ref(remote-menu): hook KickButton to redux

* ref(remote-menu): hook MuteButton to redux

* modify padding, toggle dialogs

* pixel push margins to align dialogs, adjust padding of dialogs

* add comment about margin for dialog, add file I forgot

* modify indicator markup so the icon can be moved down while trigger stays at top of toolbar
2017-08-14 10:02:58 -05:00
Aaron van Meerten
cd910e3074 docs: document the services which jitsi meet can consume
* new documentation for the services which jitsi meet can consume for conference mapping to dial-in numbers

* attempted markdown link for swagger file from documentation file
2017-08-14 16:20:20 +02:00
Saúl Ibarra Corretgé
2e3a5b1c35 [RN] Fix jsdocs 2017-08-14 12:23:46 +02:00
hristoterezov
1b0bffe251 fix(remotecontrol): Stop scroll events during the remote controll session 2017-08-14 09:13:38 +01:00
hristoterezov
1782030936 feat(alwaysontop): Toolbar. 2017-08-11 17:07:24 -07:00
hristoterezov
382b328262 fix(postmessagebackend): JS error when response is sent. 2017-08-11 17:07:24 -07:00
hristoterezov
b81dc4e59b ref(toolbar): Implement stateless toolbar 2017-08-11 17:07:24 -07:00
hristoterezov
53f675fbe0 ref(ToolbarButton): Remove unnecessary check. 2017-08-11 17:07:24 -07:00
hristoterezov
f18b42b286 fix(ToolbarButton): Don't register shortcut if APP is not defined. 2017-08-11 17:07:24 -07:00
hristoterezov
91e75bf7b9 ref(UIUtil): Move all tooltip functions into another file 2017-08-11 17:07:24 -07:00
hristoterezov
fe59084979 ref(isButtonEnable): UIUtil -> toolbox 2017-08-11 17:07:24 -07:00
hristoterezov
025f7204d5 ref(ToolbarButton): Remove dispatch 2017-08-11 17:07:24 -07:00
hristoterezov
da9e3fb63e feat(external_api): Return external resources for the always on top. 2017-08-11 17:07:24 -07:00
Leonard Kim
d7bccd0c93 ref(pinning): remove pinnedId state from VideoLayout
Instead have VideoLayout reach into redux.
2017-08-11 10:43:35 +01:00
Leonard Kim
f1f46e0af5 feat(pinning): move web pinning logic into redux
- Re-use the native redux pinning implementation for web
- Remove pinning logic from conference.js
- To the native pinning add a check for sharedVideo so
  youtube videos do not send a pin event
- Add shared videos as a participant to enable pinning and
  so they can eventually get added to the filmstrip
- Emit UIEvents.PINNED_ENDPOINT from middleware
2017-08-11 10:43:35 +01:00
Saúl Ibarra Corretgé
19d9b3f023 feat(config): reorganize and thoroughly document config.js
- Document each option.
- Group options semantically.
- Remove no longer existing options.
- Add some missing options.
- Fix punctuation here and there.

NOTE: This is a first step towards a full configuration overhaul, once it
materializes each of the "semantic sections" will be a JS object.
2017-08-10 07:44:53 -05:00
virtuacoplenny
d8cd3e75b4 feat(quality-slider): initial implementation (#1817)
* feat(quality-slider): initial implementation

- Add new menu button with an Inline Dialog slider for
  selecting received video quality.
- Place P2P status in redux store for the Inline Dialog
  to display a warning about not respecting video quality
  selection.
- Respond to data channel open events by setting receive
  video quality. This is for lonely call cases where a
  setting is set before the data channel is open.
- Remove dropdown menu from video status label and clean
  up related js and css.

* first pass at addressing feedback

- Move VideoStatusLabel to video-quality directory.
- Rename VideoStatusLabel to VideoQualityLabel.
- Open VideoQualitydialog from VideoQualityLabel.
- New CSS for making VideoQualityLabel display properly.
- Do not render VideoQualityLabel in filmstrip only instead of hiding with css.
- Remove tooltip from VideoQualityLabel.
- Show LD, SD, HD labels in VideoQualityLabel.
- Remove action SET_LARGE_VIDEO_HD_STATUS from conference.
- Create new action UPDATE_KNOWN_LARGE_VIDEO_RESOLUTION in large-video.
- Move VideoQualityButton into video-quality directory.
- General renaming (medium -> standard, menu -> dialog).
- Render P2P message between title and slider.
- Add padding to slider for displacement caused by P2P message's new placement.
- Fix display issue with VideoQualityButton displaying out of line in the
  primary toolbar.

* second pass at addressing feedback

- Fix p2p inline message color
- Force labels to break on words
- Resolve rebase issues, including only dispatching quality
  update on change. Before there was double calling of dispatch
  produced by an IE11 workaround. This breaks now when setting
  audio only mode to true twice.
- Rename some instances of quality to definition

* rename to data channel opened

* do not show p2p in audio only

* stop toggle audio only icon automatically

* remove fixme about toolbar button

* find closest resolution for label

* toggle dialog on button click

* redo last commit for both button and label
2017-08-09 14:40:03 -05:00
damencho
c1fb1a7def Installs required basexx when token package is installed. Fixes #1870.
Adds some debug messages when token verification fails for some reason.
2017-08-08 23:13:25 +03:00
Saúl Ibarra Corretgé
ca80839094 [Android] Fix gradle and plugin versions with Android Studio 3.0 Canary 9 2017-08-08 14:48:43 -05:00
Paweł Domas
194b3ac9d3 [RN] Add local tracks before joining the conference
* ref(base/conference): add tracks before join

Sometimes it will be suboptimal to add local tracks to the conference,
after the room has been joined. It may slow down the session initiation
process by having to send unnecessary 'source-add' notifications.

* squash: fix typos/comments
2017-08-08 09:27:44 -05:00
hristoterezov
cfe7e30550 fix(SS): Add toggle parameter 2017-08-08 14:18:45 +01:00
virtuacoplenny
ff442853a2 feat(feedback): convert to react and redux (#1833)
* feat(feedback): convert to react and redux

- For styles, remove "aui-dialog2" nesting so existing styles
  can be reused.
- Remove Feedback.js and replace with calls to redux for state
  storing and accessing.
- Add dispatching to FeedbackButton instead of relying on jquery
  clicking handling so the button can be hooked into redux.

* address feedback

* remove calling to not show feedback for recorder and filmstrip
2017-08-07 11:20:44 -05:00
Lyubo Marinov
85a168d51b [RN] base/media is intent, base/tracks is reality 2017-08-04 16:07:48 -05:00
Saúl Ibarra Corretgé
d600504d85 [RN] Refactor video muting
Simplify the code by using a bitfied instead of a couple of boolean flags. This
allows us to mute the video from multiple places and only make the unmute
effective once they have all unmuted.

Alas, this cannot be applied to the web without a massive refactor, because it
uses the track muted state as the source of truth instead of the media state.
2017-08-04 16:07:48 -05:00
Leonard Kim
bd4766648a fix(filmstip-only): apply background color to toolbar 2017-08-04 13:55:42 -05:00
Saúl Ibarra Corretgé
d200abb8db [RN] Polyfill window.location.search
Currently lib-jitsi-meet looks there in case the `anonymousdomain` config option
was specified.

While this commit alone doesn't add support for authenticated deployments, it
avoids a failure if `anonymousdomain` was set, regardless of authentication being
turned on or not.

Fixes: https://github.com/jitsi/jitsi-meet/issues/1858
2017-08-04 11:35:03 -05:00
Leonard Kim
002e48b886 feat(display-name): convert prompt to react
Create a new component that uses Dialog. Reuse existing actions
for updating a participant's display name.
2017-08-04 10:21:18 -05:00
Saúl Ibarra Corretgé
1c1604bee7 [Android] Don't mute the microphone under any circumstance
It's a global action, and if we do that other applications won't be able to use
it. I experienced this with the system camera. We do, however, make sure to
enable it when we need to.

Note that enabling it doesn't mean we are *using* it. It just means we *can*,
and that we will get actual audio when we do.
2017-08-03 13:45:41 -05:00
Saúl Ibarra Corretgé
99fd325a51 [Android] Fix gradle warning
This setting is no longer used.
2017-08-03 13:45:41 -05:00
Saúl Ibarra Corretgé
4f6ec920cd [Android] Set targetApiVersion to 25
We keep being compatible with versions all the way down to 16 for now, but this
will disable internal compatibility shims when running on 25.
2017-08-03 13:45:41 -05:00
Saúl Ibarra Corretgé
0d33844d51 [Android] Use an appropriate Android support library version
It must match the compileSdkVersion major number.
2017-08-03 13:45:41 -05:00
Lyubo Marinov
0836f2cefd [RN] Prefetch remote avatar images 2/2 2017-08-03 13:45:41 -05:00
Lyubo Marinov
97832e0eef [RN] Prefetch remote avatar images 1/2 2017-08-03 13:45:41 -05:00
Lyubo Marinov
00e058d392 [RN] Cache avatars and provide a default in case load fails (2)
Refactors the previous "[RN] Cache avatars and provide a default in
case load fails" for the purposes of simplification but also modifies
its functionality at the same time. For example:

- Always displays the default avatar immediately which may be seen if
  the remote avatar needs to be downloaded.
- Does not use random colors.
- Uses a default avatar image which is not transparent and ugly but at
  least it's the same image that's used on Web. I've started talks to
  have images/avatar2.png replaced with a transparent and beautiful
  so that will land later on and we'll see the automagic colors in all
  their glory then.
2017-08-03 13:45:41 -05:00
Lyubo Marinov
504646fff0 Coding style 2017-08-03 13:45:41 -05:00
Saúl Ibarra Corretgé
122ebe48c7 [RN] Cache avatars and provide a default in case load fails
Avatars are cached to the filesystem and loaded from there when requested again.
The cache is cleaned after a conference ends and on application startup
(defensive move).

In addition, implement a fully local avatar system, which is used as a fallback
when loading a remote avatar fails. It can also be forced using a prop.

The fully local avatars use a user icon as a mask and apply a background color
qhich is picked by hashing the URI passed to the avatar. If no URI is passed a
random color is chosen.

A grace period of 1 second is also implemented so a default local avatar will be
rendered if an Avatar component is mounted but has no URI. If a URI is specified
later on, it will be loaded and displayed. In case loading the remote avatar
fails, the locally generated one will be used.
2017-08-03 13:45:41 -05:00
Дамян Минков
fe8ac0fff9 Merge pull request #1852 from virtuacoplenny/lenny/device-error-notifications
feat(device-errors): move device error dialogs to notifications
2017-08-02 14:55:18 -05:00
Leonard Kim
cd66a7fcb7 ref(notifications): bring hiding of notifications into redux 2017-08-02 11:19:38 -07:00
Leonard Kim
74ddae4a6a feat(device-errors): move device error dialogs to notifications
- Create a notification component for displaying a toggle.
- Create an action for showing the component if allowed by
  the local storage setting and for saving the setting to
  local storage.
- Remove all notifications having a timeout by default so the
  device error notification must be dismissed manually.
- Split the camera and mic error dialog into two separate
  notifications.
2017-08-01 16:33:00 -07:00
Lyubo Marinov
1ad8436cb5 [Android] Use loadURL in the app 2017-08-01 12:07:22 -05:00
Lyubo Marinov
6b2a93909b [iOS] Use loadURL in the app 2017-08-01 06:31:03 -05:00
Lyubo Marinov
c259551d9a [RN] Handle multiple schemes/protocol in URLs 2017-08-01 06:31:03 -05:00
Lyubo Marinov
377be4272a [RN] Fix the conference URL delivered to JitsiMeetView's listeners 2017-08-01 06:31:03 -05:00
Lyubo Marinov
737419dbe8 Do not require domain in SDK and ExternalAPI 2017-08-01 06:31:03 -05:00
Lyubo Marinov
1748049322 [RN] Remove unncessary characters from the invite URL 2017-08-01 06:31:03 -05:00
Lyubo Marinov
caea02a322 [RN] Mitigate 'Not joining a new URL while in a conference' 2017-08-01 06:31:03 -05:00
bgrozev
d778b716be Merge pull request #1850 from jitsi/iframe_api_doc
doc(iframe_api): Fix the names of the properties in the options object.
2017-08-01 00:51:44 -05:00
hristoterezov
4dcbe5c6a0 doc(iframe_api): Fix the names of the properties in the options object. 2017-08-01 08:48:50 +03:00
virtuacoplenny
c04ef05058 feat(presence): display status in thumbnail and large video (#1828)
* feat(presence): display status in thumbnail and large video

- Create a React Component for displaying presence. It currently
  connects to the store for participant updates but in the future
  should not be as smart once more reactification occurs.
- Modify filmstrip css so the presence status displays horizontal
  center and below the avatar.
- Modify videolayout css so the presence status displays horizontal
  centered and with a rounded background.
- Dispatch presence updates so the participant state can be update.
- Update message position on large video update to ensure message
  positioning is correct.

* squash: do not show presence message if connection message is displayed
2017-07-31 18:33:22 -05:00
Дамян Минков
82117a0aef Handles disabled dial-out codes. (#1847)
Hides the UI component showing dialout codes and uses the dial input without validating it.

Skips printing error when dial-in numbers is not configured.
2017-07-31 12:44:50 -07:00
Leonard Kim
9c6afc2062 fix(dial-out): appease FieldText warning for onChange prop 2017-07-31 13:21:49 -05:00
Lyubo Marinov
dcc6ce025f Convert a function to an asynchronous redux action creator 2017-07-31 12:26:39 -05:00
paweldomas
40c9f583fa ref(tracks): remove duplication in mute/unmute 2017-07-31 12:26:39 -05:00
Leonard Kim
3e84d8b3b6 ref(dial-out): use AtlasKit FieldText for inputs
- Swap the telephone input with FieldText.
- Swap the dropdown trigger input with FieldText for styling
  consistency with the telephone input.
- Wrap the dropdown trigger so it can be modified with jitsi css.
- Use flexbox to have the trigger and input align horizontally
  but have the input take up width if the trigger is not displayed.
2017-07-31 11:44:56 -05:00
Saúl Ibarra Corretgé
0983ef48b5 [RN] Fix root component's prop types 2017-07-31 15:30:31 +02:00
virtuacoplenny
da1c760abf feat(notifications): implement a react/redux notification system (#1786)
* feat(notifications): implement a react/redux notification system

* squash into impl explicit timeout, style

* ref(notifications): convert toastr notifications to use react

* ref(toastr): remove library

* squash into conversion: pass timeout

* squash into clean remove from debian patch
2017-07-28 12:56:49 -05:00
paweldomas
e818fa1e9e fix(API): early audio muted status
Apply the same early audio muted logic as for the video.
2017-07-28 12:06:42 -05:00
paweldomas
d2e8b13add feat: add config.startWithAudioMuted config.startWithVideoMuted 2017-07-28 12:06:42 -05:00
paweldomas
68f4a4ae9f ref: enable/disable microphone button
Make toolbar's microphone button enabled whenever there are any
'audioinput' devices available and allow to add audio during
the conference even if microphone permissions were denied on startup.
2017-07-28 12:06:42 -05:00
Saúl Ibarra Corretgé
bfa5f4c953 [Android] Fix resource leak when JitsiMeetView is destroyed
In iOS this is automagically done in the view destructor, bunt we don't have
that luxury in Java we have to do it manually.

The new disponse() method MUST be called when the Activity holding the view is
going to be destroyed, typically in the onDestroy() handler.
2017-07-28 10:50:12 -05:00
Saúl Ibarra Corretgé
03b043ca2b [Android] Destroy containes when they are not visible
Whatever I've tried so far ends up failing in really weird ways, so let's admit
defeat, for now. Destroy containers only on Android.

This shall be revisited when we update RN to version >= 0.43 and we have
"display: 'none'" available.
2017-07-28 10:25:46 -05:00
Saúl Ibarra Corretgé
d00ee3d7b6 [Android] Add an example for loadURLObject 2017-07-28 09:19:07 -05:00
Saúl Ibarra Corretgé
aaf5dd75fa [iOS] Fix loading initial URL when app is closed
We must not pass nil as the URL, that will translate to null and we won't be
able to load the initial URL which is passed as the launch parameters.
2017-07-28 09:18:35 -05:00
Saúl Ibarra Corretgé
f1c9e57b43 [RN] startWithAudioMuted & startWithVideoMuted 2017-07-27 16:48:38 -05:00
Lyubo Marinov
e542af28a2 [RN] Converge with Web's ExternalAPI a bit
Web's ExternalAPI accepts an object with properties as one of its
constructor arguments and from which it generated a URL. Mobile's
JitsiMeetView.loadURLObject is supposed to accept pretty much the same
object.
2017-07-27 16:48:38 -05:00
damencho
9778aabe98 Uses languages.json to obtain supported languages. 2017-07-27 16:36:22 -05:00
Saúl Ibarra Corretgé
1fae0ee780 [RN] Update react-native-background-timer dependency
Our fixes have been applied upstream and a release has been made.
2017-07-27 11:50:01 +02:00
Saúl Ibarra Corretgé
1fb31b6773 [iOS] Fix crash when a nil URL is loaded
NSDictionary doesn't support nil values, they must be objects, so use NSNull
instead, which is the kosher way to do it.
2017-07-27 11:33:56 +02:00
Lyubo Marinov
9871580e6d [iOS] Completeness (maybe) 2017-07-26 15:54:58 -05:00
Lyubo Marinov
3546cf4915 Fixes jsdocs, formatting 2017-07-26 15:54:57 -05:00
Lyubo Marinov
a2c2d3bee1 [RN] Alternative to JitsiMeetView.loadURL w/o URL
Introduces loadURLObject in JitsiMeetView on Android and iOS which
accepts a Bundle and NSDictionary, respectively, similar in structure to
the JS object accepted by the constructor of Web's ExternalAPI. At this
time, only the property url of the bundle/dictionary is supported.
However, it allows the public API of loadURLObject to be consumed. The
property url will be made optional in the future and other properties
will be supported from which a URL will be constructed.
2017-07-26 15:53:35 -05:00
Lyubo Marinov
e5e7b59f43 Upgrade NPM dependencies/packages 2017-07-26 12:08:20 -05:00
Lyubo Marinov
980d48e00b Fix typo 2017-07-26 10:40:05 -05:00
Saúl Ibarra Corretgé
51934dac1b [Android] Fix gradle version with Android Studio 3.0 Canary 8 2017-07-26 17:30:45 +02:00
Lyubo Marinov
f0ab835b46 [RN] Add loadURLString to JitsiMeetView
Initializing a new URL/NSURL instance is a chore especially when one
takes into account that the JavaScript side (1) is loading the URL
asynchronously and (2) is capable of parsing strings that may or may not
be represented as URL/NSURL.

The Android method loadURLString(String) may have been called
loadURL(String) to overload loadURL(URL) but I didn't want to do that
because:

1. It would not be compatible with existing source code such as
loadURL(null) which would have become ambiguous.

2. I wanted to achieve better convergence with the iOS API.
2017-07-25 19:07:01 -05:00
Lyubo Marinov
6c488cc613 [RN] Simplify hiding Container components 2017-07-25 13:58:45 -05:00
Saúl Ibarra Corretgé
d3c408ae2e [RN] Simplify hiding Container components
When a Container is not visible there is no need for it to react to touch
events, thus avoid wrapping it in a touch component.

In addition, simplify the style needed for hiding the component. Moving the view
out of the window boundaries no longer works on RN 0.42 on iOS. Seting the size
to 0 works well on both platforms, but in the future (when we upgrade to RN >=
0.43) we should switch to display: none:
4d69f4b2d1
2017-07-25 13:58:44 -05:00
hristoterezov
e8223bbb4a fix(remotecontrol): Use own scope for the messages. (#1787) 2017-07-25 08:40:57 -07:00
Saúl Ibarra Corretgé
fa86d2ab9e Merge pull request #1815 from jitsi/fix_audio_only_off
fix(AudioOnly+web): crash when untoggle audio only
2017-07-25 14:05:09 +02:00
paweldomas
122a7f6346 fix(AudioOnly+web): crash when untoggle audio only
Because on web video track is stored both in redux and in 'localVideo'
field, video is attempted to be unmuted twice when turning off the audio
only mode. This will crash the app with 'unmute operation is already in
progress'. This commit will prevent from taking action from the web
world if the video track already exists and will make the redux side
rollback unmuted status in case unmute fails.
2017-07-25 11:05:02 +02:00
Lyubo Marinov
24eb37ae1e [RN] Fix jsdocs, formatting. Add flow 2017-07-24 16:08:46 -05:00
Saúl Ibarra Corretgé
2094b15432 [RN] Workaround for Android view clipping
In another installment of "how on earth?!", using a 1px border instead of a
0.2px border fixes view clipping on a device where it didn't work before
(Moto X Play).

Observations:

- When nothing was rendered, rotating the device made the buttons show up, this
  makes me think the Surface is not properly composited with the toolbar view
  for some reason. Why this happens in some devices and not in others remains a
  mistery.

Other approaches attempted:

- Setting View.collapsed to false so it will remain in the view hierarchy. It
  made no effect.

- Setting View.needsOffscreenAlphaCompositing to true. It made no effect.

Just like before, I came up with this workaround by accident, but couldn't find
another way, so here we go again.
2017-07-24 15:01:37 -05:00
Saúl Ibarra Corretgé
157eadc44a [RN] Don't destroy containers when they are not visible
This essentially reverts
023359b9d2

In the filmstrip we keep a container full of thumbnail views. Destroying these
every time we want we want to hide it is costly, as new renderers have to be
recreated, and they lack context, so there is an increased chance for "black
thumbnails".
2017-07-24 15:01:37 -05:00
Saúl Ibarra Corretgé
2525bb2805 Merge pull request #1802 from jitsi/start_in_audio_only
Start in audio only
2017-07-24 14:32:20 +02:00
paweldomas
e08171f602 fix: video muted out of sync
When video is unmuted when toggling off the audio only mode it
dispatches video muted status, but does not roll it back in case it
fails. That was causing toolbar button on Web to display incorrect
video muted status.
2017-07-24 13:54:38 +02:00
Lyubo Marinov
db88c555dc Fix warning 2017-07-21 17:40:09 -05:00
Lyubo Marinov
96e0c56bde [RN] Don't override config values 2017-07-21 17:40:09 -05:00
yanas
b0ffe2e63f Remove primary toolbar splitter (#1811) 2017-07-21 14:21:39 -07:00
yanas
06234066b6 Fixes some styles and variables (#1809)
* Fixes some toolbox/toolbar styles and variables

* [squash] Fixes variable name to fit better its purpose

* [squash] Fixes secondary toolbar variable name
2017-07-21 12:45:04 -07:00
Leonard Kim
1897c395ec fix(icons): set a size prop for AtlasKit icons
With the upgarde of @atlaskit/icon to 7.0.0, the size prop
essentially became required to maintain its appearance in the
jitsi app, otherwise it'll unexpectedly try to take up the
available space and cause minor display issues.
2017-07-21 14:25:39 -05:00
paweldomas
6ac23c8086 fix(conference): early video muted state
If muteVideo is called, before local tracks have been initialized it
will be synced up once the tracks are created (or not).
2017-07-21 15:05:09 +02:00
paweldomas
a5f61714bd fix: unmute video on audio only switch off
Will unmute local video (and ask for permissions if needed) in case user
started in audio only mode and is turing it off.
2017-07-21 15:04:37 +02:00
paweldomas
00d3d3c09a fix(VideoLayout): muted for no tracks
Will make the UI display audio/video muted icon for remote participants
with no audio/video track.
2017-07-21 15:04:03 +02:00
paweldomas
6493b09565 feat: add config.startAudioOnly
When the 'startAudioOnly' config option is set to true the conference
will start in the audio only mode.
2017-07-21 15:03:28 +02:00
Leonard Kim
955542f4a5 feat(speaker-status): update speaker status in redux
The speakerStatus field already exists as part of the objects
in the participant reducer. When the library updates the
connection status of a user, plumb that update through to redux.
2017-07-21 14:12:15 +02:00
George Politis
68d40b4fa4 Merge pull request #1738 from virtuacoplenny/lenny/connection-stats-pub-sub
ref(stats): process stats through one pub/sub
2017-07-21 12:22:55 +02:00
Aaron van Meerten
c369330054 Merge pull request #1797 from jitsi/module-poltergeist_update
Module poltergeist update
2017-07-20 16:06:50 -05:00
Aaron van Meerten
b6efdb533d Handles the async wrapping of the mod_muc_size functions
fixes handling of keyserver ASAP validation of tokens
wraps room and room-size APIs
2017-07-20 16:04:16 -05:00
Aaron van Meerten
22e9dc9893 Handles async context for all poltergeists
set up async context for all poltergeist calls
utils lib now has async wrapper for event handlers
2017-07-20 15:56:45 -05:00
damencho
8047fdf5a2 Makes possible for poltergeist to set status just before leaving. 2017-07-20 14:16:42 -05:00
damencho
2c873e8c7f Adds token verification for poltergeist accepted rest calls. 2017-07-20 13:56:55 -05:00
damencho
284b5f94b5 Adds initial status param when creating poltergeist. 2017-07-20 13:29:54 -05:00
bbaldino
6bcb9be364 Merge pull request #1806 from saghul/ff-simulcast-testing
config: document enableFirefoxSimulcast
2017-07-20 08:36:39 -07:00
Saúl Ibarra Corretgé
3c084c0082 config: document enableFirefoxSimulcast 2017-07-20 09:48:28 +02:00
bbaldino
a08ea37005 Merge pull request #1798 from virtuacoplenny/lenny/rename-hide-indicator
fix(connection-indicator): rename calls to hiding the indicator
2017-07-19 15:20:33 -07:00
Leonard Kim
2132cd6736 fix stat unsub, one loop for updating 2017-07-19 15:11:35 -07:00
Leonard Kim
44bbd26c96 ref(stats): process stats through one pub/sub
Instead of passing stats through UI then VideoLayout then the
SmallVideo, pass stats directly to what uses it--ConnectionIndicator.
This also bypasses adding the stats to the store, as they do not
seem to be something that needs to be shared or stored app-wide
just yet.
2017-07-19 15:11:35 -07:00
Saúl Ibarra Corretgé
1d90826098 [RN] Use a more resilient way for testing if we are on React Native
navigator.product is read-only, so we don't run into the risk of it being
changed.
2017-07-19 16:40:06 -05:00
Saúl Ibarra Corretgé
4efbbe14b1 [Android] Require OpenGL ES 2.0
This was already an implicit requirement, as it's the only version implemented
in libwebrtc.

The reason to add this is to (defensively) try to filter old devices which may
not implement it.

WebRTC's own Android demo app defines this.
2017-07-19 16:36:42 -05:00
Lyubo Marinov
0b5431b795 [RN] Bind event handler once per instance, not per render 2017-07-19 16:33:57 -05:00
Lyubo Marinov
e7fc4739c4 Fixes jsdocs 2017-07-19 16:25:06 -05:00
damencho
f40faecfbe Fixes using correct field for domain in multidomain mode. 2017-07-19 11:36:49 -05:00
Saúl Ibarra Corretgé
f72932d125 [RN] Fix audio / video mute buttons when permissions are not granted 2017-07-19 14:38:38 +02:00
Saúl Ibarra Corretgé
ffc12ccc0e [RN] Disable camera switch button when video is muted 2017-07-19 14:30:36 +02:00
Saúl Ibarra Corretgé
03da40b56a [RN] Disable video mute and camera switch buttons when in audio only mode 2017-07-19 11:58:08 +02:00
Saúl Ibarra Corretgé
055df1c12e [RN] Add ability to disable a ToolbarButton 2017-07-19 11:50:24 +02:00
Lyubo Marinov
d87b8823e9 [RN] Don't open the camera on startup when there is no welcome page 2017-07-18 23:42:08 -05:00
Saúl Ibarra Corretgé
8225600b61 [RN] Don't open the camera on startup when there is no welcome page
The end goal of this patch was to avoid opening the camera when there is no
welcome page.

In order to achieve this, the logic for creating the local tracks was
refactored:

Before this patch local tracks were created when lib-jitsi-meet was initialized,
and destroyed when it was deinitialized. As a side note, this meant that when a
conference in a non-default domain was joined, local tracks were destroyed and
recreated in quick succession.

Now, local trans are created and destroyed based on what the next route will be,
and this happens when the target room has been decided. This allows us to create
local tracks the moment we need to render any route, and destroy them when there
is no route to be rendered. As an interesting byproduct, this refactor also
avoids the destruction + recreation of local tracks when a conference in a
non-default domain was left.
2017-07-18 20:42:20 -05:00
Lyubo Marinov
b62b296080 Fix typos. Apply consistent formatting 2017-07-18 16:43:58 -05:00
Lyubo Marinov
a690b9d5e1 [RN] Handle denied getUserMedia permissions 2017-07-18 16:41:39 -05:00
Leonard Kim
364ab5431c fix(connection-indicator): rename calls to hiding the indicator 2017-07-18 13:27:48 -07:00
damencho
4a9a8eec9a Send poltergeist presence update reusing previous presences.
If we do not reuse previous presences we lose avatar and name and people joining after the poltergeist creation will not be updated with those values.
2017-07-18 13:08:18 -05:00
damencho
308360fbe0 Cleans poltergeists table on remove occupant and when muc is destroyed. 2017-07-18 11:11:14 -05:00
Saúl Ibarra Corretgé
c97daff506 Merge pull request #1775 from jitsi/start_screen
Add config.startScreenSharing
2017-07-18 13:51:57 +02:00
Saúl Ibarra Corretgé
7361151203 feat(dialog): add missing export for actionTypes
The full-screen module uses the HIDE_DIALOG action to re-engage the full-screen
mode.
2017-07-18 13:35:24 +02:00
paweldomas
8093043d39 style(conference.js): style fixes 2017-07-18 12:45:40 +02:00
paweldomas
3fbb022ffb ref(conference): use options in init tracks 2017-07-18 12:45:12 +02:00
damencho
e6840981ca Handles removing poltergeists.
Adds http method to remove poltergeists. Adds configurable timeout after which poltergeists automatically are removed from the room.
2017-07-17 19:29:00 -05:00
damencho
64bb5563bc Returns error when there is no query, but params expected. 2017-07-17 17:38:29 -05:00
damencho
0cffbdb967 Fixes wrong parameter name. 2017-07-17 17:26:47 -05:00
Lyubo Marinov
72691eb2dc misc: fix dispatching actions twice when mapDispatchToProps is used 2017-07-17 13:59:04 -05:00
Saúl Ibarra Corretgé
0bf9a78e4c misc: fix dispatching actions twice when mapDispatchToProps is used
The functions need not return anything, or it will be dispatched as another
action.
2017-07-17 13:51:35 -05:00
Aaron van Meerten
0c446026d6 Merge pull request #1788 from jitsi/module-poltergeist
module-poltergeist
2017-07-17 13:21:57 -05:00
Saúl Ibarra Corretgé
326ce4217f [Android] Fix gradle and plugin versions with Android Studio 3.0 Canary 6 2017-07-17 11:32:57 -05:00
Kolokotronis Panagiotis
5db605b0cf [Docs] Web server config on install 2017-07-17 10:26:12 -05:00
paweldomas
117d3bb110 ref(conference.js): show screensharing error first
If there will be microphone error it will cover any screensharing
dialog, but it's still better than in the reverse order where
the screensharing dialog will sometime be closing the microphone alert
($.prompt.close(); is called).
2017-07-17 15:32:03 +02:00
paweldomas
3926d705ad feat: add config.startScreenSharing
Will try to use screensharing instead of camera video from
the beginning.
2017-07-17 15:32:01 +02:00
paweldomas
5b5470ec66 ref(conference.js): createInitialLocalTracksAndConnect
Make 'createInitialLocalTracksAndConnect' not static.
2017-07-17 15:31:48 +02:00
Lyubo Marinov
7f041170f7 Consistent formatting 2017-07-16 03:44:07 -05:00
Lyubo Marinov
e54744e5ef [Android] Use target API 23 2017-07-16 02:26:09 -05:00
Saúl Ibarra Corretgé
96bfcafc97 [Android] Use target API 23
This reverts commit c9a29153dd.

Now that react-native-webrtc supports the permissions system in 23, use it since
it provides a more pleasant experience to users.

In addition, fix a bug in the previous code: the React Native view must be
loaded after we have acquired the permission to draw on top of other apps,
otherwise our app may crash while we accept the permission, since React may try
to draw.
2017-07-16 02:26:09 -05:00
Lyubo Marinov
9a295723cf Consistent formatting 2017-07-16 02:25:26 -05:00
damencho
58d06fe7e6 A poltergeist module.
Thanks to Matthew Wild for the initial help of creating these.
Module with REST interface to create poltergeist participants and change their statuses.
When user with same id joins the room, the poltergeist is removed.  We also make sure that that user uses same username when authenticates. This way we are sure that user will join the room with the same nick as the poltergeist.
2017-07-14 22:18:23 -05:00
damencho
cc79b073f0 Fires event before setting username, allows listeners to override it.
This is a hook to override the username that will be used when authenticating token users (which are using anonymous login with auto-generated username).
2017-07-14 22:12:56 -05:00
damencho
599d84a889 Stores the room name from the bosh url into the session. 2017-07-14 22:08:41 -05:00
damencho
2b1e8cdeff Creates util for modules and adds method get_room_from_jid in it. 2017-07-14 22:03:36 -05:00
virtuacoplenny
ea0c333f4b Merge pull request #1785 from jitsi/remove-styles
Remove unneeded css styles
2017-07-14 16:14:46 -07:00
virtuacoplenny
4eef52b84e Merge pull request #1784 from bbaldino/device_list_available_fix
fix an error when testing a result from a method that returns a promise
2017-07-14 15:44:58 -07:00
yanas
3e1dc298c8 Removes unneeded css styles 2017-07-14 14:49:28 -05:00
virtuacoplenny
244de8096f feat(local-video): convert to react (#1705)
* feat(local-video): convert to react

- Create a VideoTrack component for displaying a video element.
  This mirrors native also having a VideoTrack component.
- The VideoTrack component does not let React update it to prevent
  the video element from re-rendering, which could cause flickers
  and would not work with temasys's overriding of the video element.
- VideoTrack extends AbstractVideoTrack to mirror native
  implementation and to get the dispatch of the onplaying event.
- Remove the onclick handler on the video element. Honestly, I
  didn't get it to work, and did not try, but it is also unnecessary
  because another handler already exists on the video wrapper.

* ref(device-selection): VideoInputPreview uses VideoTrack to show video

* squash into conversion: change css selectors

* squash into conversion: mix in abstract props

* squash into conversion: change shouldComponentUpdate check

* squash: update comment about why triggerOnPlayingUpdate is used
2017-07-14 14:22:27 -05:00
bbaldino
7d99c54ec8 fix an error when testing a result from a method that returns a promise 2017-07-14 18:55:18 +00:00
virtuacoplenny
37328b3995 Merge pull request #1757 from jitsi/rc_dialog_to_notification
fix(remotecontrol): Replace info dialogs with notifications.
2017-07-14 11:32:54 -07:00
hristoterezov
b8d3e82ae7 fix(remotecontrol): Replace info dialogs with notifications. 2017-07-14 12:58:37 -05:00
hristoterezov
07a0e3d8ff fix(iframe_api): Remove min height/width. 2017-07-14 12:56:20 -05:00
hristoterezov
70122789e7 fix(iframe_api): Change the format of the arguments in the constructor 2017-07-14 12:56:20 -05:00
hristoterezov
3736d6ca78 fix(iframe_api): Remove unnecessary div that wraps the iframe 2017-07-14 12:56:20 -05:00
hristoterezov
07158e8071 style(iframe_api): Adds _ for every non public property 2017-07-14 12:56:20 -05:00
hristoterezov
cc6fcfd982 feat(iframe_api): Getter for the iframe 2017-07-14 12:56:20 -05:00
paweldomas
b84e910086 feat: add option to disable desktop sharing
config.disableDesktopSharing - when set to false will disable desktop
sharing

interfaceConfig.DESKTOP_SHARING_BUTTON_DISABLED_TOOLTIP - when value is
assigned, will not hide the desktop sharing button completely, but show
as disabled with this value used as the tooltip text.
2017-07-14 10:14:00 -05:00
virtuacoplenny
10766e6958 Merge pull request #1778 from jitsi/base-css-fix
Fix(base.scss): Don't restyle inputs, selects and buttons
2017-07-13 17:08:31 -07:00
Aaron van Meerten
d752e8b864 accept 'avatar' as well as 'avatarUrl' for avatar field 2017-07-13 15:49:25 -05:00
George Politis
d335669afe Merge pull request #1765 from jitsi/feat-local-remote-relayed
feat: Adds TURN indication.
2017-07-13 21:16:40 +02:00
yanas
7ebd2b2cd4 Fix(base.scss): Don't restyle inputs, selects and buttons 2017-07-13 14:15:07 -05:00
Aaron van Meerten
622d4ba89c added checks for audience and issuer values (#1772)
* added checks for audience and issuer values
default audience and issuer checks to validate only appId
added missing documentation lines from the previous PR for context_user and context_group session values

* support for accepting any audience
option set to accept any audience by default
2017-07-13 13:30:17 -05:00
Saúl Ibarra Corretgé
3de6f1cd7f feat(external_api): make sure the created iframe has no border 2017-07-13 13:05:30 -05:00
Saúl Ibarra Corretgé
7b1639569e feat(external_api): make height / width calculation more resilient 2017-07-13 13:05:30 -05:00
George Politis
62613ff02e feat: Adds TURN indication. 2017-07-13 17:00:27 +02:00
Leonard Kim
4eacbd9f61 fix(tracks): remove mute and videotype listeners on track remove
Listeners were set for when a track muted or changed its video
type, but the listeners were never removed. This would could
cause events to keep firing on the removed tracks, which would
cause redux to fire and error because the tracks were no longer
known. That the tracks still fire events after removal is
another issue...
2017-07-13 09:37:39 +02:00
virtuacoplenny
884509faee Merge pull request #1771 from jitsi/change-thumbnail-menu
Changes video thumbnail menu icon
2017-07-12 18:54:07 -07:00
yanas
2e2b1d47c0 Changes video thumbnail menu icon 2017-07-12 17:22:07 -05:00
Aaron van Meerten
fac6c30b1c use "sub" instead of "aud" to confirm tenant domain settings
stick user and group from token context into session if available
2017-07-12 12:57:55 -05:00
Leonard Kim
1ad614e812 fix(add-people): remove line break from searchPeople request
Chrome has deprecated line breaks in requests. The template
literal used for the searchPeople url has a line breaks. Instead
of line breaking the request url, concatenate it together.
2017-07-12 12:54:26 -05:00
paweldomas
21957c8bf2 fix(conference): disable video icon
Explicitly calls 'updateVideoIconEnabled' in case both audio and video
permission were not granted and device list changed callbacks will not
be executed (check in lib-jitsi-meet that it requires GUM call to
succeed at least once for device list changed events).
2017-07-12 10:29:18 -07:00
paweldomas
63377a2f76 ref(conference): try video only
Will make an attempt to create video only stream in case microphone
permissions were not granted.
2017-07-12 10:29:18 -07:00
paweldomas
de2eee2e61 ref(VideoLayout): reduce 'forceUpdate' usage 2017-07-12 10:29:18 -07:00
paweldomas
badbedf0f5 ref(LargeVideoManager): getCurrentContainer
Remove duplication and direct access to kind of private 'state' field by
introducing 'getCurrentContainer' method.
2017-07-12 10:29:18 -07:00
paweldomas
2281b1acd2 ref: enable/disable video button
Dynamically enables/disables the toolbar video button. Prior to that
commit if we would start with no video there would be no way to enable
it later on.
2017-07-12 10:29:18 -07:00
paweldomas
6655ae5a84 fix(conference): do not mute when screen sharing
Screen sharing video should not be muted if video input device is
disconnected.
2017-07-12 10:29:18 -07:00
paweldomas
c4c100e26a feat(conference): restore video after screen sharing
Will restore the camera video state from before screen sharing was
started (and will mute it if it was muted).
2017-07-12 10:29:18 -07:00
paweldomas
a7025c41f6 fix(conference): do not go back to video
Do not go back to video from screen sharing if there was no video stream
at the time when screen sharing was being started.
2017-07-12 10:29:18 -07:00
paweldomas
d84ab20a47 fix(conference): start camera later on
Instead of disabling the video button in the toolbar, mark it as muted,
so that the user can click it to try enable video later on, even if
joined without video (either declined permission or was starting with
screen streaming and dismissed the dialog).
2017-07-12 10:29:18 -07:00
paweldomas
751f27644f fix(VideoLayout): store userID in container
The container needs to store user's ID in order for the 'isOnLargeVideo'
logic to work correctly when user has no stream (previously it was
obtained from stream which can be null/undefined).
2017-07-12 10:29:18 -07:00
yanas
4ccd5c6072 Fix(AddPeopleDialog): Close dialog on submit (#1761)
* Fix(AddPeopleDialog): Fixes error state and close dialog

* (to-squash) Addresses comments
2017-07-12 08:35:00 -07:00
Saúl Ibarra Corretgé
bae609b296 Merge pull request #1763 from jitsi/dp_def_prop
fix(desktop_picker): Use defaultProps
2017-07-11 10:01:43 +02:00
Saúl Ibarra Corretgé
e78c70e53d misc: set supported Node version to >= 6 2017-07-10 17:45:25 -05:00
hristoterezov
cee523fbf1 fix(desktop_picker): Use defaultProps 2017-07-10 17:43:29 -05:00
virtuacoplenny
0481e4cf00 feat(indicators): move the "top toolbar" indicators to react (#1699)
* feat(indicators): move the "top toolbar" indicators to react

* wrap baseindicator
2017-07-10 17:29:44 -05:00
virtuacoplenny
fcda36a8e0 Merge pull request #1756 from jitsi/remote_control_mm
Remote control
2017-07-10 15:20:55 -07:00
yanas
f5d443d194 User Picker Implementation 2017-07-10 09:56:38 -07:00
yanas
47b6166d79 fix(StatelessDialog.web): Fixes stealing Enter events 2017-07-10 09:56:38 -07:00
Saúl Ibarra Corretgé
6fc1a3f45d [Android] Add comment on disabling JS packaging for dev builds 2017-07-10 17:42:39 +02:00
Saúl Ibarra Corretgé
ab7d1553db Merge pull request #1750 from jitsi/p2p_disabled
feat(config.js): add config.testing.
2017-07-10 10:13:25 +02:00
hristoterezov
1498245b9e fix(remotecontrol): Show error on cancel of desktop picker 2017-07-09 22:42:35 -05:00
hristoterezov
dc8198100b feat(remotecontrol): Make sure the receiver is always sharing entire screen 2017-07-09 16:34:08 -05:00
hristoterezov
1a9a8a2098 feat(SS): pass the source type to lib-jitsi-meet. 2017-07-07 17:45:24 -05:00
Saúl Ibarra Corretgé
2968f8edf8 [RN] Make the audio muted icon consistent with the web 2017-07-07 12:27:28 -05:00
Lyubo Marinov
5c094bf6e0 [RN] Fix disconnecting before the connection was established 2017-07-07 12:21:08 -05:00
Saúl Ibarra Corretgé
c4232b34ae [RN] Fix disconnecting before the connection was established
Keep track of the connection and conference objects so we can leave and / or
disconnect early, before the connection is established or the conference joined.
2017-07-07 09:37:04 -05:00
Saúl Ibarra Corretgé
99b856233d [iOS] Fix joining initial URL if app was closed
On iOS, if the app is closed the startup options are only passed as the
`launchOptions` dictionary of `applicationDidFinishLaunching`. Thus add a helper
method to be called from there by embedding applications so we can copy that
dictionary.
2017-07-07 08:57:49 -05:00
paweldomas
0f4c785705 feat(config.js): add config.testing. 2017-07-07 15:40:08 +02:00
hristoterezov
814d56c25c feat(remotecontrol): multi monitor support 2017-07-06 21:20:35 -05:00
Saúl Ibarra Corretgé
f878f54b4d [RN] Toggle audio-only icon based on state 2017-07-06 17:18:49 -05:00
Saúl Ibarra Corretgé
46a87e42ce [RN] Update audio-only icon
Match the one on the web.
2017-07-06 17:14:00 -05:00
Saúl Ibarra Corretgé
db26aa652b [RN] Update jitsi font icon selection 2017-07-06 17:14:00 -05:00
Saúl Ibarra Corretgé
8d1d3a9c42 [RN] Use same video mute indicator icon as on the web 2017-07-06 17:10:32 -05:00
Saúl Ibarra Corretgé
d5e89a60b7 [RN] Fix passing url prop to Root and App components
React (pun intended) to prop changes, that is, load the new specified URL.

In addition, fix a hidden bug in loading the initial URL from the linking
module: we prefer a prop to the URL the app was launched with, in case somehow
both are specified. We (the Jitsi Meet app) are not going to run into this
corner case, but let's be defensive just in case.
2017-07-06 15:54:56 -05:00
Lyubo Marinov
948d18f954 [Android] Fix "Minimum supported Gradle version is 4.1-milestone-1" 2017-07-06 15:20:09 -05:00
Lyubo Marinov
7dbba59dee [RN] Disconnect/hangup before joining a new URL 2017-07-06 15:00:29 -05:00
Lyubo Marinov
61fd4e4ce4 [RN] Fix passing url prop to Root and App components 2017-07-06 14:59:57 -05:00
Lyubo Marinov
9bd6bbfd95 Fix jsdocs. Simplify the source code 2017-07-06 14:59:57 -05:00
Saúl Ibarra Corretgé
cc9249ba1a [RN] Fix passing url prop to Root and App components
React (pun intended) to prop changes, that is, load the new specified URL.

In addition, fix a hidden bug in loading the initial URL from the linking
module: we prefer a prop to the URL the app was launched with, in case somehow
both are specified. We (the Jitsi Meet app) are not going to run into this
corner case, but let's be defensive just in case.
2017-07-06 14:59:57 -05:00
Boris Grozev
35fddfa8f4 fix: Removes the inclusion of local.html. 2017-07-06 10:51:44 -05:00
Saúl Ibarra Corretgé
82e10e1a00 [iOS] Don't bring the packager to the foreground upon launch 2017-07-06 14:07:20 +02:00
virtuacoplenny
84ae7df8f1 fix(filmstrip-only): vertically align center the toolbar (#1700)
* fix(filmstrip-only): vertically align center the toolbar

Use top 50% to position the toolbar's top at the vertical center
of the iframe. Then use transform 50% to move the toolbar itself
up 50% so its middle matches the middle of the iframe.

* squash: toolbox should center with filmstrip
2017-07-05 21:07:00 -05:00
bbaldino
5c199e2195 Merge pull request #1740 from bgrozev/refactor-deployment-info
Refactor deployment info
2017-07-05 18:41:38 -07:00
Lyubo Marinov
9aaf9a484d [RN] Fix TypeError: undefined is not an object (evaluating 'this.options.p2p.useStunTurn') 2017-07-05 16:34:06 -05:00
Saúl Ibarra Corretgé
4e4a9012c2 [RN] Fix iOS lockups / resprings
Apparently iOS doesn't like dangling background tasks very much, so update the
background timers plugin with a version which fixes this.

https://github.com/ocetnik/react-native-background-timer/pull/38

Also accomodate for the API changes upstream.

Credits to @lyubomir for finding the needle in the haystack.
2017-07-05 16:34:06 -05:00
Boris Grozev
4840db67ca fix: adds a hasOwnProperty check, uses "let". 2017-07-05 16:31:50 -05:00
Boris Grozev
b09613b943 ref: Uses config.deploymentInfo instead of window.jitsiDeploymentInfo. 2017-07-05 16:07:16 -05:00
Emil Ivov
66eac19058 Merge pull request #1739 from bgrozev/no-tabnabbing
No tabnabbing
2017-07-05 15:44:20 -05:00
Boris Grozev
aee5a9ca43 fix: Use https for links without a scheme. 2017-07-05 15:39:53 -05:00
Leonard Kim
129e54e262 fix(remote-menu): position volume slider in vertical center for firefox 2017-07-05 15:34:11 -05:00
Leonard Kim
0d4b77d7b1 fix(popover): set display before calculating width
Popover works by first creating a DOM element with display none
then having jquery calculate its width and new position and
then setting display to table. This does not work with p2p
connection stats, which are much wider than the default width
of the popover. What will happen is when display table is set,
the width will increase greatly so the positioning will be off.
The workaround here is to set display table as the default
display but toggle visibility instead.
2017-07-05 15:34:11 -05:00
Boris Grozev
b0eeb8a207 fix: Avoid tabnabbing
Reported by Manav.
2017-07-05 15:15:59 -05:00
Leonard Kim
ae67b2b28e fix(vertical-filmstrip): enable hardware acceleration for icons
Icons on the thumbnails can flicker when scrolling through videos.
To give rendering a bit more power, and thereby help with rendering
icons without flickering, force hardware acceleration.
2017-07-05 13:24:08 -05:00
Sergio Garcia Murillo
a97d02e0fd Change messageString to msgString in _requestRecordingToken
#1730
2017-07-05 10:05:22 -05:00
George Politis
88bfa61875 Merge pull request #1728 from saghul/unused-config-opts
feat(chore): remove unused interfaceConfig options
2017-07-05 14:34:11 +02:00
Saúl Ibarra Corretgé
4df914194c Merge pull request #1732 from jitsi/stun-turn-4p2p
docs: Documents the p2p.useStunTurn option.
2017-07-05 12:04:43 +02:00
George Politis
86c867ea71 docs: Documents the p2p.useStunTurn option. 2017-07-04 12:50:21 +02:00
Saúl Ibarra Corretgé
16e972d077 feat(chore): remove unused interfaceConfig options 2017-07-04 08:38:06 +02:00
Leonard Kim
152427e01b feat(small-video): convert the "toolbar" to react
Move display of audio muted, video muted, and moderator icons,
which make up the elements of the small video toolbar, into React
Components.
2017-06-30 14:21:44 -05:00
Boris Grozev
2a3c4cfb82 ref: Adds deployment info variables to config.js,
removes local.html
2017-06-30 13:37:11 -05:00
Emil Ivov
573aa168ea Update README.md 2017-06-30 11:25:32 -05:00
virtuacoplenny
0de032ebd7 feat(avatar): SmallVideo uses the existing Avatar component. (#1712)
* feat(avatar): SmallVideo uses the existing Avatar component.
2017-06-29 13:21:03 -05:00
Emil Ivov
ab81c2b56d Merge pull request #1713 from saghul/p2p-h264
feat(p2p): enable H.264 for P2P by default
2017-06-29 08:47:18 -05:00
Saúl Ibarra Corretgé
8a3cec4a9d feat(p2p): enable H.264 for P2P by default
On mobile we got the extra step of overriding the option and always set it to
true.
2017-06-29 11:22:32 +02:00
George Politis
2b0563ad35 Merge pull request #1710 from saghul/p2p-settings
feat(p2p): refactor configuration options
2017-06-29 11:13:26 +02:00
virtuacoplenny
928181cd7a feat(display-name): convert to React (#1672)
* feat(display-name): convert to React

- Create a new React Component for displaying and updating display
  names on small videos
- The updating of the Component is defined in the parent class
  SmallVideo, which children will get access to through prototype
  copying
- Create a new actionType and middleware so name changes that occur
  in DisplayName can be propogated to outside redux
- Update the local video's DisplayName when a conference is joined
  or else the component may keep an undefined user id

* squash: query for the container, not the el owned by react
2017-06-28 22:35:43 -05:00
paweldomas
e7a4318e8c ref(conference.js): remove global promise
Get rid of global APP.conference.screenSharingPromise.
2017-06-28 15:08:09 -05:00
Saúl Ibarra Corretgé
4e5bc172c9 feat(config): allow overriding nested config objects
This makes it possible for the following URL params to work:

config.p2p.enabled=true&config.p2p.preferH264=true
2017-06-28 17:29:04 +02:00
Saúl Ibarra Corretgé
3ea2f00578 feat(p2p): refactor configuration options 2017-06-28 14:57:39 +02:00
Saúl Ibarra Corretgé
01ac394e92 [Android] Fix compileSdkVersion
It must match the major number in buildToolsVersion.
2017-06-28 10:51:49 +02:00
Leonard Kim
4ce5888b4c feat(connection-indicator): convert to react
- Create a new ConnectionIndicator component for displaying an
  icon for connection quality and for triggering a popover. The
  popover handling has been left in ConnectionIndicator for now,
  which follows the existing implementation.
- Remove the unused method "connectionIndicatorShowMore"
- Change the implementation of existing methods that update the
  connection indicator to call the same method which will rerender
  the indicator completely.
2017-06-27 15:58:00 -05:00
Saúl Ibarra Corretgé
35f79dd2b4 config: default resolution is now 720p 2017-06-27 08:25:34 -05:00
Saúl Ibarra Corretgé
cdb547dbd1 Merge pull request #1534 from jitsi/p2p_react_native
[RN] export RTCIceCandidate
2017-06-27 11:15:29 +02:00
damencho
00afc32b6b Handles '*' as room name in jwt.
Allows '*' in jwt to allow connecting to any room.
2017-06-26 10:51:06 -05:00
Daniel Ornelas
8a01067b62 Added post-script to the Release configuraiton to build iOS SDK as Universal framework 2017-06-23 19:39:53 -05:00
Daniel Ornelas
7c2d59033b Fixed nullable pointer warnings in iOS SDK 2017-06-23 19:39:41 -05:00
Leonard Kim
fe4de31e57 feat(tracks): place local tracks in the redux store
- Add tracks to the redux store by intercepting where the
  tracks actually get used via conference.replaceTrack
- While the replace call is unique to web, the _dispose and
 _addTracks calls use existing native code implementations
- Between _dispose and addTracks is a call to update mute state.
  Without it, when changing devices or videoType while muted,
  the user will stay muted (whereas existing web behavior
  causes unmute). This is due to middelware calling
  _syncTrackMutedState to make the track mute if the user is
  currently muted.
- Move the rest of ConferenceEvents.TRACK_MUTE_CHANGED into
  middleware so the event is no longer used
- Note: This change does not guarantee the track state in the
  redux store will be 100% accurate, specifically the attribute
  videoStarted. Muted and videoType should be accurate.
2017-06-23 10:33:05 -05:00
Leonard Kim
2a446b8799 feat(tracks): place remote tracks into the redux store
- Use actions trackAdded and trackRemoved to add and remove remote
  tracks from the redux store
- Emit out to non-react components on track added and removed in
  the track middleware
- Emit out to existing non-react components on track mute and
  video type changes
2017-06-23 10:33:05 -05:00
Leonard Kim
4a1efed4a8 feat(audio-level): convert SmallVideo AudioLevelIndicator to React 2017-06-22 11:14:41 -05:00
Lyubo Marinov
8e4864004b Revert "Speed react-native run-android up (more)"
Reverts commit d117989b55 because it does
not bundle the fonts assets and the JS bundle.
2017-06-22 09:21:25 -05:00
hristoterezov
486d0802a8 fix(largevideo): show the background video only for video container type 2017-06-21 16:19:30 -05:00
hristoterezov
c250da59d5 fix(videolayout): Resize calculations 2017-06-21 16:19:30 -05:00
Ilya Daynatovich
0aee5e5b48 Add blurring effect 2017-06-21 16:19:30 -05:00
Ilya Daynatovich
292c1689ba Add maximum zooming coefficient 2017-06-21 16:19:30 -05:00
Leonard Kim
0a1bd5a0c7 feat(popover): do not remove the popover on every update
With popover usage now only passing in React Components, the
logic of removing the popover and recreating its html with
every update is not necessary. Instead allow React to update
the popover contents.

Because of this change, mouse event handlers are not recreated
on each update, so it is possible for mouseleave to fire after
the size of the popover shrinks when collapsing to hide more stats,
forcing the mouse out of the popover. To prevent this, padding has
been added to the top of the popover so on resize the mouse will
still be over the popover. The padding has the added bonus of
fixing an issue where the popover would not close until mouseenter
was triggered after size collapse, but it adds the drawback of
requiring more upward mouse travel to close the popover.
2017-06-20 13:49:02 -05:00
Leonard Kim
e0d641a787 feat(connection-stats): convert connection stats display to react
Move all logic related to displaying a table of connection stats to a React
Component. The actual parsing logic was modified as little as possible as the
focus is moving display to React.
2017-06-20 13:49:02 -05:00
Lyubo Marinov
d117989b55 Speed react-native run-android up (more)
React Native's Gradle script does not bundle the JS bundle in the Debug
configuration. Copy that source code (and adapt it) into our sdk Gradle
script.
2017-06-20 13:14:30 -05:00
Lyubo Marinov
2fa7e777d6 Speed react-native run-android up 2017-06-20 10:32:44 -05:00
Saúl Ibarra Corretgé
be30dd09e9 [iOS] Add scheme for building only the SDK 2017-06-19 16:08:30 -05:00
Saúl Ibarra Corretgé
84aa3627b4 doc: add a note con the recommended Node + npm versions 2017-06-19 15:57:35 -05:00
Saúl Ibarra Corretgé
d7818be067 [iOS] Link with WebRTC.framework at the top level
Before, Jitsi Meet (the app) would only link with JitsiMeet.framework, which in
turn embedded WebRTC.framework. While possible, Apple doesn't allow apps with
nested frameworks to be submitted to the store. Now the app will link with
WebRTC.framework directly so there is no framework nesting.

A potential improvement here is to build WebRTC as a static library so it can
then be embedded in JitsiMeet.framework and completely hidden from the app.
2017-06-19 11:03:13 -05:00
bgrozev
c782d21a36 Merge pull request #1680 from jitsi/suspended-overlay-english
Improve English of the suspended overlay message
2017-06-19 09:43:51 -05:00
Saúl Ibarra Corretgé
7800e4047f Remove executable flag from font files 2017-06-19 09:26:26 -05:00
ibauersachs
61e846c4fd Commit from translate.jitsi.org by user ibauersachs.: 353 of 354 strings translated (0 fuzzy). 2017-06-16 21:31:08 +00:00
Ingo Bauersachs
957badc792 Improve English of the suspended overlay message 2017-06-16 23:09:09 +02:00
Lyubo Marinov
53954285c7 Fix flow (and npm run lint)
The npm library promise (https://github.com/then/promise) was updated
(roughly 2 hours ago) and our flow setup does not pass successfully on
it.
2017-06-16 12:59:36 -05:00
Lyubo Marinov
5cffe328a5 Simplify the source code 2017-06-16 12:06:59 -05:00
Lyubo Marinov
1da49d86a1 Speed webpack up 2017-06-16 12:06:59 -05:00
Lyubo Marinov
0d7aea377a Increase ES6 utilization in webpack.config.js 2017-06-15 22:46:18 -05:00
Saúl Ibarra Corretgé
617df1c69c [Android] Remove no longer used gradle options 2017-06-15 10:38:08 -05:00
bgrozev
0b75f5a4d0 Commit from translate.jitsi.org by user bgrozev.: 348 of 349 strings translated (0 fuzzy). 2017-06-15 15:38:13 +00:00
Lyubo Marinov
f200b17a33 webpack 2 2017-06-15 10:09:48 -05:00
Saúl Ibarra Corretgé
2db574810b [RN] Fix target reference in iOS scheme 2017-06-15 09:51:04 -05:00
Saúl Ibarra Corretgé
c9a29153dd [RN] Lower Android target SDK version to 22
API level 22 is below 23 (aka Marshmallow), which included an overhaul in the
permissions system. React Native recommends 22 (it's the default when you create
a new app) and there have been reports when set higher [0] and [1].

This also fixes a critical bug, wherein Jitsi Meet wouldn't request permissions
for the camera and microphone.

Last, this change also allows us to get rid of the overlay checking code,
because it was only needed for API level 23 or higher.

[0]: https://github.com/facebook/react-native/pull/10479
[1]: https://github.com/facebook/react-native/issues/10587
2017-06-15 08:20:33 -05:00
Lyubo Marinov
25ec8ac6a7 Prepare for eslint 4 2017-06-14 22:17:35 -05:00
hristoterezov
c8c44d62ed fix: some exports to make it work with webpack 2 2017-06-14 19:37:13 -05:00
hristoterezov
4d329b510f ref: module.exports -> export for the ES6 modules 2017-06-14 19:37:13 -05:00
paweldomas
a30e880876 fix(AudioInputPreview): do not care about TPC
TraceablePeerConnection argument is lib-jitsi-meet internal and the app
does not need to care.
2017-06-14 10:21:11 -05:00
Leonard Kim
5d1087e464 fix(vertical-filmstrip): prevent scaling based on video count
Vertical filmstrip has a scrollbar to scroll through all remote
video thumbnails instead of scaling width and height to force all
thumbnails to display on screen. The scaling is not necessary in
vertical filmstrip mode and instead causes some UI spacing issues
with the video status label.

Also addressed a typo in "removeVideoWidth" near the area of the
changed logic.
2017-06-13 15:17:55 -05:00
Leonard Kim
da99f3b939 feat(remote-video): convert remote video menu to react
- Create new React Components for RemoteVideoMenu and its
  buttons
- Remove existing menu creation from RemoteVideo
- Refactor RemoteVideo so all function binding happens once in
  the constructor, removing the need to rebind when updating
  the RemoteVideoMenu
- Allow popover to append and remove React Components from itself
- Refactor popover so post-popover creation calls are broken out and
  popover removal behavior is all done in one function.
2017-06-13 14:54:19 -05:00
Leonard Kim
73dd7440d0 fix(remote-video): update remote video menu if it exists
In RemoteVideo, creation of the RemoteVideoMenu (popover) is
skipped if in filmstrip only mode. However, updateRemoteVideoMenu
is called by other components, and that tries to access popover
and will error.

Add a defensive check for now as filmstrip is being rewritten
for react.
2017-06-13 14:54:03 -05:00
Leonard Kim
1a87ee5f93 fix(filmstrip): adjust filmstrip remote videos positioning
- For horizontal mode, remove extra spacing created by borders
  around local video and remote videos.
- For vertical mode, ensure remote videos grow only to fill the
  parent height.
2017-06-13 14:52:43 -05:00
hristoterezov
9d953f18c2 fix(device_selection_popup): On Firefox 2017-06-13 14:08:50 -05:00
bgrozev
be3ed0cc25 Commit from translate.jitsi.org by user bgrozev.: 349 of 349 strings translated (0 fuzzy). 2017-06-13 14:53:07 +00:00
Lyubo Marinov
ee3cd30b59 [RN] Fix call/ring overlay 2017-06-10 18:07:52 -05:00
Lyubo Marinov
ca94563c51 [RN] Coding style
The files styles.js are used (pretty much) on React Native only and each
of them exports 1 name. Export it as default to cut down on source code.
2017-06-10 18:07:51 -05:00
Lyubo Marinov
9591226be6 [R] Fix call/ring overlay
There were regressions in the form of JS errors in Filmstrip introduced
when the call/ring overlay was rewritten in React.
2017-06-10 18:07:51 -05:00
Lyubo Marinov
718de31e04 [RN] Fix video in audion-only mode
When entering audio-only mode, VideoBridge is instructed to stop sending
remote videos. However, if the instruction fails because DataChannels do
not work, for example, then the app continues to display the remote
videos. Even though they're received in the case of such a failure, no
videos are to be displayed in audio-only mode.
2017-06-10 18:07:51 -05:00
Lyubo Marinov
4b2add7aa6 [Android] Allow multiple JitsiMeetViews 2017-06-10 03:34:11 -05:00
Lyubo Marinov
10e5e0fdf5 [iOS] Allow multiple JitsiMeetViews 2017-06-09 19:17:01 -05:00
Lyubo Marinov
5f64ccb97d [RN] Naming 2017-06-09 14:51:31 -05:00
Saúl Ibarra Corretgé
4687c1f465 [RN] Add ability to skip the welcome page
Also expose this in the native SDKs.
2017-06-09 14:10:10 -05:00
Saúl Ibarra Corretgé
79d51bc379 feat(App): remove obsolete config prop
It's obsolete now, since config is handled in Redux. Also add a "defaultUrl"
prop so emdedding applications can select what the default base URL is.
2017-06-09 14:10:10 -05:00
hristoterezov
893d08d614 fix(device_selection_popup): URL 2017-06-09 13:23:32 -05:00
Lyubo Marinov
a5cd118550 [Android] Naming 2017-06-09 10:55:14 -05:00
Saúl Ibarra Corretgé
a266a71999 [RN] Add JitsiMeetViewAbstractListener to Android SDK 2017-06-09 09:57:06 -05:00
Saúl Ibarra Corretgé
be8694f93e [RN] Remove duplicated font on Android
Copy it from the main fonts directory instead.
2017-06-09 16:05:27 +02:00
Saúl Ibarra Corretgé
a1a394ad0b doc: update mobile building instructions for iOS 2017-06-09 09:55:40 +02:00
Lyubo Marinov
e5cc8cd32b [RN] locationURL instead of inviteURL
The value of inviteURL is derived from locationURL by removing the hash
and query/search params in order to make it fit for display and/or
public purposes. The Jitsi Meet SDK consumers do not fall into that
category and our intention is to provide them with the URL they used
with JitsiMeetView.openURL(URL) anyway.

Also rewrites to remove repetition. I'm not saying the new source code
is better really but at least I got to examine it and comment on some of
its weaknesses.
2017-06-09 00:03:23 -05:00
Lyubo Marinov
01b397faef Fixes a jsdoc/require-description-complete-sentence warning 2017-06-09 00:03:23 -05:00
Lyubo Marinov
90466183d6 [RN] Consistency in Jitsi Meet SDK for Android 2017-06-09 00:03:23 -05:00
Saúl Ibarra Corretgé
84463d8cf0 [RN] Add workaround for loading different URLs on Android
Changing the props from native (Java) code was only added in 0.45, so add a
workaround until we get to updating our React Native dependency.
2017-06-09 00:03:23 -05:00
Saúl Ibarra Corretgé
a075f24000 [RN] Add conference events to native SDKs
The current implementation doesn't use the API and Transport modules. This is
due to the fact that they are too tied to APP at the moment, which is web only.

Once API is refactored and moved into the Redux store this will be adjusted,
though it's unlikely that the lowest level React Native module (ExternalAPI)
changes drastically.

This commit also introduces a stopgap limitation of only allowing a single
instance for JitsiMeetView objects on both Android and iOS. React Native doesn't
really play well with having multiple instances of the same modules on the same
bridge, since they behave a bit like singletons. Even if we were to use multiple
bridges, some features depend on system-level global state, such as the
AVAudioSession mode or Android's immersive mode. Further attempts will be made
at lifting this limitation in the future, though.
2017-06-09 00:03:23 -05:00
Saúl Ibarra Corretgé
ddea60efe9 [RN] Add initial Jitsi Meet SDK for Android
Dames en heren, welcome to Jitsi Meet SDK for Android, the Jitsi Meet library
for Android.

The Jitsi Meet SDK encapsulates React Native and all the dependencies Jitsi
Meet has so other aopplications can integrate it easily.

Unlike iOS, creating "fat" libraries is not allways (if at all) possible on
Android, however, effort was put into making the integration as easy as
possible.

While React Native can be embedded in native applications, I don't think it was
designed to be embedded as part of an Android library, hidden away from the
application using it. This surfaced as a number of issues which had to be
addressed specifically due to our use-case:

- Activity lifecycle methods must be linked with the React Native engine, so the
  library provides wrapper methods.
- Custom fonts have to be manually added as assets, since the provided gradle
  script doesn't work properly in a library target.
- The RN packager has to be manually triggered since the gradle script will no
  longer do it for us.

At this stage, the Jitsi Meet application is just a small single activity
application which uses the Jitsi Meet SDK to create a single activity which
represents the entire application. Events and external conference handling are
forthcoming.

PS: Yours truly would like to add that it was a lot more fun to work on the iOS
side of things.
2017-06-09 00:03:23 -05:00
hristoterezov
5a14d1ed6c fix(deviceselectionpopup): the name and position of device selection button for film strip only mode 2017-06-08 21:46:58 -05:00
Leonard Kim
9837181d5d fix(popover): z-index should be greater than toasts
Currently, the JitsiPopover z-index will cause it to display below
any toast notifications so this changes modifies the z-index
values so JitsiPopover is higher than the notification toasts.
2017-06-08 09:37:40 -05:00
Saúl Ibarra Corretgé
f6ccacb7df [RN] Fix regression handling ToolbarButton onPress
Introduced in
96e83989a5
as part of a refactor + feature.
2017-06-08 09:36:58 -05:00
Saúl Ibarra Corretgé
a0054ada08 [RN] Simplify signing embedded iOS frameworks 2017-06-08 01:13:12 -05:00
Lyubo Marinov
2251a17f96 [RN] Consistency in Jitsi Meet SDK for iOS
1. Aligns the project structure of Jitsi Meet SDK for iOS with that for
   Android for better comprehension.

2. The command `react-native run-ios` uses the last Xcode project or
   workspace in the list of these sorted in alphabetical order. Which
   limits our freedom in naming. Thus having only an Xcode project in
   the root directory of the iOS project structure gives us back the
   freedom in naming.

3. Allows the Podspec to work for the app project in addition to the sdk
   project because we need Crashlytics in the app which is integrated
   via Cocoapods as well.

4. Further removes references to JitsiKit in the source code for the
   sake of consistent naming.
2017-06-08 01:13:12 -05:00
Saúl Ibarra Corretgé
b1100a9c7a [RN] Add initial Jitsi Meet SDK for iOS
Ladies and gentlemen, allow me to introduce you to Jitsi Meet SDK for iOS, the
mobile SDK which powers Jitsi Meet.

The goal is to encapsulate the entire React Native app into a framework / SDK
and offer an API for native (ObjC or Swift) applications to embed the Jitsi
conferencing experience.

While React Native can be embedded in native applications, I don't think it was
designed to be embedded as part of a framework, hidden away from the application
using it. This surfaced as a number of issues which had to be addressed
specifically due to our use-case:

- Universal / deep linking needed to be wrapped to avoid the embedding app from
  linking with RN.
- The bundle URL had to be manually constructed, since RN considers that all
  resources are in the main bundle, but in case of a framework that is not the
  case.
- Custom fonts had to be manually loaded, since UIAppFonts doesn't work on the
  framework's Info.plist file.
- The RN packager has to be manually triggered since the React project will no
  longer do it for us.
- Custom App Transport Security rules were added since the builtin way to do it
  modifies the framework's Info.plist, which is useless in this case.

At this stage, the Jitsi Meet application is just a small single view
application which uses the Jitsi Meet SDK to create a single view which
represents the entire application. Events and external conference handling are
forthcoming.
2017-06-08 00:50:00 -05:00
damencho
8e3dfcf0d0 Handles Enter key to submit dialogs.
If there is no focused node inside the dialog we focus any of the available buttons, submit button is first.
2017-06-07 17:06:48 -05:00
damencho
bf7415e6b5 Updates field-text dependency version and add autofocus prop. 2017-06-07 17:06:48 -05:00
Lyubo Marinov
6072978454 [RN] Fix the bundling broken by unnecessary dependencies 2017-06-07 16:19:57 -05:00
Lyubo Marinov
5a74080839 Comply w/ coding style 2017-06-07 13:27:45 -05:00
Lyubo Marinov
89862cbea9 [RN] Fix exports/imports of nonexistent files 2017-06-07 13:27:44 -05:00
Leonard Kim
0451e7c9e7 fix(conference): ensure avatar url and email changes act on strings
Both conference.changeLocalEmail and conference.changeLocalAvatarUrl
are exposed in the external api. It is possible for users to then
pass in non-string values. To make it more visibly obvious of the
error and to prevent script errors, convert whatever is passed in
into a string.
2017-06-07 13:25:24 -05:00
Leonard Kim
2e08815644 fix(video): use onplaying to ensure video height and width are set
When using onplay in firefox, the event fires before data is flowing,
which can cause videoHeight and videoWidth to be 0 during resizing.
By using onplaying, there is some assurance data is being received,
so videoHeight and videoWidth should be set.
2017-06-07 10:44:05 -05:00
hristoterezov
96e83989a5 feat(device_selection): Implement popup 2017-06-07 09:23:40 -05:00
paweldomas
2c002c875d fix(SmallVideo): remove invalid character
Removes ' character which should not be there.
2017-06-06 11:15:39 -05:00
paweldomas
e38dd0e9d3 ref(LargeVideoManager): remove unused method
'_isConnectionActive' is not used anymore
2017-06-06 11:13:02 -05:00
paweldomas
a2a2a583de doc(LargeVideoManager): invalid default
The default for 'show' argument of 'showRemoteConnectionMessage' is
undefined (unspecified).
2017-06-06 11:13:02 -05:00
paweldomas
a3ba28f507 ref(LargeVideoManager): simplify
Simplify 'updateParticipantConnStatusIndication' by getting rid of
'showMessage' argument.
2017-06-06 11:13:02 -05:00
paweldomas
6865b03338 fix(RemoteVideo): broken grey avatar
Also moves the logic about participant connection status from SmallVideo
to RemoteVideo, because it doesn't make sense for local videos.
2017-06-06 11:13:02 -05:00
paweldomas
12d7e61362 feat(VideoLayout): add ninja icon
Add ninja icon which wil be displayed when user's connection status is
inactive.

Apply grey filter only for interrupted state.

Do not use isLastN directly, but check ParticipantConnectionStatus.
2017-06-06 11:13:02 -05:00
paweldomas
5c5864e94a font(jitsi): add ninja icon 2017-06-06 11:13:02 -05:00
Lyubo Marinov
d437f3db03 [React] Call/ring overlay
Rewrite the non-React RingOverlay into the React Component CallOverlay
in a way which makes it easier to port to React Native.
2017-06-06 00:11:39 -05:00
Lyubo Marinov
409255f056 [React] Cross-platform Components
Introduce certain React Components which may be used to write
cross-platform source code such as Audio like Web's audio, Container
like Web's div, Text like Web's p, etc.
2017-06-06 00:11:39 -05:00
virtuacoplenny
d1ea29beeb fix(large-video): ensure switch to local video when all others leave (#1607)
* fix(large-video): ensure switch to local video when all others leave

This handles the case where User A and B are in a call and B has
no audio or video. Then B leaves. User A would see User B left
on large video. Instead, User A should see self view on large.

* squash: always update large video if it is empty

* squash: add largeVideo check for filmstrip only mode
2017-06-05 18:47:26 -05:00
yanas
a59e691ba8 Removes redux compose utility function 2017-06-05 13:31:38 -05:00
Lyubo Marinov
a4a13bed84 Invite URL w/o (hash & query/search) params 2017-06-01 21:04:31 -05:00
Lyubo Marinov
ec454d1da0 Move ConferenceUrl.inviteURL into React and redux 2017-06-01 21:04:31 -05:00
Lyubo Marinov
e2afb4c7e7 Move ConferenceUrl.reload into React and redux 2017-06-01 21:04:31 -05:00
Lyubo Marinov
87b488a12b Comply w/ coding style 2017-06-01 21:04:31 -05:00
Lyubo Marinov
4dc658c270 Fix 'Missing JSDoc comment  require-jsdoc' 2017-06-01 21:01:50 -05:00
jitsi-pootle
a5d8b4a933 New files added from translate.jitsi.org based on templates 2017-06-01 01:19:43 +00:00
yanas
1d34a50d2f Fix raise hand toggled state 2017-05-31 15:31:06 -05:00
yanas
d1737745c2 Fix raise hand toggled state 2017-05-31 07:50:18 -05:00
Lyubo Marinov
ec2e6525ac Fix jsdocs 2017-05-31 00:53:53 -05:00
Lyubo Marinov
8882d9c3b6 Upgrade NPM dependencies/packages 2017-05-31 00:53:53 -05:00
Aaron van Meerten
6d1a018864 include local.html file meant to define local analytics properties (#1612)
* include local.html file meant to define local analytics properties
include all specified local analytics properties in analytics events

* use new variable name jitsiDeploymentInfo to represent more general use as local deployment information collection
2017-05-30 13:37:43 -05:00
Lyubo Marinov
320e67baa1 Fix the initialization of the (external) API
The counterpart of the external API in the Jitsi Meet Web app uses the
search URL param jwt to heuristically detect that the Web app is very
likely embedded (as an iframe) and, consequently, needs to forcefully
enable itself. It was looking at whether there was a JSON Web Token
(JWT) but that logic got broken when the JWT support was rewritten
because the check started happening before the search URL param jwt was
parsed.
2017-05-30 09:38:18 -05:00
Lyubo Marinov
69f8cf7836 Fix the disabling of the Welcome page 2017-05-26 19:23:23 -05:00
Saúl Ibarra Corretgé
5304660e14 [RN] Polyfill Symbol 2017-05-26 16:37:22 -05:00
Leonard Kim
538da92eae fix(large-video): attempt to update large video on all connection updates
It is possible for a connection update to come during a large video update,
between its promises, which would result in the update NOT triggering another
large video update because an update is in progress. This can cause a state
where a connection status overlay is displayed over a video in a state that
does not match the actual video state, like the restoring overlay displaying
on active video.
2017-05-26 15:31:34 -05:00
paweldomas
4b487e3c89 config: enable P2P by default 2017-05-26 12:59:24 -05:00
damencho
70e1bfc6b8 Enables vertical filmstrip by default. 2017-05-26 12:58:52 -05:00
Aaron van Meerten
d65295db8b Merge pull request #1611 from jitsi/fix-token-pubkey
Fixes using public key to verify tokens.
Tested in production.
2017-05-25 17:29:06 -05:00
damencho
34be638fca Fixes using public key to verify tokens. 2017-05-25 16:45:08 -05:00
damencho
2a0973a897 Fixes chat when on join we receive messages.
Fixes a TypeError: Cannot set property 'innerHTML' of undefined
                    at o (Chat.js:61)
                    at Object.updateChatConversation (Chat.js:271)
that is thrown when joining a conference with messages already set to the chat. The error used to remove a strophe handler and chat was not working at all for those seeing the error.
2017-05-25 15:22:49 -05:00
Leonard Kim
42b51e3c5c fix(1-on-1): remove torture test workaround, add new tests 2017-05-25 15:15:52 -05:00
Leonard Kim
ff0e392ca8 fix(device-selection): Update parameters from audio level change callback 2017-05-25 13:28:27 -05:00
virtuacoplenny
1da95d2e37 fix(large-video): trigger update after timeout for 1-on-1 calls (#1599)
* fix(large-video): trigger update after timeout for 1-on-1 calls

Currently no video switch happens if a user joins audio and video
muted. For example, User A is in a call and User B joins with no
mic and camera. User A will keep seeing local video on large video.
The fix is to set a timeout, of a somewhat arbitrary 3 seconds, to
show User B on large video.

* SQUASH: wrap videoElement access in if

* SQUASH: split out remoteVideoActive logic
2017-05-25 11:50:52 -05:00
Lyubo Marinov
b7c4ebba84 Web Filmstrip & LargeVideo React Components
We've had Filmstrip & LargeVideo React Components on mobile/React Native
from the start. We didn't have them on Web (because the rewrite in React
is not complete yet). However, that led to differences in the React
Component Conference on Web and mobile. In an effort to get closer to
merging the React Component Conference on Web and mobile, introduce the
React Components Filmstrip & LargeVideo on Web even if a minimal
render-only form at this time.
2017-05-25 11:44:35 -05:00
Lyubo Marinov
66ababc6c8 Comply w/ codying style: naming, formatting, etc. 2017-05-25 10:56:08 -05:00
yanas
e128c03f56 Merge pull request #1602 from virtuacoplenny/lenny/video-label-hover
fix(video-label): Show darker background on hover
2017-05-24 20:58:49 -05:00
virtuacoplenny
d5b40280ab fix(vertical-filmstrip): different label animations for filmstrip states (#1596)
* fix(vertical-filmstrip): different label animations for filmstrip states

Instead of one timing for sliding the video status label left and right,
have different timings depending on the filmstrip state. To facilitate
triggering the different animations, add more classes to the labels
that need to move that specify the filmstrip state.

- Faster transition if focusing on self-view with videos present so
  the label does not overlap videos transitioning from 0 opacity.
- Transition delay when de-focusing on self-view with videos present
  so videos have time to go away before the label moves over them.
- Maintain no movement if there are no videos, regardless of
  filmstrip toggle state.
- Different delays for when the filmstrip is being toggled visible
  and hidden if there are remote videos visible.

* SQUASH: remove remote videos count

* SQUASH: add docs to scss
2017-05-24 20:57:55 -05:00
Leonard Kim
346980308b fix(video-label): Show darker background on hover 2017-05-24 15:32:58 -07:00
yanas
abd30e0269 Merge pull request #1601 from jitsi/disable-speakerstats-filmstrip-only
Disables speaker stats in filmStrip only mode.
2017-05-24 16:50:39 -05:00
yanas
cbe395f463 Merge pull request #1600 from virtuacoplenny/lenny/filmstrip-1-on-1
fix(filmstrip-only): hide video label, always show remote thumbnails
2017-05-24 16:14:04 -05:00
damencho
59d4523d72 Disables speaker stats in filmStrip only mode. 2017-05-24 16:10:42 -05:00
Leonard Kim
27f968e753 fix(filmstrip-only): hide video label, always show remote thumbnails 2017-05-24 13:23:21 -07:00
yanas
a2ebc169e4 Merge pull request #1598 from virtuacoplenny/lenny/status-label-z
fix(video-label): modify z-index and cursor
2017-05-24 14:52:11 -05:00
yanas
d10cc66036 Merge pull request #1595 from virtuacoplenny/lenny/move-to-corner
fix(vertical-filmstrip): do not move recording label if not in the co…
2017-05-24 14:21:06 -05:00
Leonard Kim
3d0226ccd0 fix(video-label): modify z-index and cursor
- Change z-index so any tooltips that display over the label,
  particularly in vertical filmstrip mode, actually hide the label.
- Change the cursor to be a pointer so the label looks clickable.
- Remove unused audio-only-label styling.
2017-05-24 10:33:26 -07:00
Leonard Kim
acb4d12928 fix(vertical-filmstrip): do not move recording label if not in the corner 2017-05-23 17:14:48 -07:00
yanas
600f7bcf7b Merge pull request #1594 from jitsi/fix-scrollbars
Re-styles scrollbars
2017-05-23 16:26:29 -05:00
yanas
1ff89c5a1c Merge pull request #1587 from virtuacoplenny/lenny/vertical-filmstrip
vertical filmstrip and 1-on-1 mode
2017-05-23 16:23:11 -05:00
Leonard Kim
56b12bd969 fix(vertical-filmstrip): move video status labels back to top right
The video status labels, which include recording and hd status,
have been moved back to the top left while in vertical filmstrip
mode. The following had to be done:
- Remove styling to move the labels to the bottom left
- For VideoStatusLabel, move filmstrip remote video count, toggle
  state, and 1:1 state into redux.
- Use middleware to emit out to the Recording label when the
  filmstrip changes.
- Create an empty Filmstrip file for web and identify the existing
  Filmstrip component as native.
2017-05-23 13:28:27 -07:00
Leonard Kim
2333249b05 feat(1-on-1): Initial implementation
- Expose an api on Filmstrip to hide the remote videos container, which does so
  by adding a class
- Modify listeners for user join, leave, share video to call the api
- Hide the container when there is 1 or fewer remote participants
- Always show the container if self view is in focus
- Show the container if the number of remote thumbnails does not match the count
  of remote participants, such as the case of sharing a video
2017-05-23 13:28:27 -07:00
Leonard Kim
aabe641047 feat(vertical-filmstrip): Initial implementation
- Add a class to the body when in vertical filmstrip mode
- Override styles as necessary to support the mode
- Add an option to make tooltips display from the left
- Move the HD Label to the bottom left
- Move the remote video menu to the bottom left, move the mute
  icons to the bottom right
- Scale the local video's height and width to fit the filmstrip
2017-05-23 13:28:27 -07:00
yanas
dc5a29a976 Re-styles scrollbars 2017-05-23 15:17:46 -05:00
Leonard Kim
82ecfac4ee fix(filmstrip): Separate remote videos and local video
The 1:1 call UI and vertical filmstrip act on remote videos
while leaving local video alone. To facilitate acting only on
remote videos, place remote videos into their own container element.
2017-05-23 09:07:41 -07:00
hristoterezov
23fea490aa Merge pull request #1585 from jitsi/dial-out-ui
Adds dial-out UI.
2017-05-23 10:29:23 -05:00
yanas
1d60300016 Merge pull request #1592 from virtuacoplenny/lenny/slider-width
fix(volume-slider): modify positioning so slider fits popup width
2017-05-23 10:15:36 -05:00
yanas
6536f82559 fix(Dialog.web.js): Fixes okDisabled state not taken into account 2017-05-23 09:00:40 -05:00
yanas
4464a11314 Changes telephone icon 2017-05-23 09:00:40 -05:00
yanas
2855ea1500 Adds dial-out UI. 2017-05-23 09:00:40 -05:00
Leonard Kim
258dc594dd fix(volume-slider): modify positioning so slider fits popup width 2017-05-22 14:16:06 -07:00
Leonard Kim
a1476c68f1 fix(audio-only): remove button from toolbar and set label cursor
Audio only mode will be toggleable only from the VideoStatusLabel,
so remove AudioOnlyButton from the toolbar and delete the component
itself. As a result of the button being removed, a truthy check in
VideoStatusLabel was also removed to ensure it will display as it
is now the only way to toggle audio only mode. Also set the cursor
on VideoStatusLabel to always be default, so it can never show the
text cursor.
2017-05-22 14:46:05 -05:00
damencho
bf163d221c Adds download source archive link to the README. 2017-05-22 11:28:04 -05:00
yanas
7900b9c294 Merge pull request #1577 from virtuacoplenny/lenny/invite-conference-number
feat(invite): Add conference id to dial-in numbers display
2017-05-22 11:08:18 -05:00
jitsi-pootle
6a17d50423 New files added from translate.jitsi.org based on templates 2017-05-22 14:54:57 +00:00
Leonard Kim
9e7f8d0e16 SQUASH: use redux to get config 2017-05-19 16:07:13 -07:00
Leonard Kim
3a99ef512e SQUASH: add comment to styling and alpha order 2017-05-19 15:41:42 -07:00
Leonard Kim
a14886031f SQUASH: changes based on feedback: rename, handle error 2017-05-19 15:35:47 -07:00
Дамян Минков
ec881e0fd0 Merge pull request #1580 from jitsi/fix-isguest-typeerror
Fix TypeError: Cannot read property 'isGuest' of undefined
2017-05-18 13:10:28 -05:00
Leonard Kim
80989147ad feat(video-label): Add dropdown for toggling audio only
Add a menu that displays when hovering over VideoStatusLabel. The menu's
display is controlled by CSS. As the existing AudioOnlyLabel no longer needs
needs its own tooltip, it has been removed and label display logic has been
moved into VideoStatusLabel.
2017-05-18 13:09:34 -05:00
Lyubo Marinov
3c31a60b32 Fix TypeError: Cannot read property 'isGuest' of undefined 2017-05-18 11:53:45 -05:00
Lyubo Marinov
db59b45076 Upgrade NPM dependencies/packages 2017-05-17 16:41:52 -05:00
Leonard Kim
0f0ff6788c fix(config): Bring back minHDHeight 2017-05-17 16:13:16 -05:00
Leonard Kim
47c07c2e76 feat(invite): Add conference id to dial-in numbers display
DialInNumbersForm has been modified to display a conference id to be used for
dialing into the conference. The changes include:
- Requesting the conference id and adding the conference id to the redux store
- Displaying the conference id in DialInNumbersForm
- Modifying the copy behavior to support copying the new message to clipboard
- DialInNumbersForm does not display until all ajax requests have completed
  successfully. This eliminates the need for the REQUESTING state.
2017-05-17 10:25:07 -07:00
Leonard Kim
896dcde2b2 fix(video-label): Listen to resize events on video elements when possible 2017-05-17 11:54:22 -05:00
Leonard Kim
a88409bbfa fix(video-label): Display based on video dimensions in LargeVideoManager
In its current implementation, the VideoStatusLabel shows HD based on peer
connection stats. These stats will be available on temasys browsers soon but
will remain unavailable on Firefox, which does not collect height/width stats.
To support VideoStatusLabel showing cross-browser, move the high-definition
detection out of stat sniffing and instead check the video element itself using
an interval in LargeVideoManager. (An interval was used because the temasys
video object does not support the onresize event.) Also, add a cleanup path from
conference.web to LargeVideoManager to remove the interval.
2017-05-17 11:54:22 -05:00
damencho
b8189a31ad Updates quick-install with mention of jvb behind nat and link to config. 2017-05-16 16:26:47 -05:00
damencho
e90d09a6d9 Updates recording instructions in manual install doc. 2017-05-16 16:19:31 -05:00
damencho
9fb49cb59b Updates default config, avoids storing muc data on prosody restart. 2017-05-16 16:04:26 -05:00
Любомир Маринов
77ab05823d Merge pull request #1576 from jitsi/remote_control_enabled
fix(remotecontrol): Controller enabled property
2017-05-16 12:49:17 -05:00
hristoterezov
28ff188f96 fix(remotecontrol): Controller enabled property 2017-05-16 12:45:39 -05:00
Saúl Ibarra Corretgé
bac191f96c [RN] Rename jitsi-meet-react to jitsi-meet 2017-05-16 12:38:36 -05:00
yanas
e1a9487896 Merge pull request #1562 from virtuacoplenny/lenny/filmstrip-disable-hiding
fix(filmstrip): Disable keyboard shortcut for hiding videos
2017-05-16 11:59:44 -05:00
damencho
9e728e4b25 Fixes crashing jwt util for anonymous domains.
Room name verification crashes when we have a configured anonymousdomain as it doesn't have any token extracted data. It is safe to skip this check as room creation is verified by jicofo and we have the option restrict_room_creation to admin users.
Removes obsolete print when updating jitsi-meet-tokens.
2017-05-16 08:21:46 -05:00
bgrozev
06d2c9fb7b Merge pull request #1573 from saghul/enable-ff-ds
fix(screen-sharing) Enable it by default on Firefox
2017-05-15 15:14:49 -05:00
Дамян Минков
63c862d925 Updates docs report issue part. 2017-05-15 10:57:31 -05:00
Saúl Ibarra Corretgé
a96a70869d fix(screen-sharing) Enable it by default on Firefox
Starting with Firefox 51 the extension is no longer mandatory, so make sure the
feature is not desabled by default.
2017-05-15 12:15:00 +01:00
damencho
ede5be119f Skips changing prosody config on upgrading jitsi-meet-tokens package. 2017-05-12 16:12:15 -05:00
Saúl Ibarra Corretgé
b7c57d306a Merge pull request #1565 from virtuacoplenny/lenny/defensive-classnames
fix(toolbox): Defensively check classNames when mapping button attrib…
2017-05-12 10:10:04 +02:00
Leonard Kim
816eef1702 fix(toolbox): Defensively check classNames when mapping button attributes 2017-05-11 14:35:33 -07:00
Leonard Kim
92eeba5392 fix(filmstrip): Disable keyboard shortcut for hiding videos 2017-05-10 14:04:09 -07:00
Lyubo Marinov
2f3706bd37 [RN] Simplify
There were getDomain, setDomain, SET_DOMAIN, setRoomURL, SET_ROOM_URL
which together were repeating one and the same information and in the
case of the 'room URL' abstraction was not 100% accurate because it
would exist even when there was no room. Replace them all with a
'location URL' abstraction which exists with or without a room.

Then the 'room URL' abstraction was not used in (mobile) feature
share-room. Use the 'location URL' there now.

Finally, removes source code duplication in supporting the Web
application context root.
2017-05-09 16:31:21 -05:00
Lyubo Marinov
e6f6884c36 [RN] Support JSON Web Token (JWT)
Make 'Add jwt module to react' work on mobile.
2017-05-09 00:21:14 -05:00
Ilya Daynatovich
ab5c2e9ded Add jwt module to react 2017-05-09 00:21:14 -05:00
Ilya Daynatovich
4f72225372 Add set room url action 2017-05-09 00:21:13 -05:00
Ilya Daynatovich
3af0976a43 Beautify URLProcessor 2017-05-09 00:21:13 -05:00
Ilya Daynatovich
96b1f0ca74 Create config util 2017-05-09 00:21:13 -05:00
damencho
32ea2161eb Hides sip dialout button if configured to show it for non guest users. 2017-05-08 15:34:32 -05:00
damencho
c8ab1b9892 Catches promise errors, returned when error is received after dial cmd. 2017-05-08 15:34:32 -05:00
damencho
61e637a639 Adds prosody module to filter incoming rayo iqs based on jwt token.
Returns forbidden error message if module is enabled and the user sending a dialout rayo command is not authenticated through jwt token or is not allowed to enter the room name from the rayo iq.
2017-05-08 15:34:32 -05:00
damencho
7d94d3fd1a Updates room size API to work with multiple domains.
Checks for a parameter named subdomain and if it exists, adds it to the roomname as used in multiple domain mode ([subdomain]roomname@conference.example.com).
Moves muc_size module to per-host module and adds token verification.
2017-05-08 11:23:13 -05:00
damencho
88a58a057e Removes not needed parameter token in process_and_verify_token. 2017-05-08 11:23:13 -05:00
damencho
4bb51516bb Adds domain name verification and multidomain support.
Adds option to enable/disable domain checking, disabled by default. Domain verification for multiple domains depends on new option muc_mapper_domain_base.
2017-05-08 11:23:13 -05:00
damencho
0805b9e99e Removes disableRoomNameConstraints option.
This option is useless, as if we do not need to verify room name, we just disable the mod_token_verification module.
2017-05-08 11:23:13 -05:00
damencho
82b27b45fe Moves token related code into util so it can be reused. 2017-05-08 11:23:13 -05:00
yanas
166fb1d13f Merge pull request #1509 from virtuacoplenny/lenny/web-audio-only
Audio only mode for web
2017-05-05 11:52:15 -05:00
Leonard Kim
ef9f145cb5 fix(video-layout): always honor local video changes
During the implementation of starting as video muted, a check
was put in place to update the local thumbnail view container's
known local track only if the track was not muted. This can
cause the container to become desynced with the current local
track.(Ideally in the future all state would be in redux so this
manual syncing would not be needed.) Removing the if-muted
check seems to cause no side-effects and makes implementation of
device-switch-while-audio-only a lot simpler because new tracks
can be muted and used immediately.
2017-05-05 09:27:59 -07:00
Leonard Kim
929bc8b8b9 fix(device-selection): do not reuse tracks in previews
Device selection has live previews that reuse the current local
audio and video tracks for the sake of internet explorer. This
means when the local video was muted, device selection would
show a muted message. It is preferred to show a live preview
even when muted.

The changes include:
- Passing device ids into DeviceSelectionDialog, not tracks.
- Setting default selected devices to use for live previews.
- Removing all checks in DeviceSelectionDialog involving local tracks.
- Catching and displaying errors when creating a live video preview.
2017-05-05 09:27:59 -07:00
Leonard Kim
d24d5d95dd fix(audio-only): combine video status labels
Move the HD label into the newly renamed VideoStatusLabel
component. That way it cannot be possible for the audio only
label and the HD label to display simultaneously.
2017-05-05 09:27:59 -07:00
Saúl Ibarra Corretgé
9ba3a1c4ff feat(conference): add audio only mode
Audio only mode can be used to save bandwidth. In this mode local video is muted
and last N is set to 0, thus disabling all remote video.

When this mode is enabled avatars are shown.
2017-05-05 09:27:59 -07:00
yanas
1bcdbd1d96 Merge pull request #1552 from virtuacoplenny/lenny/ff-avatar-inlay
fix(filmstrip): Set avatar container height within inlay
2017-05-05 11:25:08 -05:00
Leonard Kim
8ada06cfe3 fix(filmstrip): Set avatar container height within inlay
In the filmstrip inlay, the avatar container holds the avatar
image. The image is set to 100% height, so it displays entirely
in the container. However, this does not adjust the horizontal
space created by the image in firefox, leaving whitespace to the
right of the avatar. The fix is to set the container height to
100% so that all its content will fit inside, automatically
adjusting the space created by the image width.
2017-05-04 11:46:10 -07:00
yanas
bf0be99366 Merge pull request #1551 from jitsi/smileys-fix
Fixes #1549, toggles smileys menu.
2017-05-04 11:28:27 -05:00
damencho
653f1dae4c Fixes #1549, toggles smileys menu. 2017-05-04 11:19:46 -05:00
hristoterezov
d91340166d Remote control - display the authorization dialog in meet (#1541)
* fix(react/participant): store display name in redux

* feat(remotecontrol): Add option to display the authorization dialog in meet

* feat(remotecontrol): Enable ESLint and Flow
2017-05-03 18:57:52 -05:00
Дамян Минков
d694e8df86 Updates README, removing "Discuss" section. 2017-05-03 13:00:46 -05:00
Lyubo Marinov
75a486ff96 Merge branch 'abstract_transport2'
Additionally, attempt to move closer to the coding style adopted by
react/.
2017-05-02 17:40:16 -05:00
Leonard Kim
48626ee71b fix(toolbox): move default toolbox buttons logic to web only
toolbox/functions has functions that are specific only to web,
specifically defaultToolbarButtons. This has caused the native
build to attempt to bring in a web dependency which leads to a
build error. The fix for now is splitting web functions from
native functions to resolve the build error.
2017-05-02 12:01:54 -05:00
hristoterezov
b297aa3f3a ref(remotecontrol): Changing the format of the messages 2017-05-02 09:47:07 -05:00
hristoterezov
dfc94ff144 ref(iframe_API): Changing the format of the outgoing messages for API.js 2017-05-01 15:59:18 -05:00
yanas
1ffa7be4e1 Merge pull request #1531 from virtuacoplenny/lenny/invite-phone-numbers
feat(invite): include dial-in numbers in the invite modal
2017-05-01 15:39:38 -05:00
Leonard Kim
d7cccacc12 feat(invite): include dial-in numbers in the invite modal
Create a new React Component for displaying a list of dial-in
numbers. The Component will fetch the numbers from a new
numberRetreviewUrl key/value set in config. If not present in
config, the Component will not be displayed.
2017-05-01 12:47:35 -07:00
hristoterezov
96bde3ff44 fix(trnasport): Names of the arguments for Transport and backend
Now the backends are working with 'message' and Transport is
working with 'request', 'response' and 'event'.
2017-04-28 16:03:36 -05:00
hristoterezov
b49c1c6ba2 fix(transport): Code style issues and enableLegacyFormat param bug
Improves naming.
Fixing typos.
enableLegacyFormat param was working like disableLegacyFormat.
Improves the structure of transport/index.js
2017-04-28 15:24:20 -05:00
Lyubo Marinov
e9dc9c47a9 Coding style
For lack of a better word/phrase, I'm calling all changes coding style.
I'm targeting readability through naming and syntax.
2017-04-28 10:41:08 -05:00
hristoterezov
3e055c1201 ref(external_api): To use transport module 2017-04-28 10:41:08 -05:00
hristoterezov
54388b6a0a ref(remotecontrol): To use transport module instead of API 2017-04-28 10:41:08 -05:00
hristoterezov
0dff35c0db feat(transport): Implement transport module
The transport module will be handling all external app
communication.
2017-04-28 10:41:08 -05:00
yanas
6c676f8d5f Merge pull request #1538 from virtuacoplenny/lenny/device-selection-disabled
fix(device-selection): do not create a dropdown menu if disabled
2017-04-26 17:16:28 -05:00
Leonard Kim
4e95dbf0e5 fix(device-selection): do not create a dropdown menu if disabled
AtlasKit DropdownMenu cannot be disabled, unlike Single Select.
The result is the isDisabled prop was not being honored. The
workaround is returning only the trigger element for the dropdown
and styling it to look like the dropdown is disabled. The text
for disabled device selection was changed along the way to fit
into the trigger.
2017-04-26 14:29:32 -07:00
Guus der Kinderen
00b4176bf8 Non-clickable watermarks without links
Watermarks can be used to link to an external site by configuring a URL.
However, the URL is optional. When it is not set, the watermark should
not be clickable. This prevents users from reloading the room by
clicking on a watermark (caused by an HTML anchor element without an
href).
2017-04-26 10:54:32 -05:00
Lyubo Marinov
7836fd1990 Introduce features/base/logging
The functionality around logging including logging_config.js i.e.
loggingConfig and the other classes and/or functions that initialize
loggers for Jits Meet truly deserves a feature of its own. Start getting
in that direction on both Web and mobile by introducing
features/base/logging and bringing loggingConfig to mobile.
2017-04-23 23:30:53 -05:00
Lyubo Marinov
92e765ea21 Introduce features/base/config
The config object defined by lib-jitsi-meet is not used by
lib-jitsi-meet only, jitsi-meet respects its values as well.
Moreover, jitsi-meet defined classes and/or functions which manipulate
that config object. Consequently, it makes sense to move the config
object and the associated classes and functions in a dedicated feature.
2017-04-23 15:18:41 -05:00
paweldomas
16d9ef5f1c [RN] export RTCIceCandidate
Required for P2P.
2017-04-23 13:54:12 -05:00
Lyubo Marinov
bce1610794 Simplify, comply w/ coding style
Rename setStateProperties and setStateProperty to assign and set,
respectively. Inspired by Object.assign, _.assign, and _.set.
2017-04-22 17:57:08 -05:00
Lyubo Marinov
1f16233afa Upgrade NPM dependencies/packages 2017-04-22 17:27:16 -05:00
yanas
e804548b22 Merge pull request #1529 from virtuacoplenny/lenny/device-overflow-stopgap
fix(device-selection): convert trigger element to a div
2017-04-21 17:05:33 -05:00
yanas
dc994173d7 Merge pull request #1500 from virtuacoplenny/whitelist-user-select
fix: do not apply user-select none to inputs
2017-04-21 13:12:07 -05:00
Leonard Kim
283140d16a fix: do not apply user-select none to inputs
Safari will prevent proper input behavior when user-select none
is applied. It prevents such actions as putting in a room lock
password or setting a room lock password. Other browsers allow
selecting on inputs while user-select is none.
2017-04-21 11:10:47 -07:00
Leonard Kim
03155c63ae fix(device-selection): pass translation key into the translate function 2017-04-21 08:58:34 -07:00
Leonard Kim
17fc28b020 fix(device-selection): convert trigger element to a div
AtlasKit Dropdown was recently updated to support fitting the
width of its container. However, AtlasKit Button, the trigger
element currently used for the dropdowns, does not fit the width
of AtlasKit Dropdown and stll has text overflowing out of its
button when there is an iconBefore prop passed in. Instead of
using AtlasKit Button, use a div and mimic the button look. This
allows the "button" to fit the container width and can display
ellipsized text within itself.
2017-04-20 19:34:02 -07:00
Saúl Ibarra Corretgé
607bef8d68 Merge pull request #1518 from jitsi/fix_removeListeners
fix(external_api): JS error in removeListeners and simplifies dispose
2017-04-20 23:47:15 +02:00
hristoterezov
55f5ceb85a fix(external_api): JS error in removeListeners and simplifies dispose 2017-04-20 15:08:13 -05:00
Saúl Ibarra Corretgé
7be8e3e1e9 Merge pull request #1523 from virtuacoplenny/lenny/mute-overlay-black
fix(device-selection): show black background only when video muted
2017-04-20 15:16:53 +02:00
Lyubo Marinov
55c3f5ddff Comply w/ coding style
@virtuacoplenny, the changes of this commit are not necessarily in
source code that you introduced in
https://github.com/jitsi/jitsi-meet/pull/1499 but I saw violations in
files modified in the PR which I had to read in order to understand the
PR.
2017-04-19 20:56:19 -05:00
Leonard Kim
44b81b20e3 feat: convert invite dialog to react and redux
Converting the invite modal includes the following:
- Creating new react components to display InviteDialog. The
  main parent components are ShareLink and PasswordOverview,
  the later handles displaying lock state and password editing.
  These components do not make use of atlaskit as the component
  for input does not yet support readonly, so for consistency
  within the modal content no atlaskit was used.
- Using redux for keeping and accessing lock state instead of
  RoomLocker.
- Publicly exposing the redux action lockStateChanged for direct
  calling on lock events experienced on the web client.
- Removing Invite, InviteDialogView, and RoomLocker and references
  to them.
- Handling errors that occur when setting a password to preserve
  existing web funtionality.
2017-04-19 20:41:23 -05:00
yanas
4097be1908 Merge pull request #1524 from jitsi/overlay_on_top
fix(overlay): Make the overlays on top of everything
2017-04-19 17:42:02 -05:00
hristoterezov
f6ef727573 fix(overlay): Make the overlays on top of everything 2017-04-19 17:09:22 -05:00
Leonard Kim
1045cb56fe fix(device-selection): show black background only when video muted
On certain modal dimensions, the black background of the video
preview could peek through, making it look like the video has a
black line. The change is to remove the black background from
showing by default and having it only display when the video is
muted. Also, the video preview dimension stylings have been
changed to facilitiate smoother size adjusting with modal size
changes.
2017-04-19 14:51:51 -07:00
Lyubo Marinov
6c0ad4966e [Android] Go back to minSdkVersion 16 2017-04-19 13:55:44 -05:00
Saúl Ibarra Corretgé
5d50792a56 [RN] Make AudioMode more resilient on Android
Some devices may give an error stating that INTERACT_ACROSS_USERS_FULL
permission is neeced. This permission can only be achieved by signing the
application with the same key as the system, which is never going to happen so
deal with it by catching any exceptions setting the mode may cause and failing
as gracefully as we can.

Ref:
http://stackoverflow.com/questions/34172575/audiomanager-setmode-securityexception-on-huawei-android-4
2017-04-19 13:55:44 -05:00
Saúl Ibarra Corretgé
0c16842e0d [RN] Fix full-screen mode when a dialog is opened on Android
When a dialog is opened on Android, full-screen mode is exited but we (the app)
know nothing about this. Make sure we re-enter full-screen mode once a dialog is
closed, if the conditions to be in such mode are still met.
2017-04-19 13:55:44 -05:00
730 changed files with 70945 additions and 20445 deletions

View File

@@ -1,44 +1,5 @@
module.exports = {
'env': {
'browser': true,
'commonjs': true,
'es6': true
},
'extends': [
'eslint:recommended',
'plugin:flowtype/recommended'
],
'globals': {
// The globals that (1) are accessed but not defined within many of our
// files, (2) are certainly defined, and (3) we would like to use
// without explicitly specifying them (using a comment) inside of our
// files.
'__filename': false
},
'parser': 'babel-eslint',
'parserOptions': {
'ecmaFeatures': {
'experimentalObjectRestSpread': true
},
'sourceType': 'module'
},
'plugins': [
'flowtype'
],
'rules': {
'new-cap': [
'error',
{
'capIsNew': false // Behave like JSHint's newcap.
}
],
// While it is considered a best practice to avoid using methods on
// console in JavaScript that is designed to be executed in the browser
// and ESLint includes the rule among its set of recommended rules, (1)
// the general practice is to strip such calls before pushing to
// production and (2) we prefer to utilize console in lib-jitsi-meet
// (and jitsi-meet).
'no-console': 'off',
'semi': 'error'
}
'eslint-config-jitsi'
]
};

View File

@@ -14,38 +14,59 @@
.*/Libraries/react-native/React.js
.*/Libraries/react-native/ReactNative.js
; Ignore polyfills
.*/Libraries/polyfills/.*
; Ignore packages in node_modules which we (i.e. the jitsi-meet project) have
; seen to cause errors and we have chosen not to fix.
.*/node_modules/babel-core/.*
.*/node_modules/bower/.*
.*/node_modules/jsonlint/.*
.*/node_modules/@atlassian
.*/node_modules/bower/lib/node_modules/bower-json/test/.*
.*/node_modules/jsonlint/test/.*
; FIXME Remove once we update past this commit:
; https://github.com/facebook/react-native/commit/df8d0d1db9203cc87ad3682e6138b2a9ed714365
.*/node_modules/react-native/local-cli/link/link.js
.*/node_modules/react-native-keep-awake/.*
.*/node_modules/styled-components/.*
.*/\.git/.*
[include]
[libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/flow
flow/
[options]
emoji=true
module.system=haste
experimental.strict_type_args=true
; FIXME: munge_underscores should be false but right now there are some errors
; if we change the value to false
; Treats class properties with underscore as private. Disabled because currently
; for us "_" can mean protected too.
; munge_underscores=false
munge_underscores=true
; FIXME Remove once we update past this commit:
; https://github.com/facebook/react-native/commit/df8d0d1db9203cc87ad3682e6138b2a9ed714365
module.name_mapper='^./link/link$' -> 'emptyObject'
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FlowFixMeProps
suppress_type=$FlowFixMeState
suppress_type=$FixMe
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(3[0-8]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(3[0-8]\\|1[0-9]\\|[1-2][0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(5[0-3]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native_oss[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(5[0-3]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native_oss[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
suppress_comment=\\(.\\|\n\\)*\\$FlowDisableNextLine
unsafe.enable_getters_and_setters=true
@@ -62,4 +83,4 @@ module.file_ext=.jsx
module.file_ext=.json
[version]
^0.38.0
^0.53.0

4
.gitignore vendored
View File

@@ -65,3 +65,7 @@ buck-out/
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
# CocoaPods
Pods/
Podfile.lock

View File

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

View File

@@ -1,20 +0,0 @@
{
// Refer to http://jshint.com/docs/options/ for an exhaustive list of options
"asi": false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
"expr": true, // true: Tolerate `ExpressionStatement` as Programs
"loopfunc": true, // true: Tolerate functions being defined in loops
"curly": false, // true: Require {} for every new block or scope
"evil": true, // true: Tolerate use of `eval` and `new Function()`
"white": true,
"undef": true, // true: Require all non-global variables to be declared (prevents global leaks)
"browser": true, // Web Browser (window, document, etc)
"node": true, // Node.js
"trailing": true,
"indent": 4, // {int} Number of spaces to use for indentation
"latedef": true, // true: Require variables/functions to be defined before being used
"newcap": true, // true: Require capitalization of all constructor functions e.g. `new F()`
"maxlen": 80, // {int} Max number of characters per line
"latedef": false, //This option prohibits the use of a variable before it was defined
"laxbreak": true, //Ignore line breaks around "=", "==", "&&", etc.
"esnext": true //support ES2015
}

View File

@@ -3,13 +3,9 @@ We would love to have your help. Before you start working however, please read
and follow this short guide.
# Reporting Issues
Before you open an issue on GitHub, please discuss it on one of our
[mailing lists](https://jitsi.org/Development/MailingLists) and wait for
confirmation from one of the committers. Once you have that confirmation,
please proceed to reporting the issue on GitHub, while providing as much
information as possible. Mention the version of Jitsi Meet, Jicofo and JVB
you are using, and explain (as detailed as you can) how the problem can
be reproduced.
Provide as much information as possible. Mention the version of Jitsi Meet,
Jicofo and JVB you are using, and explain (as detailed as you can) how the
problem can be reproduced.
# Code contributions
Found a bug and know how to fix it? Great! Please read on.

View File

@@ -1,11 +1,11 @@
/**
* Notifies interested parties that hangup procedure will start.
*/
export const BEFORE_HANGUP = "conference.before_hangup";
export const BEFORE_HANGUP = 'conference.before_hangup';
/**
* Notifies interested parties that desktop sharing enable/disable state is
* changed.
*/
export const DESKTOP_SHARING_ENABLED_CHANGED
= "conference.desktop_sharing_enabled_changed";
= 'conference.desktop_sharing_enabled_changed';

View File

@@ -31,6 +31,8 @@ deploy-appbundle:
$(BUILD_DIR)/do_external_connect.min.map \
$(BUILD_DIR)/external_api.min.js \
$(BUILD_DIR)/external_api.min.map \
$(BUILD_DIR)/device_selection_popup_bundle.min.js \
$(BUILD_DIR)/device_selection_popup_bundle.min.map \
$(OUTPUT_DIR)/analytics.js \
$(DEPLOY_DIR)

View File

@@ -15,9 +15,12 @@ For other systems, or if you wish to install all components manually, see the [d
## Download
You can download Debian/Ubuntu binaries:
* [stable](https://download.jitsi.org/stable/) ([instructions](https://jitsi.org/Main/InstallJitsiMeetDebianStableRepository))
* [testing](https://download.jitsi.org/testing/) ([instructions](https://jitsi.org/Main/InstallJitsiMeetDebianTestingRepository))
* [nightly](https://download.jitsi.org/unstable/) ([instructions](https://jitsi.org/Main/InstallJitsiMeetDebianNightlyRepository))
* [stable](https://download.jitsi.org/stable/) ([instructions](https://jitsi.org/downloads/ubuntu-debian-installations-instructions/))
* [testing](https://download.jitsi.org/testing/) ([instructions](https://jitsi.org/downloads/ubuntu-debian-installations-instructions-for-testing/))
* [nightly](https://download.jitsi.org/unstable/) ([instructions](https://jitsi.org/downloads/ubuntu-debian-installations-instructions-nightly/))
You can download source archives (produced by ```make source-package```):
* [source builds](https://download.jitsi.org/jitsi-meet/src/)
You can get our mobile versions from here:
* [Android](https://play.google.com/store/apps/details?id=org.jitsi.meet)
@@ -25,6 +28,8 @@ You can get our mobile versions from here:
## Building the sources
Node.js >= 6 is required.
On Debian/Ubuntu systems, the required packages can be installed with:
```
sudo apt-get install npm nodejs-legacy
@@ -94,11 +99,8 @@ see our [guidelines for contributing](CONTRIBUTING.md).
Jitsi Meet provides a very flexible way of embedding it in external applications by using the [Jitsi Meet API](doc/api.md).
## Mobile app
Jitsi Meet is also available as a React Native application for Android and iOS.
Instructions on how to build it can be found [here](doc/mobile.md).
## Discuss
Please use the [Jitsi dev mailing list](http://lists.jitsi.org/pipermail/dev/) to discuss feature requests before opening an issue on Github.
Jitsi Meet is also available as a React Native app for Android and iOS.
Instructions on how to build it can be found [here](doc/mobile.md).
## Acknowledgements

View File

@@ -1,33 +1,44 @@
/* global ga */
(function (ctx) {
function Analytics() {
/* eslint-disable */
(function(ctx) {
/**
* Google Analytics
*
*/
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-319188-14', 'jit.si');
ga('send', 'pageview');
function Analytics() {
/* eslint-disable */
/* eslint-enable */
}
/**
* Google Analytics
*/
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-319188-14', 'jit.si');
ga('send', 'pageview');
Analytics.prototype.sendEvent = function (action, data) {
// empty label if missing value for it and add the value,
// the value should be integer or null
var value = data.value;
value = value? Math.round(parseFloat(value)) : null;
var label = data.label || "";
/* eslint-enable */
}
ga('send', 'event', 'jit.si',
action + '.' + data.browserName, label, value);
};
Analytics.prototype.sendEvent = function(action, data) {
// empty label if missing value for it and add the value,
// the value should be integer or null
let value = data.value;
if(typeof ctx.analyticsHandlers === "undefined")
ctx.analyticsHandlers = [];
ctx.analyticsHandlers.push(Analytics);
}(window));
value = value ? Math.round(parseFloat(value)) : null;
const label = data.label || '';
ga('send', 'event', 'jit.si',
`${action}.${data.browserName}`, label, value);
};
if (typeof ctx.JitsiMeetJS === 'undefined') {
ctx.JitsiMeetJS = {};
}
if (typeof ctx.JitsiMeetJS.app === 'undefined') {
ctx.JitsiMeetJS.app = {};
}
if (typeof ctx.JitsiMeetJS.app.analyticsHandlers === 'undefined') {
ctx.JitsiMeetJS.app.analyticsHandlers = [];
}
ctx.JitsiMeetJS.app.analyticsHandlers.push(Analytics);
})(window);

311
android/README.md Normal file
View File

@@ -0,0 +1,311 @@
# Jitsi Meet SDK for Android
## Build
1. Install all required [dependencies](https://github.com/jitsi/jitsi-meet/blob/master/doc/mobile.md).
2. ```bash
cd android/
./gradlew :sdk:assembleRelease
```
3. Configure the Maven repositories in which you are going to publish the
artifacts/binaries during step 4. Modify
`"file:${rootProject.projectDir}/../../../jitsi/jitsi-maven-repository/releases"`
in adroid/sdk/build.gradle for Jitsi Meet SDK for Android and/or
`"file:${rootProject.projectDir}/../../../jitsi/jitsi-maven-repository/releases"`
in android/build.gradle for the third-party react-native modules which Jitsi
Meet SDK for Android depends on and are not publicly available in Maven
repositories. Generally, if you are modifying the JavaSource code of Jitsi
Meet SDK for Android only, you will very likely need to consider the former
only.
4. Publish the Maven artifact/binary of Jitsi Meet SDK for Android in the Maven
repository configured in step 3:
```bash
./gradlew :sdk:publish
cd ../
```
If you would like to publish a third-party react-native module which Jitsi
Meet SDK for Android depends on and is not publicly available in Maven
repositories, replace `sdk` with the name of the react-native module. For
example, to publish react-native-webrtc:
```bash
./gradlew :react-native-webrtc:publish
```
## Install
Add the Maven repository
`https://github.com/jitsi/jitsi-maven-repository/raw/master/releases` and the
dependency `org.jitsi.react:jitsi-meet-sdk:1.9.0` into your `build.gradle`.
## API
Jitsi Meet SDK is an Android library which embodies the whole Jitsi Meet
experience and makes it reusable by third-party apps.
To get started, extends your `android.app.Activity` from
`org.jitsi.meet.sdk.JitsiMeetActivity`:
```java
package org.jitsi.example;
import org.jitsi.meet.sdk.JitsiMeetActivity;
public class MainActivity extends JitsiMeetActivity {
}
```
Alternatively, you can use the `org.jitsi.meet.sdk.JitsiMeetView` class which
extends `android.view.View`:
```java
package org.jitsi.example;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import org.jitsi.meet.sdk.JitsiMeetView;
public class MainActivity extends AppCompatActivity {
private JitsiMeetView view;
@Override
public void onBackPressed() {
if (!JitsiMeetView.onBackPressed()) {
// Invoke the default handler if it wasn't handled by React.
super.onBackPressed();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
view = new JitsiMeetView(this);
view.loadURL(null);
setContentView(view);
}
@Override
protected void onDestroy() {
super.onDestroy();
view.dispose();
view = null;
JitsiMeetView.onHostDestroy(this);
}
@Override
public void onNewIntent(Intent intent) {
JitsiMeetView.onNewIntent(intent);
}
@Override
protected void onPause() {
super.onPause();
JitsiMeetView.onHostPause(this);
}
@Override
protected void onResume() {
super.onResume();
JitsiMeetView.onHostResume(this);
}
}
```
### JitsiMeetActivity
This class encapsulates a high level API in the form of an Android `Activity`
which displays a single `JitsiMeetView`.
#### getDefaultURL()
See JitsiMeetView.getDefaultURL.
#### getWelcomePageEnabled()
See JitsiMeetView.getWelcomePageEnabled.
#### loadURL(URL)
See JitsiMeetView.loadURL.
#### setDefaultURL(URL)
See JitsiMeetView.setDefaultURL.
#### setWelcomePageEnabled(boolean)
See JitsiMeetView.setWelcomePageEnabled.
### JitsiMeetView
The `JitsiMeetView` class is the core of Jitsi Meet SDK. It's designed to
display a Jitsi Meet conference (or a welcome page).
#### dispose()
Releases all resources associated with this view. This method MUST be called
when the Activity holding this view is going to be destroyed, usually in the
`onDestroy()` method.
#### getDefaultURL()
Returns the default base URL used to join a conference when a partial URL (e.g.
a room name only) is specified to `loadURLString`/`loadURLObject`. If not set or
if set to `null`, the default built in JavaScript is used: https://meet.jit.si.
#### getListener()
Returns the `JitsiMeetViewListener` instance attached to the view.
#### getWelcomePageEnabled()
Returns true if the Welcome page is enabled; otherwise, false. If false, a black
empty view will be rendered when not in a conference. Defaults to false.
#### loadURL(URL)
Loads a specific URL which may identify a conference to join. If the specified
URL is null and the Welcome page is enabled, the Welcome page is displayed
instead.
#### loadURLString(String)
Loads a specific URL which may identify a conference to join. If the specified
URL is null and the Welcome page is enabled, the Welcome page is displayed
instead.
#### loadURLObject(Bundle)
Loads a specific URL which may identify a conference to join. The URL is
specified in the form of a Bundle of properties which (1) internally are
sufficient to construct a URL (string) while (2) abstracting the specifics of
constructing the URL away from API clients/consumers. If the specified URL is
null and the Welcome page is enabled, the Welcome page is displayed instead.
Example:
```java
Bundle config = new Bundle();
config.putBoolean("startWithAudioMuted", true);
config.putBoolean("startWithVideoMuted", false);
Bundle urlObject = new Bundle();
urlObject.putBundle("config", config);
urlObject.putString("url", "https://meet.jit.si/Test123");
view.loadURLObject(urlObject);
```
#### setDefaultURL(URL)
Sets the default URL. See `getDefaultURL` for more information.
NOTE: Must be called before `loadURL`/`loadURLString` for it to take effect.
#### setListener(listener)
Sets the given listener (class implementing the `JitsiMeetViewListener`
interface) on the view.
#### setWelcomePageEnabled(boolean)
Sets whether the Welcome page is enabled. See `getWelcomePageEnabled` for more
information.
NOTE: Must be called before `loadURL`/`loadURLString` for it to take effect.
#### onBackPressed()
Helper method which should be called from the activity's `onBackPressed` method.
If this function returns `true`, it means the action was handled and thus no
extra processing is required; otherwise the app should call the parent's
`onBackPressed` method.
This is a static method.
#### onHostDestroy(activity)
Helper method which should be called from the activity's `onDestroy` method.
This is a static method.
#### onHostPause(activity)
Helper method which should be called from the activity's `onPause` method.
This is a static method.
#### onHostResume(activity)
Helper method which should be called from the activity's `onResume` method.
This is a static method.
#### onNewIntent(intent)
Helper method for integrating the *deep linking* functionality. If your app's
activity is launched in "singleTask" mode this method should be called from the
activity's `onNewIntent` method.
This is a static method.
#### JitsiMeetViewListener
`JitsiMeetViewListener` provides an interface apps can implement to listen to
the state of the Jitsi Meet conference displayed in a `JitsiMeetView`.
### JitsiMeetViewAdapter
A default implementation of the `JitsiMeetViewListener` interface. Apps may
extend the class instead of implementing the interface in order to minimize
boilerplate.
##### onConferenceFailed
Called when a joining a conference was unsuccessful or when there was an error
while in a conference.
The `data` `Map` contains an "error" key describing the error and a "url" key
with the conference URL.
#### onConferenceJoined
Called when a conference was joined.
The `data` `Map` contains a "url" key with the conference URL.
#### onConferenceLeft
Called when a conference was left.
The `data` `Map` contains a "url" key with the conference URL.
#### onConferenceWillJoin
Called before a conference is joined.
The `data` `Map` contains a "url" key with the conference URL.
#### onConferenceWillLeave
Called before a conference is left.
The `data` `Map` contains a "url" key with the conference URL.
#### onLoadConfigError
Called when loading the main configuration file from the Jitsi Meet deployment
fails.
The `data` `Map` contains an "error" key with the error and a "url" key with the
conference URL which necessitated the loading of the configuration file.

View File

@@ -1,66 +0,0 @@
import re
# To learn about Buck see [Docs](https://buckbuild.com/).
# To run your application with Buck:
# - install Buck
# - `npm start` - to start the packager
# - `cd android`
# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
# - `buck install -r android/app` - compile, install and run application
#
lib_deps = []
for jarfile in glob(['libs/*.jar']):
name = 'jars__' + re.sub(r'^.*/([^/]+)\.jar$', r'\1', jarfile)
lib_deps.append(':' + name)
prebuilt_jar(
name = name,
binary_jar = jarfile,
)
for aarfile in glob(['libs/*.aar']):
name = 'aars__' + re.sub(r'^.*/([^/]+)\.aar$', r'\1', aarfile)
lib_deps.append(':' + name)
android_prebuilt_aar(
name = name,
aar = aarfile,
)
android_library(
name = 'all-libs',
exported_deps = lib_deps
)
android_library(
name = 'app-code',
srcs = glob([
'src/main/java/**/*.java',
]),
deps = [
':all-libs',
':build_config',
':res',
],
)
android_build_config(
name = 'build_config',
package = 'org.jitsi.meet',
)
android_resource(
name = 'res',
res = 'src/main/res',
package = 'org.jitsi.meet',
)
android_binary(
name = 'app',
package_type = 'debug',
manifest = 'src/main/AndroidManifest.xml',
keystore = '//android/keystores:debug',
deps = [
':app-code',
],
)

View File

@@ -1,159 +1,40 @@
apply plugin: 'com.android.application'
import com.android.build.OutputFile
/**
* The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
* and bundleReleaseJsAndAssets).
* These basically call `react-native bundle` with the correct arguments during the Android build
* cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
* bundle directly from the development server. Below you can see all the possible configurations
* and their defaults. If you decide to add a configuration block, make sure to add it before the
* `apply from: "../../node_modules/react-native/react.gradle"` line.
*
* project.ext.react = [
* // the name of the generated asset file containing your JS bundle
* bundleAssetName: "index.android.bundle",
*
* // the entry file for bundle generation
* entryFile: "index.android.js",
*
* // whether to bundle JS and assets in debug mode
* bundleInDebug: false,
*
* // whether to bundle JS and assets in release mode
* bundleInRelease: true,
*
* // whether to bundle JS and assets in another build variant (if configured).
* // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
* // The configuration property can be in the following formats
* // 'bundleIn${productFlavor}${buildType}'
* // 'bundleIn${buildType}'
* // bundleInFreeDebug: true,
* // bundleInPaidRelease: true,
* // bundleInBeta: true,
*
* // the root of your project, i.e. where "package.json" lives
* root: "../../",
*
* // where to put the JS bundle asset in debug mode
* jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
*
* // where to put the JS bundle asset in release mode
* jsBundleDirRelease: "$buildDir/intermediates/assets/release",
*
* // where to put drawable resources / React Native assets, e.g. the ones you use via
* // require('./image.png')), in debug mode
* resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
*
* // where to put drawable resources / React Native assets, e.g. the ones you use via
* // require('./image.png')), in release mode
* resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
*
* // by default the gradle tasks are skipped if none of the JS files or assets change; this means
* // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
* // date; if you have any other folders that you want to ignore for performance reasons (gradle
* // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
* // for example, you might want to remove it from here.
* inputExcludes: ["android/**", "ios/**"],
*
* // override which node gets called and with what additional arguments
* nodeExecutableAndArgs: ["node"]
*
* // supply additional arguments to the packager
* extraPackagerArgs: []
* ]
*/
apply from: '../../node_modules/react-native/react.gradle'
/**
* Set this to true to create two separate APKs instead of one:
* - An APK that only works on ARM devices
* - An APK that only works on x86 devices
* The advantage is the size of the APK is reduced by about 4MB.
* Upload all the APKs to the Play Store and people will download
* the correct one based on the CPU architecture of their device.
*/
def enableSeparateBuildPerCPUArchitecture = false
/**
* Run Proguard to shrink the Java bytecode in release builds.
*/
def enableProguardInReleaseBuilds = false
android {
compileSdkVersion 23
buildToolsVersion '23.0.1'
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
applicationId 'org.jitsi.meet'
minSdkVersion 16
targetSdkVersion 22
versionCode Integer.parseInt("${version}")
versionName "1.4.${version}"
versionName "1.9.${version}"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
ndk {
abiFilters 'armeabi-v7a', 'x86'
}
packagingOptions {
// The project react-native does not provide 64-bit binaries at the
// time of this writing. Unfortunately, packaging any 64-bit
// binaries into the .apk will crash the app at runtime on 64-bit
// platforms.
exclude 'lib/x86_64/libjingle_peerconnection_so.so'
exclude 'lib/arm64-v8a/libjingle_peerconnection_so.so'
}
}
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include 'armeabi-v7a', 'x86'
exclude '/lib/mips64/**'
exclude '/lib/arm64-v8a/**'
exclude '/lib/x86_64/**'
}
}
buildTypes {
release {
minifyEnabled enableProguardInReleaseBuilds
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
// http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
def versionCodes = ['armeabi-v7a':1, 'x86':2]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
}
}
}
}
if (project.hasProperty('JITSI_SIGNING')
&& new File(project.property('JITSI_SIGNING')).exists()) {
apply from: project.property('JITSI_SIGNING');
}
dependencies {
compile project(':react-native-background-timer')
compile project(':react-native-immersive')
compile project(':react-native-keep-awake')
compile project(':react-native-vector-icons')
compile project(':react-native-webrtc')
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.facebook.react:react-native:+' // From node_modules
}
apply from: '../../node_modules/react-native-vector-icons/fonts.gradle'
// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
from configurations.compile
into 'libs'
implementation project(':sdk')
}

View File

@@ -1,60 +1,38 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.jitsi.meet"
android:versionCode="1"
android:versionName="1.0">
<!-- XXX: ACCESS_NETWORK_STATE is required by WebRTC. -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus"/>
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="23" />
<application
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="org.jitsi.meet">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:name=".MainApplication"
android:theme="@style/AppTheme">
<activity
<activity
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTask"
android:name=".MainActivity"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:host="beta.hipchat.me" android:scheme="https" />
<data android:host="beta.meet.jit.si" android:scheme="https" />
<data android:host="chaos.hipchat.me" android:scheme="https" />
<data android:host="enso.me" android:scheme="https" />
<data android:host="hipchat.me" android:scheme="https" />
<data android:host="meet.jit.si" android:scheme="https" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="org.jitsi.meet" />
</intent-filter>
</activity>
<activity
android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:host="beta.hipchat.me" android:scheme="https" />
<data android:host="beta.meet.jit.si" android:scheme="https" />
<data android:host="chaos.hipchat.me" android:scheme="https" />
<data android:host="enso.me" android:scheme="https" />
<data android:host="hipchat.me" android:scheme="https" />
<data android:host="meet.jit.si" android:scheme="https" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="org.jitsi.meet" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -1,46 +1,105 @@
/*
* Copyright @ 2017-present 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;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends ReactActivity {
/**
* {@inheritDoc}
*
* Overrides {@link ReactActivity#createRootActivityDelegate()} to customize
* the {@link ReactRootView} with a background color that is in accord with
* the JavaScript and iOS parts of the application and causes less perceived
* visual flicker than the default background color.
*/
import org.jitsi.meet.sdk.JitsiMeetActivity;
import org.jitsi.meet.sdk.JitsiMeetView;
import org.jitsi.meet.sdk.JitsiMeetViewListener;
import java.util.Map;
/**
* The one and only {@link Activity} that the Jitsi Meet app needs. The
* {@code Activity} is launched in {@code singleTask} mode, so it will be
* created upon application initialization and there will be a single instance
* of it. Further attempts at launching the application once it was already
* launched will result in {@link Activity#onNewIntent(Intent)} being called.
*
* This {@code Activity} extends {@link JitsiMeetActivity} to keep the React
* Native CLI working, since the latter always tries to launch an
* {@code Activity} named {@code MainActivity} when doing
* {@code react-native run-android}.
*/
public class MainActivity extends JitsiMeetActivity {
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegate(this, getMainComponentName()) {
/**
* {@inheritDoc}
*
* Overrides {@link ReactActivityDelegate#createRootView()} to
* customize the {@link ReactRootView} with a background color that
* is in accord with the JavaScript and iOS parts of the application
* and causes less perceived visual flicker than the default
* background color.
*/
@Override
protected ReactRootView createRootView() {
ReactRootView rootView = super.createRootView();
protected JitsiMeetView initializeView() {
JitsiMeetView view = super.initializeView();
rootView.setBackgroundColor(0xFF111111);
return rootView;
}
};
// XXX In order to increase (1) awareness of API breakages and (2) API
// coverage, utilize JitsiMeetViewListener in the Debug configuration of
// the app.
if (BuildConfig.DEBUG && view != null) {
view.setListener(new JitsiMeetViewListener() {
private void on(String name, Map<String, Object> data) {
// Log with the tag "ReactNative" in order to have the log
// visible in react-native log-android as well.
Log.d(
"ReactNative",
JitsiMeetViewListener.class.getSimpleName() + " "
+ name + " "
+ data);
}
@Override
public void onConferenceFailed(Map<String, Object> data) {
on("CONFERENCE_FAILED", data);
}
@Override
public void onConferenceJoined(Map<String, Object> data) {
on("CONFERENCE_JOINED", data);
}
@Override
public void onConferenceLeft(Map<String, Object> data) {
on("CONFERENCE_LEFT", data);
}
@Override
public void onConferenceWillJoin(Map<String, Object> data) {
on("CONFERENCE_WILL_JOIN", data);
}
@Override
public void onConferenceWillLeave(Map<String, Object> data) {
on("CONFERENCE_WILL_LEAVE", data);
}
@Override
public void onLoadConfigError(Map<String, Object> data) {
on("LOAD_CONFIG_ERROR", data);
}
});
}
return view;
}
/**
* Returns the name of the main component registered from JavaScript.
* This is used to schedule rendering of the component.
*/
@Override
protected String getMainComponentName() {
return "App";
protected void onCreate(Bundle savedInstanceState) {
// As this is the Jitsi Meet app (i.e. not the Jitsi Meet SDK), we do
// want the Welcome page to be enabled. It defaults to disabled in the
// SDK at the time of this writing but it is clearer to be explicit
// about what we want anyway.
setWelcomePageEnabled(true);
super.onCreate(savedInstanceState);
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,14 +1,16 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
// Top-level build file where you can add configuration options common to all
// sub-projects/modules.
buildscript {
repositories {
jcenter()
maven { url 'https://maven.google.com' }
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'com.android.tools.build:gradle:3.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
// in the individual module build.gradle files.
}
}
@@ -16,9 +18,141 @@ allprojects {
repositories {
mavenLocal()
jcenter()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
maven { url "https://maven.google.com" } // Required for appcompat.
// React Native (JS, Obj-C sources, Android binaries) is installed from
// npm.
maven { url "$rootDir/../node_modules/react-native/android" }
}
// Third-party react-native modules which Jitsi Meet SDK for Android depends
// on and which are not available in third-party Maven repositories need to
// be deployed in a Maven repository of ours.
//
if (project.name.startsWith('react-native-')) {
apply plugin: 'maven-publish'
publishing {
publications {}
repositories {
maven { url "file:${rootProject.projectDir}/../../../jitsi/jitsi-maven-repository/releases" }
}
}
}
afterEvaluate { project ->
if (project.name.startsWith('react-native-')) {
def npmManifest = project.file('../package.json')
def json = new groovy.json.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-webrtc'.equals(project.name))
versionQualifier = '-jitsi-1'
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
}
}
task androidJavadocs(type: Javadoc) {
source = android.sourceSets.main.java.source
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
failOnError false
}
task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
classifier = 'javadoc'
from androidJavadocs.destinationDir
}
task androidSourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.source
}
publishing.publications {
aarArchive(MavenPublication) {
groupId rootProject.ext.moduleGroupId
artifactId project.name
version project.version
artifact("${project.buildDir}/outputs/aar/${project.name}-release.aar") {
extension "aar"
}
artifact(androidSourcesJar)
artifact(androidJavadocsJar)
pom.withXml {
def pomXml = asNode()
pomXml.appendNode('name', project.name)
pomXml.appendNode('description', json.description)
pomXml.appendNode('url', json.homepage)
if (json.license) {
def license = pomXml.appendNode('licenses').appendNode('license')
license.appendNode('name', json.license)
license.appendNode('distribution', 'repo')
}
def dependencies = pomXml.appendNode('dependencies')
configurations.getByName('releaseCompileClasspath').getResolvedConfiguration().getFirstLevelModuleDependencies().each {
def artifactId = it.moduleName
def version = it.moduleVersion
// React Native signals breaking changes by
// increasing the minor version number. So the
// (third-party) React Native modules we utilize can
// depend not on a specific react-native release but
// a wider range.
if (artifactId.equals('react-native')) {
def versionNumber = VersionNumber.parse(version)
version = "${versionNumber.major}.${versionNumber.minor}"
}
def dependency = dependencies.appendNode('dependency')
dependency.appendNode('groupId', it.moduleGroup)
dependency.appendNode('artifactId', artifactId)
dependency.appendNode('version', version)
}
}
}
}
}
}
}
ext {
buildToolsVersion = "26.0.2"
compileSdkVersion = 26
minSdkVersion = 16
targetSdkVersion = 25
// The Maven artifact groupdId of the third-party react-native modules which
// Jitsi Meet SDK for Android depends on and which are not available in
// third-party Maven repositories so we have to deploy to a Maven repository
// of ours.
moduleGroupId = 'com.facebook.react'
}
// Force the version of the Android build tools we have chosen on all
// subprojects. The forcing was introduced for react-native and the third-party
// modules that we utilize such as react-native-background-timer.
subprojects { subproject ->
afterEvaluate{
if ((subproject.plugins.hasPlugin('android')
|| subproject.plugins.hasPlugin('android-library'))
&& rootProject.ext.has('buildToolsVersion')) {
android {
buildToolsVersion rootProject.ext.buildToolsVersion
}
}
}
}

View File

@@ -1,5 +1,6 @@
#Fri Sep 08 10:42:14 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip

162
android/sdk/build.gradle Normal file
View File

@@ -0,0 +1,162 @@
apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
}
buildTypes {
debug {}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:25.4.0'
compile 'com.facebook.react:react-native:+'
compile project(':react-native-background-timer')
compile project(':react-native-fetch-blob')
compile project(':react-native-immersive')
compile project(':react-native-keep-awake')
compile project(':react-native-vector-icons')
compile project(':react-native-webrtc')
}
// Build process helpers
//
void runBefore(String dependentTaskName, Task task) {
Task dependentTask = tasks.findByPath(dependentTaskName);
if (dependentTask != null) {
dependentTask.dependsOn task
}
}
gradle.projectsEvaluated {
android.buildTypes.all { buildType ->
def buildNameCapitalized = "${buildType.name.capitalize()}"
def bundlePath = "${buildDir}/intermediates/bundles/${buildType.name}"
// Bundle fonts in react-native-vector-icons.
//
def currentFontTask = tasks.create(
name: "copy${buildNameCapitalized}Fonts",
type: Copy) {
from("${projectDir}/../../fonts/jitsi.ttf")
from("${projectDir}/../../node_modules/react-native-vector-icons/Fonts/")
into("${bundlePath}/assets/fonts")
}
currentFontTask.dependsOn("merge${buildNameCapitalized}Resources")
currentFontTask.dependsOn("merge${buildNameCapitalized}Assets")
runBefore("processArmeabi-v7a${buildNameCapitalized}Resources", currentFontTask)
runBefore("processX86${buildNameCapitalized}Resources", currentFontTask)
runBefore("processUniversal${buildNameCapitalized}Resources", currentFontTask)
runBefore("process${buildNameCapitalized}Resources", currentFontTask)
// Bundle JavaScript and React resources.
// (adapted from react-native/react.gradle)
//
// React JS bundle directories
def jsBundleDir = file("${bundlePath}/assets")
def resourcesDir = file("${bundlePath}/res/merged")
def jsBundleFile = file("${jsBundleDir}/index.android.bundle")
// Bundle task name for variant.
def bundleJsAndAssetsTaskName = "bundle${buildNameCapitalized}JsAndAssets"
def currentBundleTask = tasks.create(
name: bundleJsAndAssetsTaskName,
type: Exec) {
// Set up inputs and outputs so gradle can cache the result.
def reactRoot = file("${projectDir}/../../")
inputs.files fileTree(dir: reactRoot, excludes: ['android/**', 'ios/**'])
outputs.dir jsBundleDir
outputs.dir resourcesDir
// Set up the call to the react-native cli.
workingDir reactRoot
// Create JS bundle
def devEnabled = !buildNameCapitalized.toLowerCase().contains('release')
commandLine(
'node',
'node_modules/react-native/local-cli/cli.js',
'bundle',
'--assets-dest', resourcesDir,
'--bundle-output', jsBundleFile,
'--dev', "${devEnabled}",
'--entry-file', 'index.android.js',
'--platform', 'android',
'--reset-cache')
// Disable bundling on dev builds
enabled !devEnabled
}
// Hook bundle${productFlavor}${buildType}JsAndAssets into the android build process
currentBundleTask.dependsOn("merge${buildNameCapitalized}Resources")
currentBundleTask.dependsOn("merge${buildNameCapitalized}Assets")
runBefore("processArmeabi-v7a${buildNameCapitalized}Resources", currentBundleTask)
runBefore("processX86${buildNameCapitalized}Resources", currentBundleTask)
runBefore("processUniversal${buildNameCapitalized}Resources", currentBundleTask)
runBefore("process${buildNameCapitalized}Resources", currentBundleTask)
}
}
publishing {
publications {
aarArchive(MavenPublication) {
groupId 'org.jitsi.react'
artifactId 'jitsi-meet-sdk'
version '1.9.0'
artifact("${project.buildDir}/outputs/aar/${project.name}-release.aar") {
extension "aar"
}
pom.withXml {
def pomXml = asNode()
pomXml.appendNode('name', 'jitsi-meet-sdk')
pomXml.appendNode('description', 'Jitsi Meet SDK for Android')
def dependencies = pomXml.appendNode('dependencies')
configurations.getByName('releaseCompileClasspath').getResolvedConfiguration().getFirstLevelModuleDependencies().each {
// The (third-party) React Native modules that we depend on
// are in source code form and do not have groupId. That is
// why we have a dedicated groupId for them. But the other
// dependencies come through Maven and, consequently, have
// groupId.
def groupId = it.moduleGroup
def artifactId = it.moduleName
if (artifactId.startsWith('react-native-')
&& groupId.equals('jitsi-meet')) {
groupId = rootProject.ext.moduleGroupId
}
def dependency = dependencies.appendNode('dependency')
dependency.appendNode('groupId', groupId)
dependency.appendNode('artifactId', artifactId)
dependency.appendNode('version', it.moduleVersion)
}
}
}
}
repositories {
maven { url "file:${rootProject.projectDir}/../../../jitsi/jitsi-maven-repository/releases" }
}
}

25
android/sdk/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,25 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/scorretge/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# 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 *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,29 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="org.jitsi.meet.sdk">
<!-- XXX ACCESS_NETWORK_STATE is required by WebRTC. -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-feature
android:name="android.hardware.camera.autofocus"
android:required="false" />
<application
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true">
<activity
android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>

View File

@@ -0,0 +1,39 @@
/**
* Adapted from
* {@link https://github.com/Aleksandern/react-native-android-settings-library}.
*/
package org.jitsi.meet.sdk;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.provider.Settings;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
class AndroidSettingsModule extends ReactContextBaseJavaModule {
public AndroidSettingsModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return "AndroidSettings";
}
@ReactMethod
public void open() {
Context context = getReactApplicationContext();
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(
Uri.fromParts("package", context.getPackageName(), null));
context.startActivity(intent);
}
}

View File

@@ -0,0 +1,61 @@
package org.jitsi.meet.sdk;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import java.util.HashMap;
import java.util.Map;
class AppInfoModule extends ReactContextBaseJavaModule {
public AppInfoModule(ReactApplicationContext reactContext) {
super(reactContext);
}
/**
* Gets a {@code Map} of constants this module exports to JS. Supports JSON
* types.
*
* @return a {@link Map} of constants this module exports to JS
*/
@Override
public Map<String, Object> getConstants() {
Context context = getReactApplicationContext();
PackageManager packageManager = context.getPackageManager();
ApplicationInfo applicationInfo;
PackageInfo packageInfo;
try {
String packageName = context.getPackageName();
applicationInfo
= packageManager.getApplicationInfo(packageName, 0);
packageInfo = packageManager.getPackageInfo(packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
applicationInfo = null;
packageInfo = null;
}
Map<String, Object> constants = new HashMap<>();
constants.put(
"name",
applicationInfo == null
? ""
: packageManager.getApplicationLabel(applicationInfo));
constants.put(
"version",
packageInfo == null ? "" : packageInfo.versionName);
return constants;
}
@Override
public String getName() {
return "AppInfo";
}
}

View File

@@ -1,4 +1,20 @@
package org.jitsi.meet.audiomode;
/*
* Copyright @ 2017-present 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 android.annotation.TargetApi;
import android.content.BroadcastReceiver;
@@ -24,18 +40,18 @@ import java.util.Map;
* Module implementing a simple API to select the appropriate audio device for a
* conference call.
*
* Audio calls should use <tt>AudioModeModule.AUDIO_CALL</tt>, which uses the
* Audio calls should use {@code AudioModeModule.AUDIO_CALL}, which uses the
* builtin earpiece, wired headset or bluetooth headset. The builtin earpiece is
* the default audio device.
*
* Video calls should should use <tt>AudioModeModule.VIDEO_CALL</tt>, which uses
* Video calls should should use {@code AudioModeModule.VIDEO_CALL}, which uses
* the builtin speaker, earpiece, wired headset or bluetooth headset. The
* builtin speaker is the default audio device.
*
* Before a call has started and after it has ended the
* <tt>AudioModeModule.DEFAULT</tt> mode should be used.
* {@code AudioModeModule.DEFAULT} mode should be used.
*/
public class AudioModeModule extends ReactContextBaseJavaModule {
class AudioModeModule extends ReactContextBaseJavaModule {
/**
* Constants representing the audio mode.
* - DEFAULT: Used before and after every call. It represents the default
@@ -58,12 +74,13 @@ public class AudioModeModule extends ReactContextBaseJavaModule {
: Intent.ACTION_HEADSET_PLUG;
/**
* React Native module name.
* The name of {@code AudioModeModule} to be used in the React Native
* bridge.
*/
private static final String MODULE_NAME = "AudioMode";
/**
* Tag used when logging messages.
* The {@code Log} tag {@code AudioModeModule} is to log messages with.
*/
static final String TAG = MODULE_NAME;
@@ -139,7 +156,7 @@ public class AudioModeModule extends ReactContextBaseJavaModule {
}
/**
* Gets the name for this module, to be used in the React Native bridge.
* Gets the name for this module to be used in the React Native bridge.
*
* @return a string with the module name.
*/
@@ -188,13 +205,24 @@ public class AudioModeModule extends ReactContextBaseJavaModule {
Runnable r = new Runnable() {
@Override
public void run() {
if (updateAudioRoute(mode)) {
boolean success;
try {
success = updateAudioRoute(mode);
} catch (Throwable e) {
success = false;
Log.e(
TAG,
"Failed to update audio route for mode: " + mode,
e);
}
if (success) {
AudioModeModule.this.mode = mode;
promise.resolve(null);
} else {
promise.reject(
"setMode",
"Failed to set the requested audio mode");
"Failed to set audio mode to " + mode);
}
}
};
@@ -263,8 +291,8 @@ public class AudioModeModule extends ReactContextBaseJavaModule {
* Updates the audio route for the given mode.
*
* @param mode the audio mode to be used when computing the audio route.
* @return true if the audio route was updated successfully, false
* otherwise.
* @return {@code true} if the audio route was updated successfully;
* {@code false}, otherwise.
*/
private boolean updateAudioRoute(int mode) {
Log.d(TAG, "Update audio route for mode: " + mode);
@@ -273,7 +301,6 @@ public class AudioModeModule extends ReactContextBaseJavaModule {
audioManager.setMode(AudioManager.MODE_NORMAL);
audioManager.abandonAudioFocus(null);
audioManager.setSpeakerphoneOn(false);
audioManager.setMicrophoneMute(true);
setBluetoothAudioRoute(false);
return true;

View File

@@ -1,7 +1,22 @@
package org.jitsi.meet.audiomode;
/*
* Copyright @ 2017-present 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 android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
@@ -18,7 +33,7 @@ import android.util.Log;
* Bluetooth headsets being connected / disconnected and notifies the module
* about device changes when this occurs.
*/
public class BluetoothHeadsetMonitor {
class BluetoothHeadsetMonitor {
/**
* {@link AudioModeModule} where this monitor reports.
*/
@@ -122,7 +137,8 @@ public class BluetoothHeadsetMonitor {
/**
* Returns the current headset availability.
*
* @return true if there is a Bluetooth headset connected, false otherwise.
* @return {@code true} if there is a Bluetooth headset connected;
* {@code false}, otherwise.
*/
public boolean isHeadsetAvailable() {
return headsetAvailable;

View File

@@ -0,0 +1,65 @@
/*
* Copyright @ 2017-present 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 android.app.Activity;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
/**
* Defines the default behavior of {@code JitsiMeetActivity} and
* {@code JitsiMeetView} upon invoking the back button if no
* {@code JitsiMeetView} handles the invocation. For example, a
* {@code JitsiMeetView} may (1) handle the invocation of the back button
* during a conference by leaving the conference and (2) not handle the
* invocation when not in a conference.
*/
public class DefaultHardwareBackBtnHandlerImpl
implements DefaultHardwareBackBtnHandler {
/**
* The {@code Activity} to which the default handling of the back button
* is being provided by this instance.
*/
private final Activity activity;
/**
* Initializes a new {@code DefaultHardwareBackBtnHandlerImpl} instance to
* provide the default handling of the back button to a specific
* {@code Activity}.
*
* @param activity the {@code Activity} to which the new instance is to
* provide the default behavior of the back button
*/
public DefaultHardwareBackBtnHandlerImpl(Activity activity) {
this.activity = activity;
}
/**
* {@inheritDoc}
*
* Finishes the associated {@code Activity}.
*/
@Override
public void invokeDefaultOnBackPressed() {
// Technically, we'd like to invoke Activity#onBackPressed().
// Practically, it's not possible. Fortunately, the documentation of
// Activity#onBackPressed() specifies that "[t]he default implementation
// simply finishes the current activity,"
activity.finish();
}
}

View File

@@ -0,0 +1,172 @@
/*
* Copyright @ 2017-present 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 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.bridge.ReadableMapKeySetIterator;
import org.jitsi.meet.sdk.JitsiMeetView;
import org.jitsi.meet.sdk.JitsiMeetViewListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Pattern;
/**
* Module implementing a simple API to enable a proximity sensor-controlled
* wake lock. When the lock is held, if the proximity sensor detects a nearby
* object it will dim the screen and disable touch controls. The functionality
* is used with the conference audio-only mode.
*/
class ExternalAPIModule extends ReactContextBaseJavaModule {
/**
* The {@code Method}s of {@code JitsiMeetViewListener} by event name i.e.
* redux action types.
*/
private static final Map<String, Method> JITSI_MEET_VIEW_LISTENER_METHODS
= new HashMap<>();
static {
// Figure out the mapping between the JitsiMeetViewListener methods
// and the events i.e. redux action types.
Pattern onPattern = Pattern.compile("^on[A-Z]+");
Pattern camelcasePattern = Pattern.compile("([a-z0-9]+)([A-Z0-9]+)");
for (Method method : JitsiMeetViewListener.class.getDeclaredMethods()) {
// * The method must be public (because it is declared by an
// interface).
// * The method must be/return void.
if (!Modifier.isPublic(method.getModifiers())
|| !Void.TYPE.equals(method.getReturnType())) {
continue;
}
// * The method name must start with "on" followed by a
// capital/uppercase letter (in agreement with the camelcase
// coding style customary to Java in general and the projects of
// the Jitsi community in particular).
String name = method.getName();
if (!onPattern.matcher(name).find()) {
continue;
}
// * The method must accept/have exactly 1 parameter of a type
// assignable from HashMap.
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length != 1
|| !parameterTypes[0].isAssignableFrom(HashMap.class)) {
continue;
}
// Convert the method name to an event name.
name
= camelcasePattern.matcher(name.substring(2))
.replaceAll("$1_$2")
.toUpperCase(Locale.ROOT);
JITSI_MEET_VIEW_LISTENER_METHODS.put(name, method);
}
}
/**
* Initializes a new module instance. There shall be a single instance of
* this module throughout the lifetime of the application.
*
* @param reactContext the {@link ReactApplicationContext} where this module
* is created.
*/
public ExternalAPIModule(ReactApplicationContext reactContext) {
super(reactContext);
}
/**
* Gets the name of this module to be used in the React Native bridge.
*
* @return The name of this module to be used in the React Native bridge.
*/
@Override
public String getName() {
return "ExternalAPI";
}
/**
* Dispatches an event that occurred on JavaScript to the view's listener.
*
* @param name The name of the event.
* @param data The details/specifics of the event to send determined
* by/associated with the specified {@code name}.
* @param scope
*/
@ReactMethod
public void sendEvent(String name, ReadableMap data, String scope) {
// 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 JitsiMeetView which hosts it.
JitsiMeetView view = JitsiMeetView.findViewByExternalAPIScope(scope);
if (view == null) {
return;
}
JitsiMeetViewListener listener = view.getListener();
if (listener == null) {
return;
}
Method method = JITSI_MEET_VIEW_LISTENER_METHODS.get(name);
if (method != null) {
try {
method.invoke(listener, toHashMap(data));
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
/**
* Initializes a new {@code HashMap} instance with the key-value
* associations of a specific {@code ReadableMap}.
*
* @param readableMap the {@code ReadableMap} specifying the key-value
* associations with which the new {@code HashMap} instance is to be
* initialized.
* @return a new {@code HashMap} instance initialized with the key-value
* associations of the specified {@code readableMap}.
*/
private HashMap<String, Object> toHashMap(ReadableMap readableMap) {
HashMap<String, Object> hashMap = new HashMap<>();
for (ReadableMapKeySetIterator i = readableMap.keySetIterator();
i.hasNextKey();) {
String key = i.nextKey();
hashMap.put(key, readableMap.getString(key));
}
return hashMap;
}
}

View File

@@ -0,0 +1,246 @@
/*
* Copyright @ 2017-present 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 android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import java.net.URL;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
/**
* Base Activity for applications integrating Jitsi Meet at a higher level. It
* contains all the required wiring between the {@code JKConferenceView} and
* the Activity lifecycle methods already implemented.
*
* In this activity we use a single {@code JKConferenceView} instance. This
* instance gives us access to a view which displays the welcome page and the
* conference itself. All lifetime methods associated with this Activity are
* hooked to the React Native subsystem via proxy calls through the
* {@code JKConferenceView} static methods.
*/
public class JitsiMeetActivity
extends AppCompatActivity {
/**
* The request code identifying requests for the permission to draw on top
* of other apps. The value must be 16-bit and is arbitrarily chosen here.
*/
private static final int OVERLAY_PERMISSION_REQUEST_CODE
= (int) (Math.random() * Short.MAX_VALUE);
/**
* The default behavior of this {@code JitsiMeetActivity} upon invoking the
* back button if {@link #view} does not handle the invocation.
*/
private DefaultHardwareBackBtnHandler defaultBackButtonImpl;
/**
* The default base {@code URL} used to join a conference when a partial URL
* (e.g. a room name only) is specified. The value is used only while
* {@link #view} equals {@code null}.
*/
private URL defaultURL;
/**
* Instance of the {@link JitsiMeetView} which this activity will display.
*/
private JitsiMeetView view;
/**
* Whether the Welcome page is enabled. The value is used only while
* {@link #view} equals {@code null}.
*/
private boolean welcomePageEnabled;
private boolean canRequestOverlayPermission() {
return
BuildConfig.DEBUG
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& getApplicationInfo().targetSdkVersion
>= Build.VERSION_CODES.M;
}
/**
*
* @see JitsiMeetView#getDefaultURL()
*/
public URL getDefaultURL() {
return view == null ? defaultURL : view.getDefaultURL();
}
/**
*
* @see JitsiMeetView#getWelcomePageEnabled()
*/
public boolean getWelcomePageEnabled() {
return view == null ? welcomePageEnabled : view.getWelcomePageEnabled();
}
/**
* Initializes the {@link #view} of this {@code JitsiMeetActivity} with a
* new {@link JitsiMeetView} instance.
*/
private void initializeContentView() {
JitsiMeetView view = initializeView();
if (view != null) {
this.view = view;
setContentView(this.view);
}
}
/**
* Initializes a new {@link JitsiMeetView} instance.
*
* @return a new {@code JitsiMeetView} instance.
*/
protected JitsiMeetView initializeView() {
JitsiMeetView view = new JitsiMeetView(this);
// XXX Before calling JitsiMeetView#loadURL, make sure to call whatever
// is documented to need such an order in order to take effect:
view.setDefaultURL(defaultURL);
view.setWelcomePageEnabled(welcomePageEnabled);
view.loadURL(null);
return view;
}
/**
* Loads the given URL and displays the conference. If the specified URL is
* null, the welcome page is displayed instead.
*
* @param url The conference URL.
*/
public void loadURL(@Nullable URL url) {
view.loadURL(url);
}
@Override
protected void onActivityResult(
int requestCode,
int resultCode,
Intent data) {
if (requestCode == OVERLAY_PERMISSION_REQUEST_CODE
&& canRequestOverlayPermission()) {
if (Settings.canDrawOverlays(this)) {
initializeContentView();
}
}
}
@Override
public void onBackPressed() {
if (!JitsiMeetView.onBackPressed()) {
// JitsiMeetView didn't handle the invocation of the back button.
// Generally, an Activity extender would very likely want to invoke
// Activity#onBackPressed(). For the sake of consistency with
// JitsiMeetView and within the Jitsi Meet SDK for Android though,
// JitsiMeetActivity does what JitsiMeetView would've done if it
// were able to handle the invocation.
if (defaultBackButtonImpl == null) {
super.onBackPressed();
} else {
defaultBackButtonImpl.invokeDefaultOnBackPressed();
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// In Debug builds React needs permission to write over other apps in
// order to display the warning and error overlays.
if (canRequestOverlayPermission() && !Settings.canDrawOverlays(this)) {
Intent intent
= new Intent(
Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, OVERLAY_PERMISSION_REQUEST_CODE);
return;
}
initializeContentView();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (view != null) {
view.dispose();
view = null;
}
JitsiMeetView.onHostDestroy(this);
}
@Override
public void onNewIntent(Intent intent) {
JitsiMeetView.onNewIntent(intent);
}
@Override
protected void onPause() {
super.onPause();
JitsiMeetView.onHostPause(this);
defaultBackButtonImpl = null;
}
@Override
protected void onResume() {
super.onResume();
defaultBackButtonImpl = new DefaultHardwareBackBtnHandlerImpl(this);
JitsiMeetView.onHostResume(this, defaultBackButtonImpl);
}
/**
*
* @see JitsiMeetView#setDefaultURL(URL)
*/
public void setDefaultURL(URL defaultURL) {
if (view == null) {
this.defaultURL = defaultURL;
} else {
view.setDefaultURL(defaultURL);
}
}
/**
*
* @see JitsiMeetView#setWelcomePageEnabled(boolean)
*/
public void setWelcomePageEnabled(boolean welcomePageEnabled) {
if (view == null) {
this.welcomePageEnabled = welcomePageEnabled;
} else {
view.setWelcomePageEnabled(welcomePageEnabled);
}
}
}

View File

@@ -0,0 +1,449 @@
/*
* Copyright @ 2017-present 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 android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.widget.FrameLayout;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactRootView;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.common.LifecycleState;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.WeakHashMap;
public class JitsiMeetView extends FrameLayout {
/**
* Background color used by {@code JitsiMeetView} and the React Native root
* view.
*/
private static final int BACKGROUND_COLOR = 0xFF111111;
/**
* React Native bridge. The instance manager allows embedding applications
* to create multiple root views off the same JavaScript bundle.
*/
private static ReactInstanceManager reactInstanceManager;
private static final Set<JitsiMeetView> views
= Collections.newSetFromMap(new WeakHashMap<JitsiMeetView, Boolean>());
private static List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
return Arrays.<NativeModule>asList(
new AndroidSettingsModule(reactContext),
new AppInfoModule(reactContext),
new AudioModeModule(reactContext),
new ExternalAPIModule(reactContext),
new ProximityModule(reactContext)
);
}
public static JitsiMeetView findViewByExternalAPIScope(
String externalAPIScope) {
synchronized (views) {
for (JitsiMeetView view : views) {
if (view.externalAPIScope.equals(externalAPIScope)) {
return view;
}
}
}
return null;
}
/**
* Internal method to initialize the React Native instance manager. We
* create a single instance in order to load the JavaScript bundle a single
* time. All {@code ReactRootView} instances will be tied to the one and
* only {@code ReactInstanceManager}.
*
* @param application {@code Application} instance which is running.
*/
private static void initReactInstanceManager(Application application) {
reactInstanceManager
= ReactInstanceManager.builder()
.setApplication(application)
.setBundleAssetName("index.android.bundle")
.setJSMainModulePath("index.android")
.addPackage(new com.corbt.keepawake.KCKeepAwakePackage())
.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.RNFetchBlob.RNFetchBlobPackage())
.addPackage(new com.rnimmersive.RNImmersivePackage())
.addPackage(new ReactPackageAdapter() {
@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
return JitsiMeetView.createNativeModules(reactContext);
}
})
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
}
/**
* Loads a specific URL {@code String} in all existing
* {@code JitsiMeetView}s.
*
* @param urlString he URL {@code String} to load in all existing
* {@code JitsiMeetView}s.
* @return If the specified {@code urlString} was submitted for loading in
* at least one {@code JitsiMeetView}, then {@code true}; otherwise,
* {@code false}.
*/
private static boolean loadURLStringInViews(String urlString) {
synchronized (views) {
if (!views.isEmpty()) {
for (JitsiMeetView view : views) {
view.loadURLString(urlString);
}
return true;
}
}
return false;
}
/**
* Activity lifecycle method which should be called from
* {@code Activity.onBackPressed} so we can do the required internal
* processing.
*
* @return {@code true} if the back-press was processed; {@code false},
* otherwise. If {@code false}, the application should call the parent's
* implementation.
*/
public static boolean onBackPressed() {
if (reactInstanceManager == null) {
return false;
} else {
reactInstanceManager.onBackPressed();
return true;
}
}
/**
* Activity lifecycle method which should be called from
* {@code Activity.onDestroy} so we can do the required internal
* processing.
*
* @param activity {@code Activity} being destroyed.
*/
public static void onHostDestroy(Activity activity) {
if (reactInstanceManager != null) {
reactInstanceManager.onHostDestroy(activity);
}
}
/**
* Activity lifecycle method which should be called from
* {@code Activity.onPause} so we can do the required internal processing.
*
* @param activity {@code Activity} being paused.
*/
public static void onHostPause(Activity activity) {
if (reactInstanceManager != null) {
reactInstanceManager.onHostPause(activity);
}
}
/**
* Activity lifecycle method which should be called from
* {@code Activity.onResume} so we can do the required internal processing.
*
* @param activity {@code Activity} being resumed.
*/
public static void onHostResume(Activity activity) {
onHostResume(activity, new DefaultHardwareBackBtnHandlerImpl(activity));
}
/**
* Activity lifecycle method which should be called from
* {@code Activity.onResume} so we can do the required internal processing.
*
* @param activity {@code Activity} being resumed.
* @param defaultBackButtonImpl a {@code DefaultHardwareBackBtnHandler} to
* handle invoking the back button if no {@code JitsiMeetView} handles it.
*/
public static void onHostResume(
Activity activity,
DefaultHardwareBackBtnHandler defaultBackButtonImpl) {
if (reactInstanceManager != null) {
reactInstanceManager.onHostResume(activity, defaultBackButtonImpl);
}
}
/**
* Activity lifecycle method which should be called from
* {@code Activity.onNewIntent} so we can do the required internal
* processing. Note that this is only needed if the activity's "launchMode"
* was set to "singleTask". This is required for deep linking to work once
* the application is already running.
*
* @param intent {@code Intent} instance which was received.
*/
public static void onNewIntent(Intent intent) {
// XXX At least twice we received bug reports about malfunctioning
// loadURL in the Jitsi Meet SDK while the Jitsi Meet app seemed to
// functioning as expected in our testing. But that was to be expected
// because the app does not exercise loadURL. In order to increase the
// test coverage of loadURL, channel deep linking through loadURL.
Uri uri;
if (Intent.ACTION_VIEW.equals(intent.getAction())
&& (uri = intent.getData()) != null
&& loadURLStringInViews(uri.toString())) {
return;
}
if (reactInstanceManager != null) {
reactInstanceManager.onNewIntent(intent);
}
}
/**
* The default base {@code URL} used to join a conference when a partial URL
* (e.g. a room name only) is specified to {@link #loadURLString(String)} or
* {@link #loadURLObject(Bundle)}.
*/
private URL defaultURL;
/**
* The unique identifier of this {@code JitsiMeetView} within the process
* for the purposes of {@link ExternalAPI}. The name scope was inspired by
* postis which we use on Web for the similar purposes of the iframe-based
* external API.
*/
private final String externalAPIScope;
/**
* {@link JitsiMeetViewListener} instance for reporting events occurring in
* Jitsi Meet.
*/
private JitsiMeetViewListener listener;
/**
* React Native root view.
*/
private ReactRootView reactRootView;
/**
* Whether the Welcome page is enabled.
*/
private boolean welcomePageEnabled;
public JitsiMeetView(@NonNull Context context) {
super(context);
setBackgroundColor(BACKGROUND_COLOR);
if (reactInstanceManager == null) {
initReactInstanceManager(((Activity) context).getApplication());
}
// Hook this JitsiMeetView into ExternalAPI.
externalAPIScope = UUID.randomUUID().toString();
synchronized (views) {
views.add(this);
}
}
/**
* Releases the React resources (specifically the {@link ReactRootView})
* associated with this view.
*
* This method MUST be called when the Activity holding this view is
* destroyed, typically in the {@code onDestroy} method.
*/
public void dispose() {
if (reactRootView != null) {
removeView(reactRootView);
reactRootView.unmountReactApplication();
reactRootView = null;
}
}
/**
* Gets the default base {@code URL} used to join a conference when a
* partial URL (e.g. a room name only) is specified to
* {@link #loadURLString(String)} or {@link #loadURLObject(Bundle)}. If not
* set or if set to {@code null}, the default built in JavaScript is used:
* {@link https://meet.jit.si}
*
* @return The default base {@code URL} or {@code null}.
*/
public URL getDefaultURL() {
return defaultURL;
}
/**
* Gets the {@link JitsiMeetViewListener} set on this {@code JitsiMeetView}.
*
* @return The {@code JitsiMeetViewListener} set on this
* {@code JitsiMeetView}.
*/
public JitsiMeetViewListener getListener() {
return listener;
}
/**
* Gets whether the Welcome page is enabled. If {@code true}, the Welcome
* page is rendered when this {@code JitsiMeetView} is not at a URL
* identifying a Jitsi Meet conference/room.
*
* @return {@code true} if the Welcome page is enabled; otherwise,
* {@code false}.
*/
public boolean getWelcomePageEnabled() {
return welcomePageEnabled;
}
/**
* Loads a specific {@link URL} which may identify a conference to join. If
* the specified {@code URL} is {@code null} and the Welcome page is
* enabled, the Welcome page is displayed instead.
*
* @param url The {@code URL} to load which may identify a conference to
* join.
*/
public void loadURL(@Nullable URL url) {
loadURLString(url == null ? null : url.toString());
}
/**
* Loads a specific URL which may identify a conference to join. The URL is
* specified in the form of a {@link Bundle} of properties which (1)
* internally are sufficient to construct a URL {@code String} while (2)
* abstracting the specifics of constructing the URL away from API
* clients/consumers. If the specified URL is {@code null} and the Welcome
* page is enabled, the Welcome page is displayed instead.
*
* @param urlObject The URL to load which may identify a conference to join.
*/
public void loadURLObject(@Nullable Bundle urlObject) {
Bundle props = new Bundle();
// defaultURL
if (defaultURL != null) {
props.putString("defaultURL", defaultURL.toString());
}
// externalAPIScope
props.putString("externalAPIScope", externalAPIScope);
// url
if (urlObject != null) {
props.putBundle("url", urlObject);
}
// welcomePageEnabled
props.putBoolean("welcomePageEnabled", welcomePageEnabled);
// XXX The method loadURLObject: is supposed to be imperative i.e.
// a second invocation with one and the same URL is expected to join
// the respective conference again if the first invocation was followed
// by leaving the conference. However, React and, respectively,
// appProperties/initialProperties are declarative expressions i.e. one
// and the same URL will not trigger componentWillReceiveProps in the
// JavaScript source code. The workaround implemented bellow introduces
// imperativeness in React Component props by defining a unique value
// per loadURLObject: invocation.
props.putLong("timestamp", System.currentTimeMillis());
if (reactRootView == null) {
reactRootView = new ReactRootView(getContext());
reactRootView.startReactApplication(
reactInstanceManager, "App", props);
reactRootView.setBackgroundColor(BACKGROUND_COLOR);
addView(reactRootView);
} else {
reactRootView.setAppProperties(props);
}
}
/**
* Loads a specific URL {@link String} which may identify a conference to
* join. If the specified URL {@code String} is {@code null} and the Welcome
* page is enabled, the Welcome page is displayed instead.
*
* @param urlString The URL {@code String} to load which may identify a
* conference to join.
*/
public void loadURLString(@Nullable String urlString) {
Bundle urlObject;
if (urlString == null) {
urlObject = null;
} else {
urlObject = new Bundle();
urlObject.putString("url", urlString);
}
loadURLObject(urlObject);
}
/**
* Sets the default base {@code URL} used to join a conference when a
* partial URL (e.g. a room name only) is specified to
* {@link #loadURLString(String)} or {@link #loadURLObject(Bundle)}. Must be
* called before {@link #loadURL(URL)} for it to take effect.
*
* @param defaultURL The {@code URL} to be set as the default base URL.
* @see #getDefaultURL()
*/
public void setDefaultURL(URL defaultURL) {
this.defaultURL = defaultURL;
}
/**
* Sets a specific {@link JitsiMeetViewListener} on this
* {@code JitsiMeetView}.
*
* @param listener The {@code JitsiMeetViewListener} to set on this
* {@code JitsiMeetView}.
*/
public void setListener(JitsiMeetViewListener listener) {
this.listener = listener;
}
/**
* Sets whether the Welcome page is enabled. Must be called before
* {@link #loadURL(URL)} for it to take effect.
*
* @param welcomePageEnabled {@code true} to enable the Welcome page;
* otherwise, {@code false}.
*/
public void setWelcomePageEnabled(boolean welcomePageEnabled) {
this.welcomePageEnabled = welcomePageEnabled;
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright @ 2017-present 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 java.util.Map;
/**
* Implements {@link JitsiMeetViewListener} so apps don't have to add stubs for
* all methods in the interface if they are only interested in some.
*/
public abstract class JitsiMeetViewAdapter implements JitsiMeetViewListener {
@Override
public void onConferenceFailed(Map<String, Object> data) {
}
@Override
public void onConferenceJoined(Map<String, Object> data) {
}
@Override
public void onConferenceLeft(Map<String, Object> data) {
}
@Override
public void onConferenceWillJoin(Map<String, Object> data) {
}
@Override
public void onConferenceWillLeave(Map<String, Object> data) {
}
@Override
public void onLoadConfigError(Map<String, Object> data) {
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright @ 2017-present 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 java.util.Map;
/**
* Interface for listening to events coming from Jitsi Meet.
*/
public interface JitsiMeetViewListener {
/**
* Called when joining a conference fails or an ongoing conference is
* interrupted due to a failure.
*
* @param data Map with an "error" key describing the problem, and a "url"
* key with the conference URL.
*/
void onConferenceFailed(Map<String, Object> data);
/**
* Called when a conference was joined.
*
* @param data Map with a "url" key with the conference URL.
*/
void onConferenceJoined(Map<String, Object> data);
/**
* Called when the conference was left, typically after hanging up.
*
* @param data Map with a "url" key with the conference URL.
*/
void onConferenceLeft(Map<String, Object> data);
/**
* Called before the conference is joined.
*
* @param data Map with a "url" key with the conference URL.
*/
void onConferenceWillJoin(Map<String, Object> data);
/**
* Called before the conference is left.
*
* @param data Map with a "url" key with the conference URL.
*/
void onConferenceWillLeave(Map<String, Object> data);
/**
* Called when loading the main configuration file from the Jitsi Meet
* deployment fails.
*
* @param data Map with an "error" key with the error and a "url" key with
* the conference URL which necessitated the loading of the configuration
* file.
*/
void onLoadConfigError(Map<String, Object> data);
}

View File

@@ -1,4 +1,20 @@
package org.jitsi.meet.proximity;
/*
* Copyright @ 2017-present 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 android.content.Context;
import android.os.PowerManager;
@@ -15,9 +31,10 @@ import com.facebook.react.bridge.UiThreadUtil;
* object it will dim the screen and disable touch controls. The functionality
* is used with the conference audio-only mode.
*/
public class ProximityModule extends ReactContextBaseJavaModule {
class ProximityModule extends ReactContextBaseJavaModule {
/**
* React Native module name.
* The name of {@code ProximityModule} to be used in the React Native
* bridge.
*/
private static final String MODULE_NAME = "Proximity";

View File

@@ -0,0 +1,40 @@
/*
* Copyright @ 2017-present 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 com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.Collections;
import java.util.List;
public class ReactPackageAdapter implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(
ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">Jitsi Meet SDK</string>
</resources>

View File

@@ -1,8 +1,10 @@
rootProject.name = 'jitsi-meet-react'
rootProject.name = 'jitsi-meet'
include ':app'
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-fetch-blob'
project(':react-native-fetch-blob').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fetch-blob/android')
include ':react-native-immersive'
project(':react-native-immersive').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-immersive/android')
include ':react-native-keep-awake'

79
app.js
View File

@@ -1,66 +1,55 @@
/* application specific logic */
import "jquery";
import "jquery-contextmenu";
import "jquery-ui";
import "strophe";
import "strophe-disco";
import "jQuery-Impromptu";
import "autosize";
// FIXME: remove once atlaskit work with React 16
// It seems that @atlaskit/icon is importing PropTypes from React, but it
// happens through some glyph coffee script template. It could be that more
// things are broken there (not only the icon).
import './react/features/base/react/prop-types-polyfill.js';
import 'jquery';
import 'jquery-contextmenu';
import 'jquery-ui';
import 'jQuery-Impromptu';
import 'autosize';
import 'aui';
import 'aui-experimental';
import 'aui-css';
import 'aui-experimental-css';
window.toastr = require("toastr");
import UI from "./modules/UI/UI";
import settings from "./modules/settings/Settings";
import conference from './conference';
import API from './modules/API/API';
import API from './modules/API';
import keyboardshortcut from './modules/keyboardshortcut/keyboardshortcut';
import remoteControl from './modules/remotecontrol/RemoteControl';
import settings from './modules/settings/Settings';
import translation from './modules/translation/translation';
import UI from './modules/UI/UI';
import translation from "./modules/translation/translation";
import remoteControl from "./modules/remotecontrol/RemoteControl";
window.APP = {
API,
conference,
const APP = {
// Used by do_external_connect.js if we receive the attach data after
// connect was already executed. status property can be "initialized",
// "ready" or "connecting". We are interested in "ready" status only which
// connect was already executed. status property can be 'initialized',
// 'ready', or 'connecting'. We are interested in 'ready' status only which
// means that connect was executed but we have to wait for the attach data.
// In status "ready" handler property will be set to a function that will
// In status 'ready' handler property will be set to a function that will
// finish the connect process when the attach data or error is received.
connect: {
status: "initialized",
handler: null
handler: null,
status: 'initialized'
},
// Used for automated performance tests
// Used for automated performance tests.
connectionTimes: {
"index.loaded": window.indexLoadedTime
'index.loaded': window.indexLoadedTime
},
UI,
keyboardshortcut,
remoteControl,
settings,
conference,
translation,
/**
* The log collector which captures JS console logs for this app.
* @type {LogCollector}
*/
logCollector: null,
/**
* Indicates if the log collector has been started (it will not be started
* if the welcome page is displayed).
*/
logCollectorStarted : false,
/**
* After the APP has been initialized provides utility methods for dealing
* with the conference room URL(address).
* @type ConferenceUrl
*/
ConferenceUrl : null,
connection: null,
API,
remoteControl
UI
};
// TODO The execution of the mobile app starts from react/index.native.js.
@@ -69,6 +58,4 @@ const APP = {
// because we are at the beginning of introducing React into the Web app, allow
// the execution of the Web app to start from app.js in order to reduce the
// complexity of the beginning step.
require('./react');
module.exports = APP;
import './react';

File diff suppressed because it is too large Load Diff

347
config.js
View File

@@ -1,99 +1,316 @@
/* jshint maxlen:false */
/* eslint-disable no-unused-vars, no-var */
var config = {
// Configuration
//
// Alternative location for the configuration.
// configLocation: './config.json',
// Custom function which given the URL path should return a room name.
// getroomnode: function (path) { return 'someprefixpossiblybasedonpath'; },
// Connection
//
var config = { // eslint-disable-line no-unused-vars
// configLocation: './config.json', // see ./modules/HttpConfigFetch.js
hosts: {
// XMPP domain.
domain: 'jitsi-meet.example.com',
//anonymousdomain: 'guest.example.com',
//authdomain: 'jitsi-meet.example.com', // defaults to <domain>
muc: 'conference.jitsi-meet.example.com', // FIXME: use XEP-0030
//jirecon: 'jirecon.jitsi-meet.example.com',
//call_control: 'callcontrol.jitsi-meet.example.com',
//focus: 'focus.jitsi-meet.example.com', // defaults to 'focus.jitsi-meet.example.com'
},
// getroomnode: function (path) { return 'someprefixpossiblybasedonpath'; },
// useStunTurn: true, // use XEP-0215 to fetch STUN and TURN server
// useIPv6: true, // ipv6 support. use at your own risk
useNicks: false,
bosh: '//jitsi-meet.example.com/http-bind', // FIXME: use xep-0156 for that
clientNode: 'http://jitsi.org/jitsimeet', // The name of client node advertised in XEP-0115 'c' stanza
//focusUserJid: 'focus@auth.jitsi-meet.example.com', // The real JID of focus participant - can be overridden here
//defaultSipNumber: '', // Default SIP number
// The STUN servers that will be used in the peer to peer connections
p2pStunServers: [
{ urls: "stun:stun.l.google.com:19302" },
{ urls: "stun:stun1.l.google.com:19302" },
{ urls: "stun:stun2.l.google.com:19302" }
],
// XMPP MUC domain. FIXME: use XEP-0030 to discover it.
muc: 'conference.jitsi-meet.example.com'
// When using authentication, domain for guest users.
// anonymousdomain: 'guest.example.com',
// Domain for authenticated users. Defaults to <domain>.
// authdomain: 'jitsi-meet.example.com',
// Jirecon recording component domain.
// jirecon: 'jirecon.jitsi-meet.example.com',
// Call control component (Jigasi).
// call_control: 'callcontrol.jitsi-meet.example.com',
// Focus component domain. Defaults to focus.<domain>.
// focus: 'focus.jitsi-meet.example.com',
},
// BOSH URL. FIXME: use XEP-0156 to discover it.
bosh: '//jitsi-meet.example.com/http-bind',
// The name of client node advertised in XEP-0115 'c' stanza
clientNode: 'http://jitsi.org/jitsimeet',
// The real JID of focus participant - can be overridden here
// focusUserJid: 'focus@auth.jitsi-meet.example.com',
// Testing / experimental features.
//
testing: {
// Enables experimental simulcast support on Firefox.
enableFirefoxSimulcast: false,
// P2P test mode disables automatic switching to P2P when there are 2
// participants in the conference.
p2pTestMode: false
},
// Disables ICE/UDP by filtering out local and remote UDP candidates in
// signalling.
// webrtcIceUdpDisable: false,
// Disables ICE/TCP by filtering out local and remote TCP candidates in
// signalling.
// webrtcIceTcpDisable: false,
// Media
//
// Audio
// Disable measuring of audio levels.
// disableAudioLevels: false,
// Start the conference in audio only mode (no video is being received nor
// sent).
// startAudioOnly: false,
// Every participant after the Nth will start audio muted.
// startAudioMuted: 10,
// Start calls with audio muted. Unlike the option above, this one is only
// applied locally. FIXME: having these 2 options is confusing.
// startWithAudioMuted: false,
// Video
// Sets the preferred resolution (height) for local video. Defaults to 720.
// resolution: 720,
// w3c spec-compliant video constraints to use for video capture. Currently
// used by browsers that return true from lib-jitsi-meet's
// RTCBrowserType#usesNewGumFlow. The constraints are independency from
// this config's resolution value. Defaults to requesting an ideal aspect
// ratio of 16:9 with an ideal resolution of 1080p.
// constraints: {
// video: {
// aspectRatio: 16 / 9,
// height: {
// ideal: 1080,
// max: 1080,
// min: 240
// }
// }
// },
// Enable / disable simulcast support.
// disableSimulcast: 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,
// Start calls with video muted. Unlike the option above, this one is only
// applied locally. FIXME: having these 2 options is confusing.
// startWithVideoMuted: false,
// If set to true, prefer to use the H.264 video codec (if supported).
// Note that it's not recommended to do this because simulcast is not
// supported when using H.264. For 1-to-1 calls this setting is enabled by
// default and can be toggled in the p2p section.
// preferH264: true,
// If set to true, disable H.264 video codec by stripping it out of the
// SDP.
// disableH264: false,
// Desktop sharing
// Enable / disable desktop sharing
// disableDesktopSharing: false,
// The ID of the jidesha extension for Chrome.
desktopSharingChromeExtId: null,
// Whether desktop sharing should be disabled on Chrome.
desktopSharingChromeDisabled: true,
// The media sources to use when using screen sharing with the Chrome
// extension.
desktopSharingChromeSources: ['screen', 'window', 'tab'],
desktopSharingChromeSources: [ 'screen', 'window', 'tab' ],
// Required version of Chrome extension
desktopSharingChromeMinExtVersion: '0.1',
// The ID of the jidesha extension for Firefox. If null, we assume that no
// extension is required.
desktopSharingFirefoxExtId: null,
// Whether desktop sharing should be disabled on Firefox.
desktopSharingFirefoxDisabled: true,
desktopSharingFirefoxDisabled: false,
// The maximum version of Firefox which requires a jidesha extension.
// Example: if set to 41, we will require the extension for Firefox versions
// up to and including 41. On Firefox 42 and higher, we will run without the
// extension.
// If set to -1, an extension will be required for all versions of Firefox.
desktopSharingFirefoxMaxVersionExtRequired: 51,
// The URL to the Firefox extension for desktop sharing.
desktopSharingFirefoxExtensionURL: null,
// Disables ICE/UDP by filtering out local and remote UDP candidates in signalling.
webrtcIceUdpDisable: false,
// Disables ICE/TCP by filtering out local and remote TCP candidates in signalling.
webrtcIceTcpDisable: false,
// Try to start calls with screen-sharing instead of camera video.
// startScreenSharing: false,
openSctp: true, // Toggle to enable/disable SCTP channels
disableStats: false,
disableAudioLevels: false,
channelLastN: -1, // The default value of the channel attribute last-n.
enableRecording: false,
// Recording
// Whether to enable recording or not.
// enableRecording: false,
// Type for recording: one of jibri or jirecon.
// recordingType: 'jibri',
// Misc
// Default value for the channel "last N" attribute. -1 for unlimited.
channelLastN: -1,
// Disables or enables RTX (RFC 4588) (defaults to false).
// disableRtx: false,
// Use XEP-0215 to fetch STUN and TURN servers.
// useStunTurn: true,
// Enable IPv6 support.
// useIPv6: true,
// Enables / disables a data communication channel with the Videobridge.
// Values can be 'datachannel', 'websocket', true (treat it as
// 'datachannel'), undefined (treat it as 'datachannel') and false (don't
// open any channel).
// openBridgeChannel: true,
// UI
//
// Use display name as XMPP nickname.
// useNicks: false,
// Require users to always specify a display name.
// requireDisplayName: true,
// Whether to use a welcome page or not. In case it's false a random room
// will be joined when no room is specified.
enableWelcomePage: true,
//enableClosePage: false, // enabling the close page will ignore the welcome
// page redirection when call is hangup
disableSimulcast: false,
// requireDisplayName: true, // Forces the participants that doesn't have display name to enter it when they enter the room.
// startAudioMuted: 10, // every participant after the Nth will start audio muted
// startVideoMuted: 10, // every participant after the Nth will start video muted
// defaultLanguage: "en",
// To enable sending statistics to callstats.io you should provide Applicaiton ID and Secret.
// callStatsID: "", // Application ID for callstats.io API
// callStatsSecret: "", // Secret for callstats.io API
/*noticeMessage: 'Service update is scheduled for 16th March 2015. ' +
'During that time service will not be available. ' +
'Apologise for inconvenience.',*/
disableThirdPartyRequests: false,
// Enabling the close page will ignore the welcome page redirection when
// a call is hangup.
// enableClosePage: false,
// Disable hiding of remote thumbnails when in a 1-on-1 conference call.
// disable1On1Mode: false,
// The minumum value a video's height (or width, whichever is smaller) needs
// The minimum value a video's height (or width, whichever is smaller) needs
// to be in order to be considered high-definition.
minHDHeight: 540,
// If true - all users without token will be considered guests and all users
// Default language for the user interface.
// defaultLanguage: 'en',
// If true all users without a token will be considered guests and all users
// with token will be considered non-guests. Only guests will be allowed to
// edit their profile.
enableUserRolesBasedOnToken: false,
// Suspending video might cause problems with audio playback. Disabling until these are fixed.
disableSuspendVideo: true,
// disables or enables RTX (RFC 4588) (defaults to false).
disableRtx: false,
// Sets the preferred resolution (height) for local video. Defaults to 360.
resolution: 720,
// Enables peer to peer mode. When enabled system will try to establish
// direct connection given that there are exactly 2 participants in
// the room. If that succeeds the conference will stop sending data through
// the JVB and use the peer to peer connection instead. When 3rd participant
// joins the conference will be moved back to the JVB connection.
//enableP2P: true
// How long we're going to wait, before going back to P2P after
// the 3rd participant has left the conference (to filter out page reload)
//backToP2PDelay: 5
// Message to show the users. Example: 'The service will be down for
// maintenance at 01:00 AM GMT,
// noticeMessage: '',
// Stats
//
// Whether to enable stats collection or not.
// disableStats: false,
// To enable sending statistics to callstats.io you must provide the
// Application ID and Secret.
// callStatsID: '',
// callStatsSecret: '',
// enables callstatsUsername to be reported as statsId and used
// by callstats as repoted remote id
// enableStatsID: false
// enables sending participants display name to callstats
// enableDisplayNameInStats: false
// Privacy
//
// If third party requests are disabled, no other server will be contacted.
// This means avatars will be locally generated and callstats integration
// will not function.
// disableThirdPartyRequests: false,
// Peer-To-Peer mode: used (if enabled) when there are just 2 participants.
//
p2p: {
// Enables peer to peer mode. When enabled the system will try to
// establish a direct connection when there are exactly 2 participants
// in the room. If that succeeds the conference will stop sending data
// through the JVB and use the peer to peer connection instead. When a
// 3rd participant joins the conference will be moved back to the JVB
// connection.
enabled: true,
// Use XEP-0215 to fetch STUN and TURN servers.
// useStunTurn: true,
// The STUN servers that will be used in the peer to peer connections
stunServers: [
{ urls: 'stun:stun.l.google.com:19302' },
{ urls: 'stun:stun1.l.google.com:19302' },
{ urls: 'stun:stun2.l.google.com:19302' }
],
// If set to true, it will prefer to use H.264 for P2P calls (if H.264
// is supported).
preferH264: true
// If set to true, disable H.264 video codec by stripping it out of the
// SDP.
// disableH264: false,
// How long we're going to wait, before going back to P2P after the 3rd
// participant has left the conference (to filter out page reload).
// backToP2PDelay: 5
},
// Information about the jitsi-meet instance we are connecting to, including
// the user region as seen by the server.
//
deploymentInfo: {
// shard: "shard1",
// region: "europe",
// userRegion: "asia"
}
};
/* eslint-enable no-unused-vars, no-var */

View File

@@ -1,5 +1,4 @@
/* global APP, JitsiMeetJS, config */
const logger = require("jitsi-meet-logger").getLogger(__filename);
import AuthHandler from './modules/UI/authentication/AuthHandler';
import jitsiLocalStorage from './modules/util/JitsiLocalStorage';
@@ -9,11 +8,12 @@ import {
connectionFailed
} from './react/features/base/connection';
import {
isFatalJitsiConnectionError
isFatalJitsiConnectionError,
JitsiConnectionErrors,
JitsiConnectionEvents
} from './react/features/base/lib-jitsi-meet';
const ConnectionEvents = JitsiMeetJS.events.connection;
const ConnectionErrors = JitsiMeetJS.errors.connection;
const logger = require('jitsi-meet-logger').getLogger(__filename);
/**
* Checks if we have data to use attach instead of connect. If we have the data
@@ -27,28 +27,39 @@ const ConnectionErrors = JitsiMeetJS.errors.connection;
* @param {string} [roomName] the name of the conference.
*/
function checkForAttachParametersAndConnect(id, password, connection) {
if(window.XMPPAttachInfo){
APP.connect.status = "connecting";
if (window.XMPPAttachInfo) {
APP.connect.status = 'connecting';
// When connection optimization is not deployed or enabled the default
// value will be window.XMPPAttachInfo.status = "error"
// If the connection optimization is deployed and enabled and there is
// a failure the value will be window.XMPPAttachInfo.status = "error"
if(window.XMPPAttachInfo.status === "error") {
connection.connect({id, password});
if (window.XMPPAttachInfo.status === 'error') {
connection.connect({
id,
password
});
return;
}
var attachOptions = window.XMPPAttachInfo.data;
if(attachOptions) {
const attachOptions = window.XMPPAttachInfo.data;
if (attachOptions) {
connection.attach(attachOptions);
delete window.XMPPAttachInfo.data;
} else {
connection.connect({id, password});
connection.connect({
id,
password
});
}
} else {
APP.connect.status = "ready";
APP.connect.handler = checkForAttachParametersAndConnect.bind(null,
id, password, connection);
APP.connect.status = 'ready';
APP.connect.handler
= checkForAttachParametersAndConnect.bind(
null,
id, password, connection);
}
}
@@ -61,53 +72,69 @@ function checkForAttachParametersAndConnect(id, password, connection) {
* everything is ok, else error.
*/
function connect(id, password, roomName) {
const connectionConfig = Object.assign({}, config);
const { issuer, jwt } = APP.store.getState()['features/base/jwt'];
let connectionConfig = Object.assign({}, config);
connectionConfig.bosh += `?room=${roomName}`;
connectionConfig.bosh += '?room=' + roomName;
let connection
= new JitsiMeetJS.JitsiConnection(null, config.token, connectionConfig);
const connection
= new JitsiMeetJS.JitsiConnection(
null,
jwt && issuer && issuer !== 'anonymous' ? jwt : undefined,
connectionConfig);
return new Promise(function (resolve, reject) {
return new Promise((resolve, reject) => {
connection.addEventListener(
ConnectionEvents.CONNECTION_ESTABLISHED, handleConnectionEstablished
);
JitsiConnectionEvents.CONNECTION_ESTABLISHED,
handleConnectionEstablished);
connection.addEventListener(
ConnectionEvents.CONNECTION_FAILED, handleConnectionFailed
);
JitsiConnectionEvents.CONNECTION_FAILED,
handleConnectionFailed);
connection.addEventListener(
ConnectionEvents.CONNECTION_FAILED, connectionFailedHandler);
JitsiConnectionEvents.CONNECTION_FAILED,
connectionFailedHandler);
function connectionFailedHandler(error, errMsg) {
APP.store.dispatch(connectionFailed(connection, error, errMsg));
/**
*
*/
function connectionFailedHandler(error, message, credentials) {
APP.store.dispatch(
connectionFailed(connection, error, message, credentials));
if (isFatalJitsiConnectionError(error)) {
connection.removeEventListener(
ConnectionEvents.CONNECTION_FAILED,
JitsiConnectionEvents.CONNECTION_FAILED,
connectionFailedHandler);
}
}
/**
*
*/
function unsubscribe() {
connection.removeEventListener(
ConnectionEvents.CONNECTION_ESTABLISHED,
handleConnectionEstablished
);
JitsiConnectionEvents.CONNECTION_ESTABLISHED,
handleConnectionEstablished);
connection.removeEventListener(
ConnectionEvents.CONNECTION_FAILED,
handleConnectionFailed
);
JitsiConnectionEvents.CONNECTION_FAILED,
handleConnectionFailed);
}
/**
*
*/
function handleConnectionEstablished() {
APP.store.dispatch(connectionEstablished(connection));
unsubscribe();
resolve(connection);
}
/**
*
*/
function handleConnectionFailed(err) {
unsubscribe();
logger.error("CONNECTION FAILED:", err);
logger.error('CONNECTION FAILED:', err);
reject(err);
}
@@ -128,35 +155,29 @@ function connect(id, password, roomName) {
*
* @returns {Promise<JitsiConnection>}
*/
export function openConnection({id, password, retry, roomName}) {
let usernameOverride
= jitsiLocalStorage.getItem("xmpp_username_override");
let passwordOverride
= jitsiLocalStorage.getItem("xmpp_password_override");
export function openConnection({ id, password, retry, roomName }) {
const usernameOverride
= jitsiLocalStorage.getItem('xmpp_username_override');
const passwordOverride
= jitsiLocalStorage.getItem('xmpp_password_override');
if (usernameOverride && usernameOverride.length > 0) {
id = usernameOverride;
id = usernameOverride; // eslint-disable-line no-param-reassign
}
if (passwordOverride && passwordOverride.length > 0) {
password = passwordOverride;
password = passwordOverride; // eslint-disable-line no-param-reassign
}
return connect(id, password, roomName).catch(function (err) {
if (!retry) {
throw err;
}
return connect(id, password, roomName).catch(err => {
if (retry) {
const { issuer, jwt } = APP.store.getState()['features/base/jwt'];
if (err === ConnectionErrors.PASSWORD_REQUIRED) {
// do not retry if token is not valid
if (config.token) {
throw err;
} else {
if (err === JitsiConnectionErrors.PASSWORD_REQUIRED
&& (!jwt || issuer === 'anonymous')) {
return AuthHandler.requestAuth(roomName, connect);
}
} else {
throw err;
}
throw err;
});
}

View File

@@ -1,37 +1,32 @@
/* global config,
createConnectionExternally,
getConfigParamsFromUrl,
getRoomName */
/* global config, createConnectionExternally */
import getRoomName from '../react/features/base/config/getRoomName';
import parseURLParams from '../react/features/base/config/parseURLParams';
/**
* Implements external connect using createConnectionExternally function defined
* in external_connect.js for Jitsi Meet. Parses the room name and token from
* the URL and executes createConnectionExternally.
* in external_connect.js for Jitsi Meet. Parses the room name and JSON Web
* Token (JWT) from the URL and executes createConnectionExternally.
*
* NOTE: If you are using lib-jitsi-meet without Jitsi Meet you should use this
* NOTE: If you are using lib-jitsi-meet without Jitsi Meet, you should use this
* file as reference only because the implementation is Jitsi Meet-specific.
*
* NOTE: For optimal results this file should be included right after
* external_connect.js.
*/
const hashParams = getConfigParamsFromUrl('hash', true);
const searchParams = getConfigParamsFromUrl('search', true);
if (typeof createConnectionExternally === 'function') {
// URL params have higher proirity than config params.
let url
= parseURLParams(window.location, true, 'hash')[
'config.externalConnectUrl']
|| config.externalConnectUrl;
let roomName;
// URL params have higher proirity than config params.
let url
= hashParams.hasOwnProperty('config.externalConnectUrl')
? hashParams['config.externalConnectUrl']
: config.externalConnectUrl;
if (url && window.createConnectionExternally) {
const roomName = getRoomName();
if (roomName) {
if (url && (roomName = getRoomName())) {
url += `?room=${roomName}`;
const token
= hashParams['config.token'] || config.token || searchParams.jwt;
const token = parseURLParams(window.location, true, 'search').jwt;
if (token) {
url += `&token=${token}`;

View File

@@ -1,4 +1,9 @@
* {
/**
* Safari will limit input in input elements to one character when user-select
* none is applied. Other browsers already support selecting within inputs while
* user-select is none. As such, disallow user-select except on inputs.
*/
*:not(input) {
-webkit-user-select: none;
user-select: none;
}
@@ -36,16 +41,11 @@ body, input, textarea, keygen, select, button {
button, input, select, textarea {
margin: 0;
vertical-align: baseline;
color: $inputColor;
font-size: 1em;
}
button, select, input[type="button"],
input[type="reset"], input[type="submit"] {
height: 32px;
line-height: 32px;
padding-left: 4px;
padding-right: 4px;
cursor: pointer;
}
@@ -80,8 +80,8 @@ form {
display: block;
position: absolute;
top: 15;
width: 186px;
height: 74px;
width: $watermarkWidth;
height: $watermarkHeight;
background-size: contain;
background-repeat: no-repeat;
z-index: $zindex2;
@@ -119,21 +119,6 @@ form {
font-size: 12px;
}
/**
* Tooltips
**/
.tipsy {
z-index: $tooltipsZ;
&-inner {
background-color: $tooltipBg;
max-width: 350px;
}
&-arrow {
border-color: $tooltipBg;
}
}
/**
* Dialogs fade
*/
@@ -145,3 +130,28 @@ form {
-webkit-user-select: text;
user-select: text;
}
/**
* Re-style default OS scrollbar.
*/
::-webkit-scrollbar {
background: transparent;
width: 7px;
}
::-webkit-scrollbar-button {
display: none;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-track-piece {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, .5);
border-radius: 4px;
}

View File

@@ -31,6 +31,28 @@
a:active {
color: black;
}
&::-webkit-scrollbar {
background: #06a5df;
width: 7px;
}
&::-webkit-scrollbar-button {
display: none;
}
&::-webkit-scrollbar-track {
background: black;
}
&::-webkit-scrollbar-track-piece {
background: black;
}
&::-webkit-scrollbar-thumb {
background: #06a5df;
border-radius: 4px;
}
}
#chat_container.is-conversation-mode #chatconversation {
@@ -212,28 +234,6 @@
line-height: 30px;
}
:not(.default-scrollbar)::-webkit-scrollbar {
background: #06a5df;
width: 7px;
}
:not(.default-scrollbar)::-webkit-scrollbar-button {
display: none;
}
:not(.default-scrollbar)::-webkit-scrollbar-track {
background: black;
}
:not(.default-scrollbar)::-webkit-scrollbar-track-piece {
background: black;
}
:not(.default-scrollbar)::-webkit-scrollbar-thumb {
background: #06a5df;
border-radius: 4px;
}
#usermsg::-webkit-scrollbar-track-piece {
background: #3a3a3a;
}

View File

@@ -1,8 +1,6 @@
%connection-info {
text-align: left;
font-size: 12px;
font-weight: 400;
color: $popoverFontColor;
td {
padding: 2px 0;
@@ -11,11 +9,14 @@
.connection-info
{
float: left;
padding: 5px;
padding-left: 0;
@extend %connection-info;
/**
* Apply negative margin to reduce the appearance of padding in AtlasKit
* InlineDialog.
*/
margin: -15px;
> table {
white-space: nowrap;
@extend %connection-info;
@@ -32,12 +33,22 @@
&__download
{
@extend .connection-info__icon;
color: $downloadConnectionIconColor;
}
&__status
{
font-weight: bold;
}
&__upload
{
@extend .connection-info__icon;
color: $uploadConnectionIconColor;
}
.showmore {
display: block;
margin: 10px auto;
text-align: center;
width: 90px;
}
}

View File

@@ -1,7 +1,7 @@
#contacts_container {
cursor: default;
> ul#contacts {
#contacts {
font-size: 12px;
bottom: 0px;
margin: 0;
@@ -21,30 +21,33 @@
}
#contacts {
>li {
display: block;
.contact-list-item {
align-items: center;
border-radius: 3px;
color: $baseLight;
display: flex;
font-size: 14px;
height: 36px;
list-style-type: none;
padding: 0 10%;
text-align: left;
white-space: nowrap;
color: $baseLight;
font-size: 16px;
padding: 0 10%;
height: 27px;
&:hover,
&:active {
background: $toolbarSelectBackground;
}
> p {
display: inline-block;
vertical-align: middle;
margin: 0px;
width: 100%;
line-height: 1.5em;
text-overflow: ellipsis;
.contact-list-item-name {
overflow: hidden;
text-overflow: ellipsis;
}
.avatar {
cursor: pointer;
height: 24px;
margin: 0 8px 0 4px;
width: 24px;
}
}
}
@@ -58,4 +61,4 @@
border-radius: 20px;
max-height: 30px;
max-width: 30px;
}
}

81
css/_dial-out.scss Normal file
View File

@@ -0,0 +1,81 @@
/**
* The dialog content element.
*/
.dial-out-content {
margin-top: 5px;
/**
* Wrap the contents in flex so items can be aligned on the same line.
*/
.form-control {
display: flex;
}
/**
* The style of the flag icon.
*/
.dial-out-flag-icon {
position: absolute;
left: 5px;
top: 50%;
transform: translate(0, -50%);
}
/**
* The style of the dial code element.
*/
.dial-out-code {
margin-bottom: 0;
padding-left: 25px;
}
/**
* The dial-out dialog error element.
*/
.dial-out-error {
color: $errorColor;
}
/**
* The style of the dial input element.
*/
.dial-out-input {
display: inline-block;
flex: 1;
margin-left: 5px;
}
/**
* Re-styling the default dropdown inside the dial-out-content.
*/
.dropdown {
position: relative;
width: 65px;
}
/**
* Re-styling the default form-control inside the dial-out-content.
*/
.form-control {
margin-bottom: 8px;
}
.dropdown {
position: relative;
input {
padding-left: 16px;
&:read-only {
color: inherit;
}
}
}
.dropdown-trigger-icon {
position: absolute;
right: 0;
top: 50%;
transform: translate(0, -50%);
}
}

View File

@@ -11,13 +11,13 @@
right: 0;
padding: 10px 5px;
@extend %align-right;
z-index: $filmstripVideosZ;
&__toolbar {
@include flex();
flex-direction: column-reverse;
flex-wrap: nowrap;
position: relative;
z-index: $zindex1; // Set z-index to make element visible.
width: $filmstripToggleButtonWidth;
button {
@@ -48,24 +48,65 @@
&__videos {
@extend %align-right;
position:relative;
height:196px;
padding: 0;
/* The filmstrip should not be covered by the left toolbar. */
padding-left: $defaultToolbarSize + 5;
bottom: 0;
width:auto;
border: $thumbnailsBorder solid transparent;
z-index: $filmstripVideosZ;
transition: bottom 2s;
overflow: visible !important;
/*!!! Removes the gap between the local video container and the remote
videos. */
font-size: 0pt;
&#remoteVideos {
border: $thumbnailsBorder solid transparent;
padding-left: $defaultToolbarSize + 5;
transition: bottom 2s;
}
/**
* The local video identifier.
*/
&#filmstripLocalVideo {
bottom: 32px;
display: block;
/**
* The invite button style.
*/
.filmstrip__invite {
padding-bottom: 5px;
margin-left: 2px;
}
/**
* The invite button group style.
* TOFIX: use AtlasKit.ButtonGroup if it starts supporting different
* flex grow options for the buttons.
*/
.invite-button-group {
display: inline-flex;
justify-content: space-between;
width: 100%;
& button {
flex-grow: 1;
flex-shrink: 1;
overflow: hidden;
}
& > * {
flex-grow: 0;
flex-shrink: 0;
margin-left: 2px;
}
}
}
&.hidden {
bottom: -196px;
}
.remote-videos-container {
display: flex;
}
.videocontainer {
display: none;
position: relative;
@@ -96,6 +137,24 @@
display: none;
}
.presence-label {
color: $participantNameColor;
font-size: 12px;
font-weight: 100;
left: 0;
margin: 0 auto;
overflow: hidden;
pointer-events: none;
position: absolute;
right: 0;
text-align: center;
text-overflow: ellipsis;
top: calc(50% + 30px);
white-space: nowrap;
width: 100%;
z-index: $zindex3;
}
/**
* Hovered video thumbnail.
*/
@@ -128,6 +187,22 @@
&__videos-filmstripOnly {
margin-top: auto;
margin-bottom: auto;
padding-right: $defaultToolbarSize;
.filmstrip__videos {
&#filmstripLocalVideo {
bottom: 0px;
}
}
}
.remote-videos-container {
transition: opacity 1s;
}
&.hide-videos {
.remote-videos-container {
opacity: 0;
pointer-events: none;
}
}
}

35
css/_flag-icon.scss Executable file
View File

@@ -0,0 +1,35 @@
.flag-icon-background {
background-size: contain;
background-position: 50%;
background-repeat: no-repeat;
}
.flag-icon {
background-size: contain;
background-position: 50%;
background-repeat: no-repeat;
position: relative;
display: inline-block;
width: 1.33333333em;
line-height: 1em;
}
.flag-icon:before {
content: "\00a0";
}
.flag-icon-au {
background-image: url(../images/countries/au.svg);
}
.flag-icon-ca {
background-image: url(../images/countries/ca.svg);
}
.flag-icon-de {
background-image: url(../images/countries/de.svg);
}
.flag-icon-gb {
background-image: url(../images/countries/gb.svg);
}
.flag-icon-fr {
background-image: url(../images/countries/fr.svg);
}
.flag-icon-us {
background-image: url(../images/countries/us.svg);
}

View File

@@ -25,120 +25,135 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-thumb-menu:before {
content: "\e5d4";
}
.icon-mic-camera-combined:before {
content: "\e903";
content: "\e903";
}
.icon-feedback:before {
content: "\e91d";
content: "\e91d";
}
.icon-toggle-filmstrip:before {
content: "\e91c";
content: "\e91c";
}
.icon-avatar:before {
content: "\e901";
content: "\e901";
}
.icon-hangup:before {
content: "\e905";
content: "\e905";
}
.icon-chat:before {
content: "\e906";
content: "\e906";
}
.icon-download:before {
content: "\e902";
}
.icon-dialpad:before {
content: "\e61c";
content: "\e902";
}
.icon-edit:before {
content: "\e907";
content: "\e907";
}
.icon-share-doc:before {
content: "\e908";
}
.icon-telephone:before {
content: "\e909";
content: "\e908";
}
.icon-kick:before {
content: "\e904";
content: "\e904";
}
.icon-menu-up:before {
content: "\e91f";
content: "\e91f";
}
.icon-menu-down:before {
content: "\e920";
content: "\e920";
}
.icon-full-screen:before {
content: "\e90b";
content: "\e90b";
}
.icon-exit-full-screen:before {
content: "\e90c";
content: "\e90c";
}
.icon-star-full:before {
content: "\e90a";
content: "\e90a";
}
.icon-security:before {
content: "\e90d";
content: "\e90d";
}
.icon-security-locked:before {
content: "\e90e";
content: "\e90e";
}
.icon-reload:before {
content: "\e90f";
content: "\e90f";
}
.icon-microphone:before {
content: "\e910";
content: "\e910";
}
.icon-mic-empty:before {
content: "\e911";
content: "\e911";
}
.icon-mic-disabled:before {
content: "\e912";
content: "\e912";
}
.icon-ninja:before {
content: "\e909";
}
.icon-raised-hand:before {
content: "\e91e";
content: "\e91e";
}
.icon-contactList:before {
content: "\e91b";
content: "\e91b";
}
.icon-link:before {
content: "\e913";
content: "\e913";
}
.icon-shared-video:before {
content: "\e914";
content: "\e914";
}
.icon-settings:before {
content: "\e915";
content: "\e915";
}
.icon-star:before {
content: "\e916";
content: "\e916";
}
.icon-switch-camera:before {
content: "\e921";
content: "\e921";
}
.icon-share-desktop:before {
content: "\e917";
content: "\e917";
}
.icon-camera:before {
content: "\e918";
content: "\e918";
}
.icon-camera-disabled:before {
content: "\e919";
content: "\e919";
}
.icon-volume:before {
content: "\e91a";
}
.icon-connection-lost:before {
content: "\e900";
}
.icon-connection:before {
content: "\e61a";
content: "\e91a";
}
.icon-recDisable:before {
content: "\e613";
content: "\e613";
}
.icon-recEnable:before {
content: "\e614";
content: "\e614";
}
.icon-presentation:before {
content: "\e603";
}
content: "\e603";
}
.icon-dialpad:before {
content: "\e925";
}
.icon-visibility:before {
content: "\e923";
}
.icon-visibility-off:before {
content: "\e924";
}
.icon-telephone:before {
content: "\e0cd";
}
.icon-add:before {
content: "\e145";
}
.icon-info:before {
content: "\e922";
}
.icon-gsm-bars:before {
content: "\e926";
}

View File

@@ -93,6 +93,7 @@
}
&__avatar-container {
height: 100%;
position: relative;
> img {
height: 100%;

View File

@@ -1,47 +0,0 @@
.jitsipopover {
position: absolute;
top: 0;
left: 0;
z-index: $jitsipopoverZ;
display: none;
max-width: 300px;
min-width: 100px;
text-align: left;
color: $popoverFontColor;
background-color: $popoverBg;
background-clip: padding-box;
border-radius: $borderRadius;
/*-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);*/
/*box-shadow: 0 5px 10px rgba(0, 0, 0, 0.4);*/
white-space: normal;
margin-top: -$popoverMenuPadding;
&__menu-padding {
height: $popoverMenuPadding;
width: 100px;
position: absolute;
bottom: -$popoverMenuPadding;
}
&__showmore {
display: block;
text-align: center;
width: 90px;
margin: 10px auto;
}
> .arrow {
position: absolute;
display: block;
left: 50%;
bottom: -5px;
margin-left: -5px;
width: 0;
height: 0;
border-color: transparent;
border-top-color: $popoverBg;
border-style: solid;
border-width: 5px;
border-bottom-width: 0;
}
}

View File

@@ -1,124 +1,33 @@
.popover {
position: absolute;
top: 0;
left: 0;
z-index: $popoverZ;
display: none;
max-width: 300px;
min-width: 100px;
padding: 1px;
text-align: left;
color: #333333;
background-color: #ffffff;
background-clip: padding-box;
border: 1px solid #cccccc;
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 6px;
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.4);
white-space: normal;
/**
* Mousemove padding styles are used to add invisible elements to the popover
* to allow mouse movement from the popover trigger to the popover itself
* without triggering a mouseleave event.
*/
.popover-mousemove-padding-bottom {
bottom: -15px;
height: 20px;
position: absolute;
right: 0;
width: 100%;
}
.popover.top {
margin-top: -10px;
.popover-mousemove-padding-right {
height: 100%;
position: absolute;
right: -20;
top: 0;
width: 40px;
}
.popover.right {
margin-left: 10px;
}
.popover.bottom {
margin-top: 10px;
}
.popover.left {
margin-left: -10px;
}
.popover-title {
margin: 0;
padding: 8px 14px;
font-size: 11pt;
font-weight: normal;
line-height: 18px;
background-color: #f7f7f7;
border-bottom: 1px solid #ebebeb;
border-radius: 5px 5px 0 0;
}
.popover-content {
padding: 9px 14px;
font-size: 10pt;
white-space:pre-wrap;
text-align: center;
}
.popover > .arrow,
.popover > .arrow:after {
position: absolute;
display: block;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
}
.popover > .arrow {
border-width: 11px;
}
.popover > .arrow:after {
border-width: 10px;
content: "";
}
.popover.top > .arrow {
left: 50%;
margin-left: -11px;
border-bottom-width: 0;
border-top-color: #999999;
border-top-color: rgba(0, 0, 0, 0.25);
bottom: -11px;
}
.popover.top > .arrow:after {
content: " ";
bottom: 1px;
margin-left: -10px;
border-bottom-width: 0;
border-top-color: #ffffff;
}
.popover.right > .arrow {
top: 50%;
left: -11px;
margin-top: -11px;
border-left-width: 0;
border-right-color: #999999;
border-right-color: rgba(0, 0, 0, 0.25);
}
.popover.right > .arrow:after {
content: " ";
left: 1px;
bottom: -10px;
border-left-width: 0;
border-right-color: #ffffff;
}
.popover.bottom > .arrow {
left: 50%;
margin-left: -11px;
border-top-width: 0;
border-bottom-color: #999999;
border-bottom-color: rgba(0, 0, 0, 0.25);
top: -11px;
}
.popover.bottom > .arrow:after {
content: " ";
top: 1px;
margin-left: -10px;
border-top-width: 0;
border-bottom-color: #ffffff;
}
.popover.left > .arrow {
top: 50%;
right: -11px;
margin-top: -11px;
border-right-width: 0;
border-left-color: #999999;
border-left-color: rgba(0, 0, 0, 0.25);
}
.popover.left > .arrow:after {
content: " ";
right: 1px;
border-right-width: 0;
border-left-color: #ffffff;
bottom: -10px;
/**
* An invisible element is added to the top of the popover to ensure the mouse
* stays over the popover when the popover's height is shrunk, which would then
* normally leave the mouse outside of the popover itself and cause a mouseleave
* event.
*/
.popover-mouse-padding-top {
height: 30px;
position: absolute;
right: 0;
top: -25px;
width: 100%;
}

View File

@@ -3,22 +3,16 @@
**/
.popupmenu {
text-align: left;
padding: 0;
margin: 2px 0;
bottom: 0;
height: auto;
&:first-child {
margin-top: 2px;
}
white-space: nowrap;
&__item {
list-style-type: none;
text-align: left;
height: 35px;
&:hover {
background-color: $popupMenuSelectedItemBackground;
background-color: rgba(9, 30, 66, 0.04);
}
}
@@ -28,36 +22,55 @@
display: block;
box-sizing: border-box;
text-decoration: none;
color: #fff;
padding: 5px;
height: 100%;
font-size: 9pt;
width: 100%;
cursor: hand;
cursor: pointer;
padding: 0 5px;
&.disabled {
color: gray !important;
pointer-events: none;
}
}
&__text,
&__slider {
&__text {
display: inline-block;
vertical-align: middle;
}
&__slider {
width: 50px;
&__link {
i {
cursor: pointer;
}
}
&__contents {
display: flex;
/**
* Positioning styles on the slider and its container are used to make
* the container fit the popup width, by removing the slider from the
* page flow, and then making the slider fit the container.
*/
.popupmenu__slider_container {
position: relative;
width: 100%;
.popupmenu__slider {
position: absolute;
top: 50%;
transform: translate(0, -50%);
width: 100%;
}
}
}
&__icon {
vertical-align: middle;
position: relative;
display: inline-block;
width: 20px;
min-width: 20px;
height: 100%;
text-align: center;
> * {
@include absoluteAligning();
@@ -69,6 +82,15 @@
}
}
/**
* Override reset css styling modifying all lists and set negative margin to
* reduce the visibility of padding on AtlasKit
* InlineDialogs.
*/
ul.popupmenu {
margin: -15px;
}
span.remotevideomenu:hover ul.popupmenu, ul.popupmenu:hover {
display:block !important;
}

View File

@@ -1,4 +1,3 @@
.recordingSpinner {
display: none;
vertical-align: top;
}
}

View File

@@ -2,7 +2,7 @@
* Toolbar side panel main container element.
*/
#sideToolbarContainer {
background-color: rgba(0,0,0,0.8);
background-color: $sideToolbarContainerBg;
height: 100%;
left: $defaultToolbarSize;
max-width: $sidebarWidth;

View File

@@ -1,107 +0,0 @@
/*
* Toastr
* Copyright 2012-2014 John Papa and Hans Fjällemark.
* All Rights Reserved.
* Use, reproduction, distribution, and modification of this code is subject to the terms and
* conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php
*
* Author: John Papa and Hans Fjällemark
* Project: https://github.com/CodeSeven/toastr
*
* Last updated: October 13, 2016
*/
.toast-title,
.toast-message .nickname {
font-weight: bold;
margin: 0 0 3px;
@include text-truncate;
}
.toast-message {
-ms-word-wrap: break-word;
word-wrap: break-word;
}
.toast-message a,
.toast-message label,
.toast-message .connected,
.toast-message .disconnected {
color: $notificationLinkColor;
text-decoration: none;
}
.toast-message a:hover {
text-decoration: underline;
}
.toast-message br {
display: none;
}
// close button
.toast-close-button {
color: $notificationColor;
background: transparent;
font-size: 15px;
line-height: 1.2;
height: 20px;
width: 20px;
padding: 0;
border: 0;
margin: -6px -10px 0 0;
float: right;
cursor: pointer;
@include opacity(0.4);
/* Additional properties for button version
iOS requires the button element instead of an anchor tag.
If you want the anchor version, it requires `href="#"`. */
-webkit-appearance: none;
}
.toast-close-button:hover,
.toast-close-button:focus {
@include opacity(1);
}
.toast {
color: $notificationColor;
background-color: $notificationBackground;
font-size: $notificationFontSize;
padding: $notificationPadding;
border: 1px solid lighten($notificationBackground, 10%);
@include border-radius($notificationBorderRadius);
@include box-shadow(1px, 1px, 2px, rgba(0,0,0,0.3));
@include opacity($notificationOpacity);
}
.toast:hover {
@include opacity(1);
}
#toast-container {
position: fixed;
z-index: $notificationZ;
}
#toast-container.notification-bottom-right {
$videoOffset: 2 * ($thumbnailVideoMargin + $thumbnailsBorder) + $thumbnailVideoBorder;
bottom: 135px;
right: $filmstripToggleButtonWidth + $videoOffset;
}
#toast-container * {
@include box-sizing(border-box);
}
#toast-container .toast {
width: $notificationWidth;
margin: 0 0 8px;
}

View File

@@ -19,70 +19,6 @@
vertical-align: middle;
}
/**
* Toolbar button styles.
*/
.button {
color: #FFFFFF;
cursor: pointer;
z-index: $zindex1;
display: inline-block;
font-size: $toolbarFontSize !important;
height: 50px;
line-height: 50px !important;
position: relative;
text-align: center;
top:0px;
vertical-align: middle;
width: 50px;
&_hangup {
color: $hangupColor;
font-size: $hangupFontSize !important;
}
&[disabled] {
opacity: 0.5;
}
&:hover, &:active {
cursor: pointer;
text-decoration: none;
}
&:not(.toggled) {
&:hover, &:active {
// sum opacity with background layer should give us 0.8
background: $toolbarSelectBackground;
}
}
&.toggled {
background: $toolbarToggleBackground;
&.icon-camera {
@extend .icon-camera-disabled;
}
&.icon-full-screen {
@extend .icon-exit-full-screen;
}
&.icon-microphone {
@extend .icon-mic-disabled;
}
}
&.unclickable {
cursor: default;
&:hover, &:active, &.selected {
background: none;
cursor: default;
}
}
}
.toolbar-container {
display: block;
left:0;
@@ -100,28 +36,104 @@
* Common toolbar styles.
*/
.toolbar {
background-color: $toolbarBackground;
height: 100%;
pointer-events: auto;
position: relative;
z-index: $toolbarZ;
/**
* Splitter button in the toolbar.
* Ensure nested elements that don't have a button class, maybe because they
* are wrapped in a React Element, still display in a line.
*/
&__splitter {
background: $splitterColor;
> div {
display: inline-block;
height: 50%;
margin: 0 $splitterToolbarButtonMargin;
}
/**
* Always on top overrides.
*/
&.always-on-top {
/**
* Toolbar button styles for always on top.
*/
> .button {
font-size: $alwaysOnTopToolbarFontSize;
height: $alwaysOnTopToolbarSize;
line-height: $alwaysOnTopToolbarSize;
width: $alwaysOnTopToolbarSize;
}
}
/**
* Toolbar button styles.
*/
.button {
color: $toolbarButtonColor;
cursor: pointer;
z-index: $zindex1;
display: inline-block;
font-size: $toolbarFontSize;
height: $defaultToolbarSize;
line-height: $defaultToolbarSize;
position: relative;
text-align: center;
top:0px;
vertical-align: middle;
width: 1px;
width: $defaultToolbarSize;
&[disabled] {
opacity: 0.5;
}
&:hover, &:active {
color: $toolbarButtonColor;
cursor: pointer;
text-decoration: none;
}
&_hangup, &_hangup:hover {
color: $hangupColor;
font-size: $hangupFontSize;
}
&:not(.toggled) {
&:hover, &:active {
// sum opacity with background layer should give us 0.8
background: $toolbarSelectBackground;
}
}
&.toggled {
background: $toolbarToggleBackground;
&.icon-camera {
@extend .icon-camera-disabled;
}
&.icon-full-screen {
@extend .icon-exit-full-screen;
}
&.icon-microphone {
@extend .icon-mic-disabled;
}
}
&.unclickable {
cursor: default;
&:hover, &:active, &.selected {
background: none;
cursor: default;
}
}
}
/**
* Primary toolbar styles.
*/
&_primary {
background-color: $toolbarBackground;
position: absolute;
left: 50%;
top: 30px;
@@ -131,13 +143,18 @@
border-radius: 3px;
opacity: 0;
&.always-on-top {
height: $alwaysOnTopToolbarSize;
top: 10px;
}
@include transform(translateX(-50%));
.button:first-child {
> div:first-child .button {
border-bottom-left-radius: 3px;
border-top-left-radius: 3px;
}
.button:last-child {
> div:last-child .button {
border-bottom-right-radius: 3px;
border-top-right-radius: 3px;
}
@@ -151,6 +168,7 @@
* Secondary toolbar styles.
*/
&_secondary {
background-color: $secondaryToolbarBg;
position: absolute;
align-items: center;
box-sizing: border-box;
@@ -164,14 +182,20 @@
height: 100%;
justify-content: flex-start;
left: 0;
padding-top: 10px;
padding-top: 24px;
top: 0;
transform: translateX(-100%);
width: $defaultToolbarSize;
-webkit-transform: translateX(-100%);
.button.toggled:not(.icon-raised-hand) {
background: $toolbarSelectBackground;
.button {
font-size: $secToolbarFontSize;
height: $secToolbarLineHeight;
line-height: $secToolbarLineHeight;
}
.button.toggled:not(.icon-raised-hand):not(.button-active) {
background: $secondaryToolbarBg;
cursor: pointer;
text-decoration: none;
@@ -190,19 +214,27 @@
* Styles the toolbar in filmstrip-only mode.
*/
&_filmstrip-only {
background-color: $toolbarBackground;
border-radius: 3px;
bottom: 0;
display: inline-block;
height: auto;
position: absolute;
right: 0;
width: $defaultToolbarSize;
width: $defaultFilmStripOnlyToolbarSize;
.button:first-child {
.button {
height: 37px;
line-height: 37px !important;
width: 37px;
}
.button-popover-message {
width: 100px;
}
.toolbar-button-wrapper:first-child .button {
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
.button:last-child {
.toolbar-button-wrapper:last-child .button {
border-bottom-right-radius: 3px;
border-bottom-left-radius: 3px;
}
@@ -218,6 +250,14 @@
}
}
.filmstrip-only {
.toolbox,
.toolbox-toolbars {
align-items: center;
display: flex;
}
}
.subject {
background: linear-gradient(to bottom, rgba(255,255,255,.85) , rgba(255,255,255,.35));
border-bottom-left-radius: 12px;
@@ -242,11 +282,15 @@
}
}
#toolbar_button_profile {
height: $toolbarAvatarSize + 2*$toolbarAvatarPadding;
}
a.button>#avatar {
border-radius: 50%;
padding-bottom: 10px;
padding-top: 10px;
width: 30px;
padding-bottom: $toolbarAvatarPadding;
padding-top: $toolbarAvatarPadding;
width: $toolbarAvatarSize;
}
#feedbackButton {

View File

@@ -28,21 +28,20 @@ $defaultColor: #F1F1F1;
$defaultSideBarFontColor: #44A5FF;
$defaultSemiDarkColor: #ACACAC;
$defaultDarkColor: #2b3d5c;
$tooltipBg: rgba(0,0,0, 0.7);
/**
* Toolbar
*/
$alwaysOnTopToolbarFontSize: 1em;
$alwaysOnTopToolbarSize: 30px;
$defaultToolbarSize: 50px;
$splitterToolbarButtonMargin: 18px;
$toolbarBackground: rgba(0, 0, 0, 0.5);
$toolbarBadgeBackground: #165ECC;
$toolbarBadgeColor: #FFFFFF;
$defaultFilmStripOnlyToolbarSize: 37px;
$secToolbarFontSize: 1.9em;
$secToolbarLineHeight: 45px;
$toolbarAvatarPadding: 10px;
$toolbarAvatarSize: 40px;
$toolbarFontSize: 1.9em;
$toolbarSelectBackground: rgba(0, 0, 0, .6);
$toolbarTitleColor: #FFFFFF;
$toolbarTitleFontSize: 19px;
$toolbarToggleBackground: #12499C;
/**
* Main controls
@@ -65,6 +64,7 @@ $connectionIndicatorBg: #165ecc;
$audioLevelShadow: rgba(9, 36, 77, 0.9);
$videoStateIndicatorColor: $defaultColor;
$videoStateIndicatorBackground: $toolbarBackground;
$videoStateIndicatorSize: 40px;
/**
* Feedback Modal
@@ -83,22 +83,10 @@ $rateStarSize: 34px;
* Modals
*/
$modalButtonFontSize: 14px;
$modalMockAKInputBackground: #fafbfc;
$modalMockAKInputBorder: 1px solid #f4f5f7;
$modalTextColor: #333;
/**
* Notifications
*/
$notificationFontSize: 13px;
$notificationColor: #FFFFFF;
$notificationBackground: $tooltipBg;
$notificationTitleColor: $notificationColor;
$notificationMessageColor: $notificationColor;
$notificationLinkColor: $notificationColor;
$notificationOpacity: 0.9;
$notificationPadding: 15px 20px;
$notificationBorderRadius: 4px;
$notificationWidth: 215px;
/**
* Misc.
*/
@@ -121,15 +109,13 @@ $reloadZ: 20;
$poweredByZ: 100;
$ringingZ: 300;
$sideToolbarContainerZ: 300;
$toolbarZ: 400;
$toolbarZ: 350;
$tooltipsZ: 401;
$dropdownMaskZ: 900;
$dropdownZ: 901;
$overlayZ: 902;
$jitsipopoverZ: 1010;
$centeredVideoLabelZ: 1011;
$notificationZ: 1012;
$centeredVideoLabelZ: 1010;
$popoverZ: 1015;
$overlayZ: 1016;
/**
@@ -147,6 +133,7 @@ $inputControlEmColor: #f29424;
//buttons
$linkFontColor: #489afe;
$linkHoverFontColor: #287ade;
$formPadding: 16px;
/**
* Unsupported browser
@@ -159,3 +146,9 @@ $unsupportedBrowserTitleColor: #fff;
$unsupportedBrowserTitleFontSize: 24px;
$unsupportedDesktopBrowserTextColor: rgba(255, 255, 255, 0.7);
$unsupportedDesktopBrowserTextFontSize: 21px;
/**
* The size of the default watermark.
*/
$watermarkWidth: 186px;
$watermarkHeight: 74px;

View File

@@ -0,0 +1,226 @@
/**
* Override other styles to support vertical filmstrip mode.
*/
.vertical-filmstrip {
.filmstrip {
align-items: flex-end;
box-sizing: border-box;
display: flex;
flex-direction: column-reverse;
height: 100%;
/**
* fixed positioning is necessary for remote menus and tooltips to pop
* out of the scrolling filmstrip. AtlasKit dialogs and tooltips use
* a library called popper which will position its elements fixed if
* any parent is also fixed.
*/
position: fixed;
/**
* z-index adjusting is needed because the video state indicator has to
* display over the filmstrip when no videos are displayed but still be
* clickable but its inline dialogs must display over the video state
* indicator when videos are displayed.
*/
z-index: #{$tooltipsZ + 1};
/**
* Hide videos by making them slight to the right.
*/
.filmstrip__videos {
right: 0;
&.hidden {
bottom: auto;
right: -196px;
}
/**
* An id selector is used to match id specificity with existing
* filmstrip styles.
*/
&#remoteVideos {
/**
* Remove horizontal filmstrip padding used to prevent videos
* from overlapping the left-side toolbar. An id selector is
* used to match id specificity with filmstrip styles.
*/
padding-left: 0;
transition: right 2s;
}
}
/**
* Re-styles the local Video and invite button to better fit the
* vertical filmstrip layout.
*/
#filmstripLocalVideo {
bottom: 5px;
display: flex;
flex-direction: column-reverse;
height: auto;
justify-content: flex-start;
.filmstrip__invite {
padding-bottom: 0px;
padding-top: 5px;
z-index: $dropdownZ;
}
}
/**
* Remove unnecssary padding that is normally used to prevent horizontal
* filmstrip from overlapping the left edge of the screen.
*/
#filmstripLocalVideo,
#filmstripRemoteVideos {
padding: 0;
}
#filmstripRemoteVideos {
display: flex;
flex: 1;
flex-direction: column;
height: auto;
justify-content: flex-end;
#filmstripRemoteVideosContainer {
flex-direction: column-reverse;
overflow-x: hidden;
}
}
/**
* Rotate the hide filmstrip icon so it points towards the right edge
* of the screen.
*/
&__toolbar {
transform: rotate(-90deg);
}
/**
* Move the remote video menu trigger to the bottom left of the
* video thumbnail.
*/
.remotevideomenu,
.remote-video-menu-trigger {
bottom: 0;
left: 0;
top: auto;
right: auto;
}
.remote-video-menu-trigger {
margin-bottom: 7px;
}
#remoteVideos {
flex-direction: column;
flex-grow: 1;
}
.videocontainer {
/**
* Move status icons to the bottom right of the thumbnail.
*/
&__toolbar {
text-align: right;
.right {
float: none;
margin: auto;
}
}
}
}
&.filmstrip-only {
.filmstrip {
flex-direction: row-reverse;
}
.filmstrip__videos-filmstripOnly {
height: 100%;
}
/**
* In filmstrip only mode, the toolbar is normally displayed in the
* vertical center of the filmstrip strip. In vertical filmstrip mode,
* that alignment makes the toolbar appear floating and detached from
* the filmstrip. So, instead anchor the toolbar next to the local
* video.
*/
.toolbar_filmstrip-only {
bottom: 0;
top: auto;
transform: none;
}
}
/**
* These styles are for the video labels that display on the top right. The
* styles adjust the labels' positioning as the filmstrip itself or
* filmstrip's remote videos appear and disappear.
*
* The class with-filmstrip is for when the filmstrip is visible.
* The class without-filmstrip is for when the filmstrip has been toggled to
* be hidden.
* The class opening is for when the filmstrip is transitioning from hidden
* to visible.
*/
.video-state-indicator.moveToCorner {
transition: right 0.5s;
&.with-filmstrip {
&#recordingLabel {
right: 200px;
}
&#videoResolutionLabel {
right: 150px;
}
}
&.with-filmstrip.opening {
transition: 0.9s;
transition-timing-function: ease-in-out;
}
&.without-filmstrip {
transition: 1.2s ease-in-out;
transition-delay: 0.1s;
}
}
/**
* Apply hardware acceleration to prevent flickering on scroll. The
* selectors are specific to icon wrappers to prevent fixed position dialogs
* and tooltips from getting a new location context due to translate3d.
*/
.connection-indicator,
.remote-video-menu-trigger,
.indicator-icon-container {
transform: translate3d(0, 0, 0);
}
.indicator-container {
float: none;
}
/**
* FIXME: disable pointer to allow any elements moved below to still be
* clickable. The real fix would to make sure those moved elements are
* actually part of the toolbar instead of positioning being faked.
*/
.videocontainer__toolbar {
pointer-events: none;
> div {
pointer-events: none;
}
.toolbar-icon {
pointer-events: all;
}
}
}

View File

@@ -12,6 +12,16 @@
overflow: hidden;
}
.video_blurred_container {
height: 100%;
filter: blur(40px);
left: 0;
overflow: hidden;
position: absolute;
top: 0;
width: 100%;
}
.videocontainer {
position: relative;
text-align: center;
@@ -31,32 +41,85 @@
&__toptoolbar {
position: absolute;
left: 0;
z-index: $zindex3;
pointer-events: none;
z-index: $zindex10;
width: 100%;
box-sizing: border-box; // Includes the padding in the 100% width.
/**
* FIXME (lenny): Disabling pointer-events is a pretty big sin that
* sidesteps the problems. There are z-index wars occurring within
* videocontainer and AtlasKit Tooltips rely on their parent z-indexe
* being higher than whatever they need to appear over. So set a higher
* z-index for the tooltip containers but make any empty space not block
* mouse overs for various mouseover triggers.
*/
pointer-events: none;
* {
pointer-events: auto;
}
.indicator-container {
display: inline-block;
float: left;
pointer-events: all;
}
/**
* Need to overwrite the background for the top toolbar dark theme div
* wrapper needed before we're able to move all top toolbar indicators
* creation to react.
*/
.ckAJgx {
background: none;
}
}
&__toolbar {
bottom: 0;
padding: 0 5px 0 5px;
height: $thumbnailToolbarHeight;
padding: 0 5px 0 5px;
}
&__toptoolbar {
$toolbarPadding: 5px;
$toolbarIconMargin: 5px;
top: 0;
padding: $toolbarPadding;
padding-bottom: 0;
/**
* Override text-align center as icons need to be left justified.
*/
text-align: left;
span.indicator {
/**
* Intentionally use margin on the icon itself as AtlasKit InlineDialog
* positioning depends on the trigger (indicator icon).
*/
.indicator {
margin-left: 5px;
margin-top: $toolbarIconMargin;
}
.indicator-container:nth-child(1) .indicator {
margin-left: $toolbarIconMargin;
}
.indicator-container {
display: inline-block;
vertical-align: top;
.popover-trigger {
display: inline-block;
}
}
.connection-indicator,
.indicator {
position: relative;
font-size: 8px;
text-align: center;
line-height: $thumbnailIndicatorSize;
display: none;
padding: 0;
margin-right: em(5, 8);
float: left;
@include circle($thumbnailIndicatorSize);
box-sizing: border-box;
z-index: $zindex3;
@@ -64,10 +127,6 @@
color: $thumbnailPictogramColor;
border: $thumbnailIndicatorBorder solid $thumbnailPictogramColor;
&:last-child {
margin-right: 0;
}
.indicatoricon {
@include absoluteAligning();
}
@@ -79,31 +138,35 @@
left: 0;
@include transform(translate(0, -50%));
&_empty
&_empty,
&_lost
{
color: #8B8B8B;/*#FFFFFF*/
overflow: hidden;
}
&_lost
{
color: #8B8B8B;
overflow: visible;
}
&_full
{
@include topLeft();
color: #FFFFFF;/*#15A1ED*/
overflow: hidden;
}
&_ninja
{
font-size: 1.5em;
}
}
.icon-connection,
.icon-connection-lost {
.icon-gsm-bars {
cursor: pointer;
font-size: 1em;
}
}
.hide-connection-indicator {
display: none;
}
}
&__hoverOverlay {
@@ -115,6 +178,12 @@
visibility: hidden;
z-index: $zindex2;
}
&.audio-only {
.videoThumbnailProblemFilter {
filter: none;
}
}
}
#localVideoWrapper {
@@ -128,8 +197,8 @@
-o-transform: scale(-1, 1);
}
#localVideoWrapper>video,
#localVideoWrapper>object {
#localVideoWrapper video,
#localVideoWrapper object {
border-radius: $borderRadius !important;
cursor: hand;
object-fit: cover;
@@ -142,6 +211,10 @@
text-align: center;
}
#largeVideoWrapper {
box-shadow: 0 0 20px -2px #444;
}
#largeVideo,
#largeVideoWrapper
{
@@ -150,8 +223,8 @@
#sharedVideo,
#etherpad,
#localVideoWrapper>video,
#localVideoWrapper>object,
#localVideoWrapper video,
#localVideoWrapper object,
#localVideoWrapper,
#largeVideoWrapper,
#largeVideoWrapper>video,
@@ -250,7 +323,6 @@
padding: 0;
border: 0;
margin: 0px 5px 0px 0px;
float: left;
}
/**
@@ -263,37 +335,73 @@
/**
* Toolbar icons positioned on the right.
*/
.toolbar-icon.right {
float: right;
margin: 0px 0px 0px 5px;
.moderator-icon {
display: inline-block;
&.right {
float: right;
margin: 0px 0px 0px 5px;
}
.toolbar-icon {
margin: 0;
}
}
#raisehandindicator {
.raisehandindicator {
background: $raiseHandBg;
}
#connectionindicator {
background: $connectionIndicatorBg;
.connection-indicator {
background: $connectionIndicatorBg;
&.status-high {
background: green;
}
&.status-med {
background: #FFD740;
}
&.status-lost {
background: gray;
}
&.status-low {
background: #BF2117;
}
&.status-other {
background: $connectionIndicatorBg;
}
}
.remote-video-menu-trigger,
.remotevideomenu
{
display: inline-block;
position: absolute;
top: 0px;
right: 0;
margin: 7px;
z-index: $zindex3;
z-index: $zindex2;
width: 18px;
height: 13px;
color: #FFF;
font-size: 8pt;
font-size: 10pt;
>i{
cursor: hand;
}
}
.remote-video-menu-trigger {
margin-top: 7px;
}
/**
* Audio indicator on video thumbnails.
*/
.videocontainer>span.audioindicator {
.videocontainer>span.audioindicator,
.videocontainer>.audioindicator-container {
position: absolute;
display: inline-block;
left: 6px;
@@ -449,8 +557,8 @@
filter: grayscale(100%);
}
#remotePresenceMessage,
#remoteConnectionMessage {
display: none;
position: absolute;
width: auto;
z-index: $zindex2;
@@ -458,6 +566,11 @@
font-size: 14px;
text-align: center;
color: #FFF;
left: 50%;
transform: translate(-50%, 0);
}
#remotePresenceMessage .presence-label,
#remoteConnectionMessage {
opacity: .80;
text-shadow: 0px 0px 1px rgba(0,0,0,0.3),
0px 1px 1px rgba(0,0,0,0.3),
@@ -470,6 +583,10 @@
padding-left: 10px;
padding-right: 10px;
}
#remotePresenceMessage .no-presence,
#remoteConnectionMessage {
display: none;
}
#localConnectionMessage {
display: none;
@@ -488,44 +605,3 @@
1px 0px 1px rgba(0,0,0,0.3),
0px 0px 1px rgba(0,0,0,0.3);
}
.video-state-indicator {
background: $videoStateIndicatorBackground;
color: $videoStateIndicatorColor;
font-size: 13px;
line-height: 20px;
text-align: center;
min-width: 40px;
height: 40px;
padding: 10px 5px;
border-radius: 50%;
position: absolute;
box-sizing: border-box;
}
#videoResolutionLabel,
.centeredVideoLabel {
display: none;
z-index: $centeredVideoLabelZ;
}
.centeredVideoLabel {
bottom: 45%;
border-radius: 2px;
-webkit-transition: all 2s 2s linear;
transition: all 2s 2s linear;
&.moveToCorner {
bottom: auto;
}
}
.moveToCorner {
position: absolute;
top: 30px;
right: 30px;
}
.moveToCorner + .moveToCorner {
right: 80px;
}

View File

@@ -1,5 +1,5 @@
.form-control {
padding: 16px 0;
padding: $formPadding 0;
&:first-child {
padding-top: 0;
@@ -23,19 +23,6 @@
color: $inputControlEmColor;
}
&__hint {
margin-top: 0;
font-size: $hintFontSize;
span {
vertical-align: middle;
}
&_error {
color: $errorColor;
}
}
&__container {
position: relative;
width: 100%;

View File

@@ -3,13 +3,10 @@
display: inline-block;
width: 100%;
padding: 5px 7px;
color: $inputColor;
border-radius: $borderRadius;
line-height: 32px;
height: 32px;
text-align: left;
border:1px solid $inputBorderColor;
background-color: $inputBackground;
margin-bottom: 8px;
&:last-child {

View File

@@ -26,12 +26,13 @@
@import 'font';
@import 'font-awesome';
/* Fonts END */
@import 'flag-icon';
/* Modules BEGIN */
@import 'toastr';
@import 'dial-out';
@import 'base';
@import 'utils';
@import 'overlay/overlay';
@@ -41,14 +42,14 @@
@import 'modals/device-selection/device-selection';
@import 'modals/dialog';
@import 'modals/feedback/feedback';
@import 'modals/invite/info';
@import 'modals/speaker_stats/speaker_stats';
@import 'modals/video-quality/video-quality';
@import 'videolayout_default';
@import 'notice';
@import 'popup_menu';
@import 'recording';
@import 'login_menu';
@import 'popover';
@import 'jitsi_popover';
@import 'contact_list';
@import 'chat';
@import 'ringing/ringing';
@@ -69,7 +70,10 @@
@import 'aui-components/dropdown';
@import '404';
@import 'policy';
@import 'popover';
@import 'filmstrip';
@import 'unsupported-browser/main';
@import 'modals/invite/add-people';
@import 'vertical_filmstrip_overrides';
/* Modules END */

View File

@@ -79,7 +79,36 @@
.modal-dialog-form {
color: $modalTextColor;
margin-top: 5px !important;
.input-control {
background: $modalMockAKInputBackground;
border: $modalMockAKInputBorder;
color: inherit;
}
&-error {
margin-bottom: 8px;
}
}
.modal-dialog-footer {
font-size: $modalButtonFontSize;
}
/**
* Styling inline dialog errors.
*/
.inline-dialog-error {
margin-top: 16px;
&-text {
color: $dialogErrorText;
margin-bottom: 8px;
text-align: center;
}
&-button {
display: block;
margin: 16px auto 0 auto;
}
}

View File

@@ -26,6 +26,13 @@
width: 30%;
}
}
&-spinner {
justify-content: center;
display: flex;
height: 100%;
align-items: center;
}
}
.desktop-picker-source {

View File

@@ -4,12 +4,6 @@
.device-selectors {
font-size: 14px;
/* ensure all child components do not exceed parent width */
button,
div {
max-width: 100%;
}
> div {
display: block;
margin-bottom: 10px;
@@ -20,8 +14,41 @@
}
.device-selector-icon {
align-self: center;
color: inherit;
font-size: 20px;
margin-left: 3px;
}
/* device-selector-trigger stylings attempt to mimic AtlasKit button */
.device-selector-trigger {
background-color: rgba(9, 30, 66, 0.04);
border-radius: 3px;
color: #505f79;
display: flex;
height: 2.3em;
justify-content: space-between;
line-height: 2.3em;
overflow: hidden;
padding: 0 8px;
&:hover {
background-color: rgba(9,30,66,.08);
}
}
.device-selector-trigger-disabled {
.device-selector-trigger {
color: #a5adba;
cursor: default;
}
}
.device-selector-trigger-text {
overflow: hidden;
margin-left: 8px;
text-overflow: ellipsis;
white-space: nowrap;
width: 100%;
}
}
@@ -41,11 +68,7 @@
}
.device-selection-video-container {
/* TOFIX: to be removed when we move out from muted preview */
background: black;
border-radius: 3px;
/* TOFIX-END */
height: 160px;
margin-bottom: 5px;
.video-input-preview {
@@ -56,7 +79,7 @@
border-radius: 3px;
}
.video-input-preview-muted {
.video-input-preview-error {
color: $participantNameColor;
display: none;
left: 0;
@@ -66,12 +89,16 @@
top: 50%;
}
&.video-muted .video-input-preview-muted {
display: block;
&.video-preview-has-error {
background: black;
.video-input-preview-error {
display: block;
}
}
.video-input-preview-display {
height: 100%;
height: auto;
overflow: hidden;
width: 100%;
}

View File

@@ -45,83 +45,59 @@
animation-timing-function: ease-in-out
}
.feedback.aui-dialog2{
.aui-dialog2{
&-header {
background-color: $feedbackContentBg;
border-bottom-color: transparent;
padding-top: 30px;
h2 {
color: $feedbackTextColor;
text-align: center;
}
}
.feedback-dialog {
.details {
margin-top: 20px;
padding-left: 60px;
padding-right: 60px;
&-content {
background-color: $feedbackContentBg;
text-align: center;
padding: 10px 40px 20px 40px;
.input-control {
background-color: $feedbackInputBg;
color: $feedbackInputTextColor;
&::-webkit-input-placeholder {
color: $feedbackInputPlaceholderColor;
}
&::-moz-placeholder { /* Firefox 19+ */
color: $feedbackInputPlaceholderColor;
}
&:-ms-input-placeholder {
color: $feedbackInputPlaceholderColor;
}
}
.rating {
line-height: 1.2;
text-align: center;
margin-top: 10px;
.star-label {
height: 16px;
font-size: 14px;
color: $rateStarLabelColor;
}
.star-btn {
display: inline-block;
color: $rateStarDefault;
font-size: $rateStarSize;
position: relative;
cursor: pointer;
outline: none;
text-decoration: none;
@include transition(all .2s ease);
&.starHover,
&.active,
&:hover {
color: $rateStarActivity;
};
}
}
.details {
padding-left: 60px;
padding-right: 60px;
margin-top: 20px;
textarea {
min-height: 100px;
}
}
}
&-footer {
background-color: $feedbackContentBg;
border-top-color: transparent;
.button-control {
color: $feedbackCancelFontColor;
}
textarea {
min-height: 100px;
}
}
}
.input-control {
background-color: $feedbackInputBg;
color: $feedbackInputTextColor;
&::-webkit-input-placeholder {
color: $feedbackInputPlaceholderColor;
}
&::-moz-placeholder { /* Firefox 19+ */
color: $feedbackInputPlaceholderColor;
}
&:-ms-input-placeholder {
color: $feedbackInputPlaceholderColor;
}
}
.rating {
line-height: 1.2;
margin-top: 10px;
text-align: center;
.star-label {
color: $rateStarLabelColor;
font-size: 14px;
height: 16px;
}
.star-btn {
color: $rateStarDefault;
cursor: pointer;
display: inline-block;
font-size: $rateStarSize;
outline: none;
position: relative;
text-decoration: none;
@include transition(all .2s ease);
&.active,
&:hover,
&.starHover {
color: $rateStarActivity;
};
}
}
}

View File

@@ -0,0 +1,32 @@
/**
* Styles errors and links in the AddPeopleDialog.
*/
.modal-dialog-form {
.add-people-form-wrap {
.error {
padding-left: 5px;
a {
padding-left: 5px;
}
}
}
}
/**
* Styles the loading element in the MultiSelectAutocomplete.
*/
.autocomplete-loading {
justify-content: center;
display: flex;
min-width: 260px;
padding: 20px;
}
/**
* Styles errors in the MultiSelectAutocomplete.
*/
.autocomplete-error {
min-width: 260px;
}

View File

@@ -0,0 +1,60 @@
.info-dialog {
cursor: default;
display: flex;
.info-dialog-action-link {
display: inline-block;
a {
cursor: pointer;
}
}
.info-dialog-action-link:before {
color: $linkFontColor;
content: '\2022';
padding: 0 10px;
}
.info-dialog-action-link:first-child:before {
content: '';
padding: 0;
}
.info-dialog-action-links {
white-space: nowrap;
}
.info-dialog-action-separator {
display: inline-block;
}
.info-dialog-copy-element {
opacity: 0;
pointer-events: none;
position: fixed;
-webkit-user-select: text;
user-select: text;
}
.info-dialog-column {
margin-right: 10px;
}
.info-dialog-conference-url {
margin: 10px 0;
max-width: 250px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.info-dialog-icon {
color: #6453C0;
font-size: 16px;
}
.info-dialog-title {
font-weight: bold;
}
}

View File

@@ -4,4 +4,93 @@
*/
#inviteDialogRemovePassword {
cursor: hand;
}
}
.invite-dialog {
.dial-in-numbers {
.dial-in-numbers-conference-id {
color: orange;
margin-left: 3px;
}
/*
* dial-in-numbers-copy styling is needed for the feature of copying
* text to the clipboard. The styling keeps the element invisible
* to the user but still programmatically selectable for copying.
*/
.dial-in-numbers-copy {
opacity: 0;
pointer-events: none;
position: fixed;
-webkit-user-select: text;
user-select: text;
}
.is-disabled,
.is-loading {
.dial-in-numbers-trigger-icon {
display: none;
}
}
}
.form-control {
padding: 0;
&__container {
/**
* Ensure contents display in a line and vertically centered.
*/
align-items: center;
button {
font-size: $modalButtonFontSize;
}
}
&__input-container {
flex: 1;
margin-right: 10px;
.dropdown-button-trigger {
text-align: left;
}
}
}
.inviteLink {
color: $readOnlyInputColor;
}
.lock-state {
display: flex;
}
.password-overview {
margin-top: 10px;
.form-control {
margin-top: 10px;
}
.password-overview-status,
.remove-password {
display: flex;
justify-content: space-between;
}
.password-overview-toggle-edit,
.remove-password-link {
cursor: pointer;
text-decoration: none;
}
.remove-password {
margin-top: 15px;
}
}
.remove-password-current {
color: $inputControlEmColor;
}
}

View File

@@ -0,0 +1,173 @@
.video-quality-dialog {
.hide-warning {
height: 0;
visibility: hidden;
}
.video-quality-dialog-title {
margin-bottom: 10px;
}
.video-quality-dialog-contents {
align-items: center;
display: flex;
flex-direction: column;
padding: 10px;
min-width: 250px;
.video-quality-dialog-slider-container {
width: 100%;
text-align: center;
}
.video-quality-dialog-slider {
width: calc(100% - 5px);
@mixin sliderTrackStyles() {
height: 15px;
border-radius: 10px;
background: #0E1624;
}
&::-ms-track {
@include sliderTrackStyles();
}
&::-moz-range-track {
@include sliderTrackStyles();
}
&::-webkit-slider-runnable-track {
@include sliderTrackStyles();
}
@mixin sliderThumbStyles() {
top: 50%;
border: none;
position: relative;
opacity: 0;
}
&::-ms-thumb {
@include sliderThumbStyles();
}
&::-moz-range-thumb {
@include sliderThumbStyles();
}
&::-webkit-slider-thumb {
@include sliderThumbStyles();
}
}
.video-quality-dialog-labels {
box-sizing: border-box;
display: flex;
margin-top: 5px;
position: relative;
width: 90%;
}
.video-quality-dialog-label-container {
position: absolute;
text-align: center;
transform: translate(-50%, 0%);
&::before {
content: '';
border-radius: 50%;
left: 0;
height: 6px;
margin: 0 auto;
pointer-events: none;
position: absolute;
right: 0;
top: -16px;
width: 6px;
}
}
.video-quality-dialog-label-container.active {
color: $videoQualityActive;
&::before {
background: $videoQualityActive;
height: 12px;
top: -19px;
width: 12px;
}
}
.video-quality-dialog-label-container:first-child {
position: relative;
}
.video-quality-dialog-label {
display: table-caption;
word-spacing: unset;
}
}
}
.video-state-indicator {
background: $videoStateIndicatorBackground;
cursor: default;
font-size: 13px;
height: $videoStateIndicatorSize;
line-height: 20px;
text-align: left;
min-width: $videoStateIndicatorSize;
border-radius: 50%;
position: absolute;
box-sizing: border-box;
i {
line-height: $videoStateIndicatorSize;
}
/**
* Give the label padding so it has more volume and can be easily clicked.
*/
.video-quality-label-status {
line-height: $videoStateIndicatorSize;
min-width: $videoStateIndicatorSize;
text-align: center;
}
}
.centeredVideoLabel.moveToCorner {
z-index: $tooltipsZ;
}
#videoResolutionLabel {
z-index: #{$tooltipsZ + 1};
}
.centeredVideoLabel {
bottom: 45%;
border-radius: 2px;
display: none;
padding: 10px;
transform: translate(-50%, 0);
z-index: $centeredVideoLabelZ;
&.moveToCorner {
bottom: auto;
transform: none;
-webkit-transition: all 2s 2s linear;
transition: all 2s 2s linear;
}
}
.moveToCorner {
position: absolute;
top: 30px;
right: 30px;
}
.moveToCorner + .moveToCorner {
right: 80px;
}

View File

@@ -44,12 +44,6 @@ $defaultBackground: #474747;
$filmstripOnlyOverlayBg: #000;
$reloadProgressBarBg: #0074E0;
/**
* Connection indicator
**/
$downloadConnectionIconColor: #4abd04;
$uploadConnectionIconColor: #ffa800;
/**
* Dialog colors
**/
@@ -58,6 +52,7 @@ $auiDialogBg: #f5f5f5;
$auiDialogContentBg: $baseLight;
$auiBorderColor: #ccc;
$dialogTitleFontWeight: 400;
$dialogErrorText: #344563;
/**
* Inlay colors
@@ -70,9 +65,6 @@ $inlayFilmstripOnlyColor: #474747;
$inlayFilmstripOnlyBg: #fff;
// Main controls
$inputBackground: $controlBackground;
$inputBorderColor: #ccc;
$inputColor: $controlColor;
$placeHolderColor: #a7a7a7;
$readOnlyInputColor: #a7a7a7;
$defaultDarkSelectionColor: #ccc;
@@ -93,7 +85,17 @@ $popoverFontColor: #ffffff;
$popupMenuSelectedItemBackground: rgba(256, 256, 256, .2);
// Toolbar
$splitterColor: #ccc;
$secondaryToolbarBg: rgba(0, 0, 0, 0.5);
// TOFIX: Once moved to react rename to match the side panel class name.
$sideToolbarContainerBg: rgba(0, 0, 0, 0.75);
$toolbarBackground: rgba(0, 0, 0, 0.5);
$toolbarBadgeBackground: #165ECC;
$toolbarBadgeColor: #FFFFFF;
$toolbarButtonColor: #FFFFFF;
$toolbarSelectBackground: rgba(0, 0, 0, .6);
$toolbarTitleColor: #FFFFFF;
$toolbarToggleBackground: #12499C;
/**
* Forms
@@ -103,3 +105,8 @@ $selectFontColor: $controlColor;
$selectBg: $controlBackground;
$selectActiveBg: darken($controlBackground, 5%);
$selectActiveItemBg: darken($controlBackground, 20%);
/**
* TODO: Replace by themed component.
*/
$videoQualityActive: #4C9AFF;

View File

@@ -103,27 +103,6 @@ case "$1" in
echo -e "\nInclude \"conf.d/*.cfg.lua\"" >> $PROSODY_CONFIG_OLD
fi
fi
# UPGRADE to server side focus check if focus is configured
if [ -f $PROSODY_HOST_CONFIG ] && ! grep -q "VirtualHost \"$JICOFO_AUTH_DOMAIN\"" $PROSODY_HOST_CONFIG; then
echo -e "\nVirtualHost \"$JICOFO_AUTH_DOMAIN\"" >> $PROSODY_HOST_CONFIG
echo -e " authentication = \"internal_plain\"\n" >> $PROSODY_HOST_CONFIG
sed -i "s/Component \"conference.$JVB_HOSTNAME\" \"muc\"/Component \"conference.$JVB_HOSTNAME\" \"muc\"\nadmins = { \"$JICOFO_AUTH_USER@$JICOFO_AUTH_DOMAIN\" }\n/g" $PROSODY_HOST_CONFIG
echo -e "Component \"focus.$JVB_HOSTNAME\"" >> $PROSODY_HOST_CONFIG
echo -e " component_secret=\"$JICOFO_SECRET\"\n" >> $PROSODY_HOST_CONFIG
PROSODY_CREATE_JICOFO_USER="true"
# UPGRADE to server side focus on old config(/etc/prosody/prosody.cfg.lua)
elif [ ! -f $PROSODY_HOST_CONFIG ] && ! grep -q "VirtualHost \"$JICOFO_AUTH_DOMAIN\"" $PROSODY_CONFIG_OLD; then
echo -e "\nVirtualHost \"$JICOFO_AUTH_DOMAIN\"" >> $PROSODY_CONFIG_OLD
echo -e " authentication = \"internal_plain\"\n" >> $PROSODY_CONFIG_OLD
if ! grep -q "admins = { }" $PROSODY_CONFIG_OLD; then
echo -e "admins = { \"$JICOFO_AUTH_USER@$JICOFO_AUTH_DOMAIN\" }\n" >> $PROSODY_CONFIG_OLD
else
sed -i "s/admins = { }/admins = { \"$JICOFO_AUTH_USER@$JICOFO_AUTH_DOMAIN\" }\n/g" $PROSODY_CONFIG_OLD
fi
echo -e "Component \"focus.$JVB_HOSTNAME\"" >> $PROSODY_CONFIG_OLD
echo -e " component_secret=\"$JICOFO_SECRET\"\n" >> $PROSODY_CONFIG_OLD
PROSODY_CREATE_JICOFO_USER="true"
fi
if [ "$PROSODY_CREATE_JICOFO_USER" = "true" ]; then
# create 'focus@auth.domain' prosody user
@@ -139,9 +118,36 @@ case "$1" in
"/O=$DOMAIN/OU=$HOST/CN=$JVB_HOSTNAME/emailAddress=webmaster@$HOST.$DOMAIN" \
-keyout /var/lib/prosody/$JVB_HOSTNAME.key \
-out /var/lib/prosody/$JVB_HOSTNAME.crt
ln -sf /var/lib/prosody/$JVB_HOSTNAME.key /etc/prosody/certs/$JVB_HOSTNAME.key
ln -sf /var/lib/prosody/$JVB_HOSTNAME.crt /etc/prosody/certs/$JVB_HOSTNAME.crt
fi
if [ ! -f /var/lib/prosody/$JICOFO_AUTH_DOMAIN.crt ]; then
HOST="$( (hostname -s; echo localhost) | head -n 1)"
DOMAIN="$( (hostname -d; echo localdomain) | head -n 1)"
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 -subj \
"/O=$DOMAIN/OU=$HOST/CN=$JICOFO_AUTH_DOMAIN/emailAddress=webmaster@$HOST.$DOMAIN" \
-keyout /var/lib/prosody/$JICOFO_AUTH_DOMAIN.key \
-out /var/lib/prosody/$JICOFO_AUTH_DOMAIN.crt
AUTH_KEY_FILE="/etc/prosody/certs/$JICOFO_AUTH_DOMAIN.key"
AUTH_CRT_FILE="/etc/prosody/certs/$JICOFO_AUTH_DOMAIN.crt"
ln -sf /var/lib/prosody/$JICOFO_AUTH_DOMAIN.key $AUTH_KEY_FILE
ln -sf /var/lib/prosody/$JICOFO_AUTH_DOMAIN.crt $AUTH_CRT_FILE
ln -sf /var/lib/prosody/$JICOFO_AUTH_DOMAIN.crt /usr/local/share/ca-certificates/$JICOFO_AUTH_DOMAIN.crt
update-ca-certificates
# don't fail on systems with custom config ($PROSODY_HOST_CONFIG is missing)
if [ -f $PROSODY_HOST_CONFIG ]; then
# now let's add the ssl cert for the auth. domain (we use # as a sed delimiter cause filepaths are confused with default / delimiter)
sed -i "s#VirtualHost \"$JICOFO_AUTH_DOMAIN\"#VirtualHost \"$JICOFO_AUTH_DOMAIN\"\n ssl = {\n key = \"$AUTH_KEY_FILE\";\n certificate = \"$AUTH_CRT_FILE\";\n \}#g" $PROSODY_HOST_CONFIG
fi
# trigger a restart
PROSODY_CONFIG_PRESENT="false"
fi
ln -sf /var/lib/prosody/$JVB_HOSTNAME.key /etc/prosody/certs/$JVB_HOSTNAME.key
ln -sf /var/lib/prosody/$JVB_HOSTNAME.crt /etc/prosody/certs/$JVB_HOSTNAME.crt
if [ "$PROSODY_CONFIG_PRESENT" = "false" ]; then
invoke-rc.d prosody restart

View File

@@ -48,7 +48,9 @@ case "$1" in
db_stop
if [ -f "$PROSODY_HOST_CONFIG" ] ; then
if grep -q "plugin_paths" "$PROSODY_HOST_CONFIG"; then
# search for --plugin_paths, if this is not enabled this is the
# first time we install tokens package and needs a config change
if grep -q "\-\-plugin_paths" "$PROSODY_HOST_CONFIG"; then
# enable tokens in prosody host config
sed -i 's/--plugin_paths/plugin_paths/g' $PROSODY_HOST_CONFIG
sed -i 's/authentication = "anonymous"/authentication = "token"/g' $PROSODY_HOST_CONFIG
@@ -62,6 +64,11 @@ case "$1" in
echo "Failed to install luajwtjitsi - try installing it manually"
fi
# Install basexx
if ! luarocks install basexx; then
echo "Failed to install basexx - try installing it manually"
fi
if [ -x "/etc/init.d/prosody" ]; then
invoke-rc.d prosody restart
fi
@@ -70,8 +77,6 @@ case "$1" in
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"
else
echo "Failed apply auto-config to $PROSODY_HOST_CONFIG which most likely comes from not supported version of jitsi-meet"
fi
else
echo "Prosody config not found at $PROSODY_HOST_CONFIG - unable to auto-configure token authentication"

View File

@@ -3,7 +3,7 @@ Index: jitsi-meet/index.html
===================================================================
--- jitsi-meet.orig/index.html
+++ jitsi-meet/index.html
@@ -10,14 +10,14 @@
@@ -10,13 +10,13 @@
<meta itemprop="description" content="Join a WebRTC video conference powered by the Jitsi Videobridge"/>
<meta itemprop="image" content="/images/jitsilogo.png"/>
<script src="https://api.callstats.io/static/callstats.min.js"></script>
@@ -19,4 +19,4 @@ Index: jitsi-meet/index.html
+ <script src="libs/jquery-ui.min.js"></script>
<script src="libs/tooltip.js?v=1"></script><!-- bootstrap tooltip lib -->
<script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib -->
<script src="libs/toastr.js?v=1"></script><!-- notifications lib -->
- <script src="libs/toastr.js?v=1"></script><!-- notifications lib -->

View File

@@ -9,54 +9,56 @@ To embed Jitsi Meet in your application you need to add the Jitsi Meet API libra
```javascript
<script src="https://meet.jit.si/external_api.js"></script>
```
## API
### `api = new JitsiMeetExternalAPI(domain, room, [width], [height], [htmlElement], [configOverwite], [interfaceConfigOverwrite], [noSsl], [jwt])`
### `api = new JitsiMeetExternalAPI(domain, options)`
The next step for embedding Jitsi Meet is to create the Jitsi Meet API object.
Its constructor gets a number of options:
* **domain**: domain used to build the conference URL, "meet.jit.si" for
example.
* **room**: name of the room to join.
* **width**: (optional) width for the iframe which will be created.
* **height**: (optional) height for the iframe which will be created.
* **htmlElement**: (optional) HTL DOM Element where the iframe will be added as
a child.
* **configOverwite**: (optional) JS object with overrides for options defined in
[config.js].
* **interfaceConfigOverwrite**: (optional) JS object with overrides for options
defined in [interface_config.js].
* **noSsl**: (optional, defaults to true) Boolean indicating if the server
should be contacted using HTTP or HTTPS.
* **jwt**: (optional) [JWT](https://jwt.io/) token.
* **options**: object with properties - the optional arguments:
* **roomName**: (optional) name of the room to join.
* **width**: (optional) width for the iframe which will be created. If a number is specified it's treated as pixel units. If a string is specified the format is number followed by 'px', 'em', 'pt' or '%'.
* **height**: (optional) height for the iframe which will be created. If a number is specified it's treated as pixel units. If a string is specified the format is number followed by 'px', 'em', 'pt' or '%'.
* **parentNode**: (optional) HTML DOM Element where the iframe will be added as a child.
* **configOverwrite**: (optional) JS object with overrides for options defined in [config.js].
* **interfaceConfigOverwrite**: (optional) JS object with overrides for options defined in [interface_config.js].
* **noSSL**: (optional, defaults to true) Boolean indicating if the server should be contacted using HTTP or HTTPS.
* **jwt**: (optional) [JWT](https://jwt.io/) token.
Example:
```javascript
var domain = "meet.jit.si";
var room = "JitsiMeetAPIExample";
var width = 700;
var height = 700;
var htmlElement = document.querySelector('#meet');
var api = new JitsiMeetExternalAPI(domain, room, width, height, htmlElement);
var options = {
roomName: "JitsiMeetAPIExample",
width: 700,
height: 700,
parentNode: document.querySelector('#meet')
}
var api = new JitsiMeetExternalAPI(domain, options);
```
You can overwrite options set in [config.js] and [interface_config.js].
For example, to enable the filmstrip-only interface mode, you can use:
```javascript
var interfaceConfigOverwrite = {filmStripOnly: true};
var api = new JitsiMeetExternalAPI(domain, room, width, height, undefined, undefined, interfaceConfigOverwrite);
var options = {
interfaceConfigOverwrite: {filmStripOnly: true}
};
var api = new JitsiMeetExternalAPI(domain, options);
```
You can also pass a jwt token to Jitsi Meet:
```javascript
var jwt = "<jwt_token>";
var noSsl = false;
var api = new JitsiMeetExternalAPI(domain, room, width, height, htmlElement, configOverwrite, interfaceConfigOverwrite, noSsl, jwt);
var options = {
jwt: "<jwt_token>",
noSsl: false
};
var api = new JitsiMeetExternalAPI(domain, options);
```
### Controlling the embedded Jitsi Meet Conference
@@ -139,6 +141,20 @@ The `listener` parameter is a Function object with one argument that will be not
The following events are currently supported:
* **audioAvailabilityChanged** - event notifications about audio availability status changes. The listener will receive an object with the following structure:
```javascript
{
"available": available // new available status - boolean
}
```
* **audioMuteStatusChanged** - event notifications about audio mute status changes. The listener will receive an object with the following structure:
```javascript
{
"muted": muted // new muted status - boolean
}
```
* **incomingMessage** - Event notifications about incoming
messages. The listener will receive an object with the following structure:
```javascript
@@ -194,6 +210,20 @@ changes. The listener will receive an object with the following structure:
}
```
* **videoAvailabilityChanged** - event notifications about video availability status changes. The listener will receive an object with the following structure:
```javascript
{
"available": available // new available status - boolean
}
```
* **videoMuteStatusChanged** - event notifications about video mute status changes. The listener will receive an object with the following structure:
```javascript
{
"muted": muted // new muted status - boolean
}
```
* **readyToClose** - event notification fired when Jitsi Meet is ready to be closed (hangup operations are completed).
You can also add multiple event listeners by using `addEventListeners`.
@@ -234,6 +264,39 @@ You can get the number of participants in the conference with the following API
var numberOfParticipants = api.getNumberOfParticipants();
```
You can get the iframe HTML element where Jitsi Meet is loaded with the following API function:
```javascript
var iframe = api.getIFrame();
```
You can check whether the audio is muted with the following API function:
```javascript
isAudioMuted().then(function(muted) {
...
});
```
You can check whether the video is muted with the following API function:
```javascript
isVideoMuted().then(function(muted) {
...
});
```
You can check whether the audio is available with the following API function:
```javascript
isAudioAvailable().then(function(available) {
...
});
```
You can check whether the video is available with the following API function:
```javascript
isVideoAvailable().then(function(available) {
...
});
```
You can remove the embedded Jitsi Meet Conference with the following API function:
```javascript
api.dispose()

5
doc/cloud-api.md Normal file
View File

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

147
doc/cloud-api.swagger Normal file
View File

@@ -0,0 +1,147 @@
swagger: "2.0"
info:
description: "Documents the REST calls used by Jitsi Meet to integrate with other services"
version: "1.0.0"
title: "Swagger Video"
termsOfService: "https://jitsi.org/CloudAPITOS/"
contact:
email: "team@jitsi.org"
host: "jitsi-api.jitsi.org"
basePath: "/"
tags:
- name: "conferenceMapper"
description: "Conference to ID Mapper"
externalDocs:
description: "Conference API Details"
url: "https://jitsi.org/CloudAPI"
- name: "phoneNumberList"
description: "List of dial-in numbers"
schemes:
- "https"
paths:
/conferenceMapper:
get:
tags:
- "conferenceMapper"
summary: "Create or retrieve conference ID mapping"
description: "When called with a conference, creates a new ID and both stores and returns the result. When called with an ID, returns the mapping if previously created."
operationId: "GETconferenceMapper"
consumes:
- "application/json"
produces:
- "application/json"
parameters:
- in: "query"
name: "conference"
type: "string"
format: "JID"
description: "Full JID (room@conference.server.domain) for the conference to create or return existing conference mapping. Used preferentially over all other input parameters (search by conference)"
- in: "query"
name: "id"
type: "number"
description: "ID to search for existing conference mapping. Only used when provided alone (search by ID)"
responses:
200:
description: "mapping search performed"
schema:
$ref: "#/definitions/ConferenceMapperDetails"
405:
description: "Invalid input"
post:
tags:
- "conferenceMapper"
summary: "Create or retrieve conference ID mapping"
description: "When called with a conference, creates a new ID and both stores and returns the result. When called with an ID, returns the mapping if previously created."
operationId: "POSTconferenceMapper"
consumes:
- "application/json"
produces:
- "application/json"
parameters:
- in: "body"
name: "body"
description: "Conference Mapper Request"
required: true
schema:
$ref: "#/definitions/ConferenceMapperRequest"
responses:
200:
description: "mapping search performed"
schema:
$ref: "#/definitions/ConferenceMapperDetails"
405:
description: "Invalid input"
/phoneNumberList:
get:
tags:
- "phoneNumberList"
summary: "Returns a list phone numbers by country"
description: "Used to populate the Share The Link section of jitsi-meet"
operationId: "phoneNumberList"
produces:
- "application/json"
responses:
200:
description: "successful operation"
schema:
$ref: "#/definitions/PhoneNumberList"
securityDefinitions:
token:
type: "apiKey"
name: "token"
in: "query"
Bearer:
type: "apiKey"
name: "Authorization"
in: "header"
definitions:
ConferenceMapperRequest:
description: "Request to create or find a conference mapping"
type: "object"
properties:
id:
type: "number"
description: "ID to search for existing conference mapping. Only used when provided alone (search by ID)"
conference:
type: "string"
format: "JID"
description: "Full JID (room@conference.server.domain) for the conference to create or return existing conference mapping. Used preferentially over all other input parameters (search by conference)"
room:
type: "string"
description: "Room part of the conference. Required if 'conference' is not provided. Used to generate a 'conference' value (search by conference)"
domain:
type: "string"
description: "Domain part of the conference. Used if 'conference' is not provided. Defaults to domain of the API endpoint. Used to generate a 'conference' value (search by conference)"
ConferenceMapperDetails:
description: "Conference mapping between conference JID and numeric ID"
type: "object"
properties:
id:
type: "number"
description: "Unique ID mapped to conference"
conference:
type: "string"
format: "JID"
description: "Full JID for the conference OR boolean false if no conference was found (search by ID)"
PhoneNumberList:
type: "object"
properties:
numbersEnabled:
type: "boolean"
description: "Control flag for Jitsi Meet user interface. Must be set to true for Jitsi Meet to display phone-in UI elements"
numbers:
type: "object"
description: "Keys are Country Names, each value is an array of phone numbers"
additionalProperties:
type: "array"
items:
type: "string"
format: "phone"
externalDocs:
description: "Find out more about the Jitsi Cloud API"
url: "https://jitsi.org/CloudAPI"

View File

@@ -76,7 +76,7 @@
projects. For example:
* The instance of lib-jitsi-meet's `JitsiConnection` type should be named
`connection` or `jitsiConnection` in jitsi-meet-react, not `client`.
`connection` or `jitsiConnection` in jitsi-meet, not `client`.
* The class `ReducerRegistry` should be defined in ReducerRegistry.js and its
imports in other files should use the same name. Don't define the class

View File

@@ -26,6 +26,7 @@ VirtualHost "jitmeet.example.com"
c2s_require_encryption = false
Component "conference.jitmeet.example.com" "muc"
storage = "null"
--modules_enabled = { "token_verification" }
admins = { "focusUser@auth.jitmeet.example.com" }

View File

@@ -7,16 +7,17 @@
<script src="https://meet.jit.si/external_api.js"></script>
<script>
var domain = "meet.jit.si";
var room = "JitsiMeetAPIExample";
var width = 700;
var height = 180;
var htmlElement = undefined;
var configOverwrite = {};
var interfaceConfigOverwrite = {
filmStripOnly: true
};
var api = new JitsiMeetExternalAPI(domain, room, width, height,
htmlElement, configOverwrite, interfaceConfigOverwrite);
var options = {
roomName: "JitsiMeetAPIExample",
width: 700,
height: 180,
parent: undefined,
configOverwrite: {},
interfaceConfigOverwrite: {
filmStripOnly: true
}
}
var api = new JitsiMeetExternalAPI(domain, options);
</script>
</body>
</html>

View File

@@ -238,23 +238,4 @@ You are now all set and ready to have your first meet by going to http://jitsi.e
## Enabling recording
Currently recording is only supported for linux-64 and macos. To enable it, add
the following properties to sip-communicator.properties:
```
org.jitsi.videobridge.ENABLE_MEDIA_RECORDING=true
org.jitsi.videobridge.MEDIA_RECORDING_PATH=/path/to/recordings/dir
org.jitsi.videobridge.MEDIA_RECORDING_TOKEN=secret
```
where /path/to/recordings/dir is the path to a pre-existing directory where recordings
will be stored (needs to be writeable by the user running jitsi-videobridge),
and "secret" is a string which will be used for authentication.
Then, edit the Jitsi-Meet config.js file and set:
```
enableRecording: true
```
Restart jitsi-videobridge and start a new conference (making sure that the page
is reloaded with the new config.js) -- the organizer of the conference should
now have a "recording" button in the floating menu, near the "mute" button.
[Jibri](https://github.com/jitsi/jibri)is a set of tools for recording and/or streaming a Jitsi Meet conference.

View File

@@ -1,14 +1,13 @@
# Jitsi Meet mobile apps
# Jitsi Meet apps for Android and iOS
Jitsi Meet can also be built as a standalone mobile application for
iOS and Android. It uses the [React Native] framework.
Jitsi Meet can also be built as a standalone app for Android or iOS. It uses the
[React Native] framework.
First make sure the [React Native dependencies] are installed.
**NOTE**: This document assumes the app is being built on a macOS system.
**NOTE**: This document assumes the app is being built on a macOS system.
**NOTE**: The app must be built for an actual device since the simulators don't
work properly with the native plugins we require.
**NOTE**: Node 6.X and npm 3.X are recommended for building.
## iOS
@@ -24,6 +23,21 @@ work properly with the native plugins we require.
You may need to add ```--unsafe-perm=true``` if you are running on [Mac OS 10.11 or greater](https://github.com/phonegap/ios-deploy#os-x-1011-el-capitan-or-greater).
- Install main dependencies:
```bash
npm install
```
- Install the required pods (CocoaPods must be installled first, it can
be done with Homebrew: `brew install cocoapods`)
```bash
cd ios
pod install
cd ..
```
2. Build the app
There are 2 ways to build the app: using the CLI or using Xcode.
@@ -43,8 +57,8 @@ work properly with the native plugins we require.
Using Xcode
- Open **ios/jitsi-meet-react.xcworkspace** in Xcode. Make sure it's the
workspace file!
- Open **ios/jitsi-meet.xcworkspace** in Xcode. Make sure it's the workspace
file!
- Select your device from the top bar and hit the "play" button.
@@ -78,17 +92,15 @@ build environment. Make sure you follow it closely.
It will be launched on the connected Android device.
## Debugging
The official documentation on [debugging] is quite extensive, it is the
The official documentation on [debugging] is quite extensive and specifies the
preferred method for debugging.
**NOTE**: When using Chrome Developer Tools for debugging the JavaScript code
is being interpreted by Chrome's V8 engine, instead of JSCore which
React Native uses. It's important to keep this in mind due to potential
differences in supported JavaScript features.
**NOTE**: When using Chrome Developer Tools for debugging the JavaScript source
code is being interpreted by Chrome's V8 engine, instead of JSCore which React
Native uses. It's important to keep this in mind due to potential differences in
supported JavaScript features.
[Android Studio]: https://developer.android.com/studio/index.html
[debugging]: https://facebook.github.io/react-native/docs/debugging.html

View File

@@ -22,6 +22,8 @@ apt-get update
### Install Jitsi Meet
Note : Something to consider before installation is how you're planning to serve Jitsi Meet. The installer will check if Nginx or Apache is present (with this order) and configure a virtualhost within the web server it finds to serve Jitsi Meet. If none of the above is found it then configures itself to be served via jetty. So if for example you are planning on deploying Jitsi Meet with a web server, you have to make sure to install the server **before** installing jitsi-meet.
```sh
apt-get -y install jitsi-meet
```
@@ -30,6 +32,25 @@ During the installation, you will be asked to enter the hostname of the Jitsi Me
This hostname (or IP address) will be used for virtualhost configuration inside the Jitsi Meet and also, you and your correspondents will be using it to access the web conferences.
### Generate a Let's Encrypt certificate
Simply run the following in your shell
```sh
/usr/share/jitsi-meet/scripts/install-letsencrypt-cert.sh
```
#### Advanced configuration
If installation is on a machine behind NAT further configuration of jitsi-videobridge is needed in order for it to be accessible.
Provided that all required ports are routed (forwarded) to the machine that it runs on. By default these ports are (TCP/443 or TCP/4443 and UDP 10000).
The following extra lines need to be added the file `/etc/jitsi/videobridge/sip-communicator.properties`:
```
org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS=<Local.IP.Address>
org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS=<Public.IP.Address>
```
See [the documenation of ice4j](https://github.com/jitsi/ice4j/blob/master/doc/configuration.md)
for details.
### Open a conference
Launch a web browser (Chrome, Chromium or latest Opera) and enter in the URL bar the hostname (or IP address) you used in the previous step.
@@ -63,7 +84,7 @@ Enjoy!
## Uninstall
```sh
apt-get purge jigasi jitsi-meet jicofo jitsi-videobridge
apt-get purge jigasi jitsi-meet jitsi-meet-web-config jitsi-meet-web jicofo jitsi-videobridge
```
Sometimes the following packages will fail to uninstall properly:

15
doc/turn.md Normal file
View File

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

3205
flow-typed/npm/lodash_v4.x.x.js vendored Normal file

File diff suppressed because it is too large Load Diff

34
flow-typed/npm/prop-types_v15.x.x.js vendored Normal file
View File

@@ -0,0 +1,34 @@
// flow-typed signature: 3eaa1f24c7397b78a7481992d2cddcb2
// flow-typed version: a1a20d4928/prop-types_v15.x.x/flow_>=v0.41.x
type $npm$propTypes$ReactPropsCheckType = (
props: any,
propName: string,
componentName: string,
href?: string) => ?Error;
declare module 'prop-types' {
declare var array: React$PropType$Primitive<Array<any>>;
declare var bool: React$PropType$Primitive<boolean>;
declare var func: React$PropType$Primitive<Function>;
declare var number: React$PropType$Primitive<number>;
declare var object: React$PropType$Primitive<Object>;
declare var string: React$PropType$Primitive<string>;
declare var any: React$PropType$Primitive<any>;
declare var arrayOf: React$PropType$ArrayOf;
declare var element: React$PropType$Primitive<any>; /* TODO */
declare var instanceOf: React$PropType$InstanceOf;
declare var node: React$PropType$Primitive<any>; /* TODO */
declare var objectOf: React$PropType$ObjectOf;
declare var oneOf: React$PropType$OneOf;
declare var oneOfType: React$PropType$OneOfType;
declare var shape: React$PropType$Shape;
declare function checkPropTypes<V>(
propTypes: $Subtype<{[_: $Keys<V>]: $npm$propTypes$ReactPropsCheckType}>,
values: V,
location: string,
componentName: string,
getStack: ?(() => ?string)
) : void;
}

View File

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

View File

@@ -1,10 +1,12 @@
// flow-typed signature: 0ed284c5a2e97a9e3c0e87af3dedc09d
// flow-typed version: bdf1e66252/react-redux_v5.x.x/flow_>=v0.30.x
// flow-typed signature: 4e93c65cedbfbf7f1ab3fe4e800943d3
// flow-typed version: 9092387fd2/react-redux_v5.x.x/flow_>=v0.53.x <=v0.53.x
import type { Dispatch, Store } from 'redux'
// flow-typed signature: 8db7b853f57c51094bf0ab8b2650fd9c
// flow-typed version: ab8db5f14d/react-redux_v5.x.x/flow_>=v0.30.x
declare module 'react-redux' {
import type { Dispatch, Store } from "redux";
declare module "react-redux" {
/*
S = State
@@ -15,30 +17,47 @@ declare module 'react-redux' {
*/
declare type MapStateToProps<S, OP: Object, SP: Object> = (state: S, ownProps: OP) => SP | MapStateToProps<S, OP, SP>;
declare type MapStateToProps<S, OP: Object, SP: Object> = (
state: S,
ownProps: OP
) => ((state: S, ownProps: OP) => SP) | SP;
declare type MapDispatchToProps<A, OP: Object, DP: Object> = ((dispatch: Dispatch<A>, ownProps: OP) => DP) | DP;
declare type MapDispatchToProps<A, OP: Object, DP: Object> =
| ((dispatch: Dispatch<A>, ownProps: OP) => DP)
| DP;
declare type MergeProps<SP, DP: Object, OP: Object, P: Object> = (stateProps: SP, dispatchProps: DP, ownProps: OP) => P;
declare type MergeProps<SP, DP: Object, OP: Object, P: Object> = (
stateProps: SP,
dispatchProps: DP,
ownProps: OP
) => P;
declare type StatelessComponent<P> = (props: P) => ?React$Element<any>;
declare type Context = { store: Store<*, *> };
declare class ConnectedComponent<OP, P, Def, St> extends React$Component<void, OP, void> {
static WrappedComponent: Class<React$Component<Def, P, St>>;
getWrappedInstance(): React$Component<Def, P, St>;
static defaultProps: void;
props: OP;
state: void;
declare class ConnectedComponent<OP, P> extends React$Component<OP> {
static WrappedComponent: Class<React$Component<P>>,
getWrappedInstance(): React$Component<P>,
props: OP,
state: void
}
declare type ConnectedComponentClass<OP, P, Def, St> = Class<ConnectedComponent<OP, P, Def, St>>;
declare type ConnectedComponentClass<OP, P> = Class<
ConnectedComponent<OP, P>
>;
declare type Connector<OP, P> = {
(component: StatelessComponent<P>): ConnectedComponentClass<OP, P, void, void>;
<Def, St>(component: Class<React$Component<Def, P, St>>): ConnectedComponentClass<OP, P, Def, St>;
};
declare type Connector<OP, P> = (
component: React$ComponentType<P>
) => ConnectedComponentClass<OP, P>;
declare class Provider<S, A> extends React$Component<void, { store: Store<S, A>, children?: any }, void> { }
declare class Provider<S, A> extends React$Component<{
store: Store<S, A>,
children?: any
}> {}
declare function createProvider(
storeKey?: string,
subKey?: string
): Provider<*, *>;
declare type ConnectOptions = {
pure?: boolean,
@@ -81,9 +100,15 @@ declare module 'react-redux' {
declare function connect<S, A, OP, SP, DP, P>(
mapStateToProps: MapStateToProps<S, OP, SP>,
mapDispatchToProps: MapDispatchToProps<A, OP, DP>,
mapDispatchToProps: Null,
mergeProps: MergeProps<SP, DP, OP, P>,
options?: ConnectOptions
): Connector<OP, P>;
declare function connect<S, A, OP, SP, DP, P>(
mapStateToProps: MapStateToProps<S, OP, SP>,
mapDispatchToProps: MapDispatchToProps<A, OP, DP>,
mergeProps: MergeProps<SP, DP, OP, P>,
options?: ConnectOptions
): Connector<OP, P>;
}

View File

@@ -1,5 +1,5 @@
// flow-typed signature: ba132c96664f1a05288f3eb2272a3c35
// flow-typed version: c4bbd91cfc/redux_v3.x.x/flow_>=v0.33.x
// flow-typed signature: 33b83b6284653250e74578cf4dbe6124
// flow-typed version: e282e4128f/redux_v3.x.x/flow_>=v0.33.x
declare module 'redux' {
@@ -7,50 +7,103 @@ declare module 'redux' {
S = State
A = Action
D = Dispatch
*/
declare type Dispatch<A: { type: $Subtype<string> }> = (action: A) => A;
declare export type DispatchAPI<A> = (action: A) => A;
declare export type Dispatch<A: { type: $Subtype<string> }> = DispatchAPI<A>;
declare type MiddlewareAPI<S, A> = {
dispatch: Dispatch<A>;
declare export type MiddlewareAPI<S, A, D = Dispatch<A>> = {
dispatch: D;
getState(): S;
};
declare type Store<S, A> = {
declare export type Store<S, A, D = Dispatch<A>> = {
// rewrite MiddlewareAPI members in order to get nicer error messages (intersections produce long messages)
dispatch: Dispatch<A>;
dispatch: D;
getState(): S;
subscribe(listener: () => void): () => void;
replaceReducer(nextReducer: Reducer<S, A>): void
};
declare type Reducer<S, A> = (state: S, action: A) => S;
declare export type Reducer<S, A> = (state: S, action: A) => S;
declare type Middleware<S, A> =
(api: MiddlewareAPI<S, A>) =>
(next: Dispatch<A>) => Dispatch<A>;
declare export type CombinedReducer<S, A> = (state: $Shape<S> & {} | void, action: A) => S;
declare type StoreCreator<S, A> = {
(reducer: Reducer<S, A>, enhancer?: StoreEnhancer<S, A>): Store<S, A>;
(reducer: Reducer<S, A>, preloadedState: S, enhancer?: StoreEnhancer<S, A>): Store<S, A>;
declare export type Middleware<S, A, D = Dispatch<A>> =
(api: MiddlewareAPI<S, A, D>) =>
(next: D) => D;
declare export type StoreCreator<S, A, D = Dispatch<A>> = {
(reducer: Reducer<S, A>, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
(reducer: Reducer<S, A>, preloadedState: S, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
};
declare type StoreEnhancer<S, A> = (next: StoreCreator<S, A>) => StoreCreator<S, A>;
declare export type StoreEnhancer<S, A, D = Dispatch<A>> = (next: StoreCreator<S, A, D>) => StoreCreator<S, A, D>;
declare function createStore<S, A>(reducer: Reducer<S, A>, enhancer?: StoreEnhancer<S, A>): Store<S, A>;
declare function createStore<S, A>(reducer: Reducer<S, A>, preloadedState: S, enhancer?: StoreEnhancer<S, A>): Store<S, A>;
declare export function createStore<S, A, D>(reducer: Reducer<S, A>, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
declare export function createStore<S, A, D>(reducer: Reducer<S, A>, preloadedState: S, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
declare function applyMiddleware<S, A>(...middlewares: Array<Middleware<S, A>>): StoreEnhancer<S, A>;
declare export function applyMiddleware<S, A, D>(...middlewares: Array<Middleware<S, A, D>>): StoreEnhancer<S, A, D>;
declare type ActionCreator<A, B> = (...args: Array<B>) => A;
declare type ActionCreators<K, A> = { [key: K]: ActionCreator<A, any> };
declare export type ActionCreator<A, B> = (...args: Array<B>) => A;
declare export type ActionCreators<K, A> = { [key: K]: ActionCreator<A, any> };
declare function bindActionCreators<A, C: ActionCreator<A, any>>(actionCreator: C, dispatch: Dispatch<A>): C;
declare function bindActionCreators<A, K, C: ActionCreators<K, A>>(actionCreators: C, dispatch: Dispatch<A>): C;
declare export function bindActionCreators<A, C: ActionCreator<A, any>, D: DispatchAPI<A>>(actionCreator: C, dispatch: D): C;
declare export function bindActionCreators<A, K, C: ActionCreators<K, A>, D: DispatchAPI<A>>(actionCreators: C, dispatch: D): C;
declare function combineReducers<O: Object, A>(reducers: O): Reducer<$ObjMap<O, <S>(r: Reducer<S, any>) => S>, A>;
declare export function combineReducers<O: Object, A>(reducers: O): CombinedReducer<$ObjMap<O, <S>(r: Reducer<S, any>) => S>, A>;
declare function compose<S, A>(...fns: Array<StoreEnhancer<S, A>>): Function;
declare export function compose<A, B>(ab: (a: A) => B): (a: A) => B
declare export function compose<A, B, C>(
bc: (b: B) => C,
ab: (a: A) => B
): (a: A) => C
declare export function compose<A, B, C, D>(
cd: (c: C) => D,
bc: (b: B) => C,
ab: (a: A) => B
): (a: A) => D
declare export function compose<A, B, C, D, E>(
de: (d: D) => E,
cd: (c: C) => D,
bc: (b: B) => C,
ab: (a: A) => B
): (a: A) => E
declare export function compose<A, B, C, D, E, F>(
ef: (e: E) => F,
de: (d: D) => E,
cd: (c: C) => D,
bc: (b: B) => C,
ab: (a: A) => B
): (a: A) => F
declare export function compose<A, B, C, D, E, F, G>(
fg: (f: F) => G,
ef: (e: E) => F,
de: (d: D) => E,
cd: (c: C) => D,
bc: (b: B) => C,
ab: (a: A) => B
): (a: A) => G
declare export function compose<A, B, C, D, E, F, G, H>(
gh: (g: G) => H,
fg: (f: F) => G,
ef: (e: E) => F,
de: (d: D) => E,
cd: (c: C) => D,
bc: (b: B) => C,
ab: (a: A) => B
): (a: A) => H
declare export function compose<A, B, C, D, E, F, G, H, I>(
hi: (h: H) => I,
gh: (g: G) => H,
fg: (f: F) => G,
ef: (e: E) => F,
de: (d: D) => E,
cd: (c: C) => D,
bc: (b: B) => C,
ab: (a: A) => B
): (a: A) => I
}

81
flow-typed/npm/uuid_v3.x.x.js vendored Normal file
View File

@@ -0,0 +1,81 @@
// flow-typed signature: 615e568e95029d58f116dd157e320137
// flow-typed version: 2b95c0dfc1/uuid_v3.x.x/flow_>=v0.32.x
declare module "uuid" {
declare class uuid {
static (
options?: {|
random?: number[],
rng?: () => number[] | Buffer
|},
buffer?: number[] | Buffer,
offset?: number
): string,
static v1(
options?: {|
node?: number[],
clockseq?: number,
msecs?: number | Date,
nsecs?: number
|},
buffer?: number[] | Buffer,
offset?: number
): string,
static v4(
options?: {|
random?: number[],
rng?: () => number[] | Buffer
|},
buffer?: number[] | Buffer,
offset?: number
): string
}
declare module.exports: Class<uuid>;
}
declare module "uuid/v1" {
declare class v1 {
static (
options?: {|
node?: number[],
clockseq?: number,
msecs?: number | Date,
nsecs?: number
|},
buffer?: number[] | Buffer,
offset?: number
): string
}
declare module.exports: Class<v1>;
}
declare module "uuid/v4" {
declare class v4 {
static (
options?: {|
random?: number[],
rng?: () => number[] | Buffer
|},
buffer?: number[] | Buffer,
offset?: number
): string
}
declare module.exports: Class<v4>;
}
declare module "uuid/v5" {
declare class v5 {
static (
name?: string | number[],
namespace?: string | number[],
buffer?: number[] | Buffer,
offset?: number
): string
}
declare module.exports: Class<v5>;
}

Binary file not shown.

View File

@@ -7,12 +7,12 @@
<font-face units-per-em="1024" ascent="1024" descent="0" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" d="" />
<glyph unicode="&#xe0cd;" glyph-name="phone" d="M282 564c62-120 162-220 282-282l94 94c12 12 30 16 44 10 48-16 100-24 152-24 24 0 42-18 42-42v-150c0-24-18-42-42-42-400 0-726 326-726 726 0 24 18 42 42 42h150c24 0 42-18 42-42 0-54 8-104 24-152 4-14 2-32-10-44z" />
<glyph unicode="&#xe145;" glyph-name="add" d="M810 470h-256v-256h-84v256h-256v84h256v256h84v-256h256v-84z" />
<glyph unicode="&#xe5d4;" glyph-name="thumb-menu" d="M512 342c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM512 598c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM512 682c-46 0-86 40-86 86s40 86 86 86 86-40 86-86-40-86-86-86z" />
<glyph unicode="&#xe603;" glyph-name="presentation" horiz-adv-x="1088" d="M952.495 1019.065h-818.689c-72.81 0-132.183-60.63-132.183-135.162v-750.719c0-74.473 59.372-135.101 132.183-135.101h818.686c72.936 0 132.314 60.625 132.314 135.101v750.722c0.003 74.532-59.378 135.159-132.311 135.159zM946.346 139.651h-806.14v737.822h806.015l0.126-737.822zM685.753 738.544h216.911v-566.758h-216.911v566.758zM428.672 610.002h216.911v-438.216h-216.911v438.216zM172.339 481.46h216.161v-309.677h-216.161v309.677z" />
<glyph unicode="&#xe613;" glyph-name="recDisable" horiz-adv-x="1140" d="M1123.444 1003.015c-23.593 26.481-64.131 28.989-90.74 5.395l-1008.269-893.436c-26.609-23.468-28.991-64.131-5.46-90.676 12.674-14.306 30.308-21.649 48.126-21.649 15.123 0 30.372 5.401 42.544 16.195l130.045 115.22c90.743-81.844 210.569-132.165 342.473-132.101 282.816 0.061 510.913 227.969 511.287 510.972 0.126 109.934-34.682 211.367-93.499 294.72l118.088 104.625c26.483 23.526 28.997 64.129 5.404 90.735zM944.422 513.818c0.128-200.922-161.896-363.201-362.509-362.952-87.56 0.123-167.573 31.151-230.061 82.569l331.277 293.509v-73.176c1.071-60.993 32.696-92.18 94.944-93.692 61.997 1.512 93.686 32.763 95.131 93.756v41.096h-72.227v-47.499c0.251-4.642-0.564-10.607-2.511-17.949-1.25-3.261-3.448-6.020-6.525-8.093-3.197-2.572-7.845-3.828-13.868-3.828-10.543 0.31-17.132 4.268-19.827 11.921-1.068 3.512-1.947 6.905-2.508 10.163-0.254 2.887-0.377 5.532-0.377 7.786v143.511l42.477 37.634c0.215-0.432 0.452-0.851 0.63-1.303 1.947-6.467 2.762-12.799 2.511-19.076v-36.772h72.227v30.121c-0.246 31.245-9.086 54.699-26.363 70.447l40.711 36.069c35.787-56.055 56.803-122.585 56.867-194.244zM239.795 395.47c-12.613 37.023-19.827 76.557-19.827 117.913-0.19 200.236 161.584 362.009 361.945 362.135 56.853 0 110.313-13.302 158.133-36.398l117.846 104.421c-79.444 50.952-173.758 80.817-275.292 80.948-283.377 0.181-511.354-227.729-511.789-511.675-0.126-79.567 18.636-154.679 51.137-221.882l117.848 104.538zM388.576 690.020h-97.514v-249.057l72.23 64.070v0.689h0.815l117.72 104.418c0 0.564 0.123 0.94 0.123 1.509 0.753 53.898-30.369 80.069-93.374 78.37zM405.959 625.517c1.942-2.767 3.074-6.469 3.323-11.112 0.312-4.452 0.438-9.6 0.438-15.246 0.251-10.916-0.689-19.83-2.949-26.985-2.952-7.594-10.983-11.357-24.159-11.357h-19.325v74.043h15.31c7.842 0 13.865-0.683 18.072-2.19 4.397-1.573 7.468-3.953 9.29-7.153z" />
<glyph unicode="&#xe614;" glyph-name="recEnable" horiz-adv-x="1142" d="M581.278 1025.708c284.857-0.19 514.807-230.517 514.427-514.997-0.378-285.047-230.073-514.553-514.869-514.615-284.541-0.062-515.311 230.517-514.933 514.422 0.439 285.936 230.009 515.439 515.375 515.19zM580.579 875.756c-201.764-0.123-364.666-163.032-364.478-364.663 0-202.018 162.524-364.735 364.478-364.984 202.018-0.316 365.174 163.030 365.048 365.423-0.252 201.767-163.156 364.35-365.048 364.224zM287.698 688.907h98.196c63.442 1.767 94.785-24.518 94.027-78.863 0.254-19.081-2.211-34.882-7.456-47.521-6.005-12.508-18.706-21.988-38.167-28.181v-0.819c28.373-6.259 43.031-23.573 43.981-51.946v-57.689c0-11.247 0.254-22.813 0.758-34.756 0.819-12.005 3.033-20.979 6.696-27.043h-71.846c-3.727 6.064-6.128 15.038-7.14 27.043-1.012 11.943-1.454 23.509-1.138 34.756v52.321c0 9.603-2.214 16.553-6.573 20.979-4.675 4.107-12.701 6.19-24.012 6.19h-14.599v-141.291h-72.73v326.82zM360.428 558.861h19.463c13.271 0 21.359 3.794 24.331 11.375 2.276 7.204 3.221 16.304 2.969 27.171 0 5.815-0.126 10.867-0.442 15.418-0.252 4.675-1.392 8.404-3.352 11.247-1.831 3.157-4.926 5.561-9.352 7.14-4.233 1.454-10.299 2.211-18.2 2.211h-15.418v-74.564zM498.372 688.907h162.082v-62.687h-89.35v-65.587h78.103v-62.685h-78.103v-73.11h92.822v-62.749h-165.557v326.818zM682.507 599.999c0.316 31.782 9.416 55.542 27.425 71.407 17.44 15.29 40.185 22.936 68.181 22.936 28.247 0 51.119-7.646 68.623-23 17.82-15.798 26.92-39.623 27.171-71.407v-30.333h-72.73v37.031c0.254 6.192-0.57 12.639-2.527 19.209-1.264 3.157-3.475 5.938-6.573 8.214-3.221 1.515-7.898 2.404-13.964 2.404-10.615-0.316-17.249-3.855-19.967-10.618-2.211-6.573-3.223-13.017-2.907-19.209v-161.956c0-2.273 0.126-4.865 0.38-7.772 0.568-3.411 1.454-6.824 2.527-10.233 2.717-7.775 9.352-11.756 19.967-12.007 6.067 0 10.744 1.261 13.964 3.791 3.098 2.15 5.309 4.867 6.573 8.216 1.96 7.33 2.782 13.33 2.527 18.007v47.837h72.73v-41.328c-1.451-61.547-33.364-93.015-95.794-94.469-62.685 1.454-94.53 32.922-95.607 94.343v148.937z" />
<glyph unicode="&#xe61a;" glyph-name="connection" horiz-adv-x="1444" d="M3.881 210.835h220.26v-210.835h-220.26v210.835zM308.817 414.143h220.27v-414.143h-220.27v414.143zM613.764 617.412h220.268v-617.412h-220.268v617.412zM918.685 820.715h220.265v-820.715h-220.265v820.715zM1223.629 1024h220.263v-1024h-220.263v1024z" />
<glyph unicode="&#xe61c;" glyph-name="dialpad" horiz-adv-x="1026" d="M74.418 881.299h239.304v-228.491h-239.304v228.491zM393.455 881.299h239.304v-228.491h-239.304v228.491zM712.494 881.299h239.263v-228.491h-239.263v228.491zM74.418 562.265h239.304v-228.555h-239.304v228.555zM393.455 562.265h239.304v-228.555h-239.304v228.555zM712.494 562.265h239.263v-228.555h-239.263v228.555zM74.418 243.166h239.304v-228.465h-239.304v228.465zM393.455 243.166h239.304v-228.465h-239.304v228.465zM712.494 243.166h239.263v-228.465h-239.263v228.465z" />
<glyph unicode="&#xe900;" glyph-name="connection-lost" horiz-adv-x="1414" d="M0 299.153h196.337v-187.951h-196.337v187.951zM271.842 480.372h196.337v-369.169h-196.337v369.169zM543.656 661.562h196.337v-550.36h-196.337v550.36zM815.47 842.766v-731.564h119.56c-14.589 33.025-23.125 71.503-23.232 111.943 0.132 86.42 38.697 163.851 99.656 216.468l0.348 403.153h-196.332zM1087.292 1024v-533.672c28.874 10.572 62.222 16.73 97.009 16.825 35.717-0.129 69.823-6.614 101.322-18.371l-1.999 535.218h-196.332zM1192.868 439.852c-0.009 0-0.020 0-0.031 0-122.247 0-221.351-98.447-221.372-219.896 0-0.007 0-0.014 0-0.021 0-121.467 99.111-219.935 221.372-219.935 0.011 0 0.021 0 0.032 0 122.248 0.014 221.345 98.477 221.345 219.935 0 0.007 0 0.013 0 0.020-0.021 121.441-99.11 219.883-221.345 219.897zM1194.706 372.607c87.601-0.006 158.614-69.787 158.614-155.866 0-0.006 0-0.012 0-0.019-0.022-86.062-71.026-155.822-158.614-155.828-87.588 0.006-158.593 69.766-158.615 155.826 0 0.007 0 0.014 0 0.020 0 86.079 71.013 155.86 158.613 155.866zM1286.795 355.682l48.348-52.528-236.375-217.567-48.348 52.528 236.375 217.567z" />
<glyph unicode="&#xe901;" glyph-name="avatar" d="M512 204c106 0 200 56 256 138-2 84-172 132-256 132-86 0-254-48-256-132 56-82 150-138 256-138zM512 810c-70 0-128-58-128-128s58-128 128-128 128 58 128 128-58 128-128 128zM512 938c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426z" />
<glyph unicode="&#xe902;" glyph-name="download" d="M726 470h-128v170h-172v-170h-128l214-214zM826 596c110-8 198-100 198-212 0-118-96-214-214-214h-554c-142 0-256 114-256 256 0 132 100 240 228 254 54 102 160 174 284 174 156 0 284-110 314-258z" />
<glyph unicode="&#xe903;" glyph-name="mic-camera-combined" d="M756.704 628.138l267.296 202.213v-635.075l-267.296 202.213v-191.923c0-12.085-11.296-21.863-25.216-21.863h-706.272c-13.92 0-25.216 9.777-25.216 21.863v612.25c0 12.085 11.296 21.863 25.216 21.863h706.272c13.92 0 25.216-9.777 25.216-21.863v-189.679zM371.338 376.228c47.817 0 86.529 40.232 86.529 89.811v184.835c0 49.651-38.713 89.883-86.529 89.883-47.788 0-86.515-40.232-86.515-89.883v-184.835c0-49.579 38.756-89.811 86.515-89.811v0zM356.754 314.070v-32.78h33.718v33.412c73.858 9.606 131.235 73.73 131.235 151.351v88.232h-30.636v-88.232c0-67.57-53.696-122.534-119.734-122.534-66.024 0-119.691 54.964-119.691 122.534v88.232h-30.636v-88.232c0-79.215 59.674-144.502 135.744-151.969v-0.014z" />
@@ -21,7 +21,7 @@
<glyph unicode="&#xe906;" glyph-name="chat" d="M854 342v512h-684v-598l86 86h598zM854 938c46 0 84-38 84-84v-512c0-46-38-86-84-86h-598l-170-170v768c0 46 38 84 84 84h684z" />
<glyph unicode="&#xe907;" glyph-name="edit" d="M884 724l-78-78-160 160 78 78c16 16 44 16 60 0l100-100c16-16 16-44 0-60zM128 288l472 472 160-160-472-472h-160v160z" />
<glyph unicode="&#xe908;" glyph-name="share-doc" d="M554 640h236l-236 234v-234zM682 426v86h-340v-86h340zM682 256v86h-340v-86h340zM598 938l256-256v-512c0-46-40-84-86-84h-512c-46 0-86 38-86 84l2 684c0 46 38 84 84 84h342z" />
<glyph unicode="&#xe909;" glyph-name="telephone" d="M854 362c24 0 42-18 42-42v-150c0-24-18-42-42-42-400 0-726 326-726 726 0 24 18 42 42 42h150c24 0 42-18 42-42 0-54 8-104 24-152 4-14 2-32-10-44l-94-94c62-122 162-220 282-282l94 94c12 12 30 14 44 10 48-16 98-24 152-24zM854 810v44h-44v-44h44zM768 896h128v-128h-86v-86h-42v214zM640 810v-128h-128v44h86v42h-86v128h128v-42h-86v-44h86zM726 896v-214h-44v214h44z" />
<glyph unicode="&#xe909;" glyph-name="ninja" d="M330.667 469.333c-0.427 14.933 6.4 29.44 17.92 39.253 32-6.827 61.867-20.053 88.747-39.253 0-29.013-23.893-52.907-53.333-52.907s-52.907 23.467-53.333 52.907zM586.667 469.333c26.88 18.773 56.747 32 88.747 38.827 11.52-9.813 18.347-24.32 17.92-38.827 0-29.867-23.893-53.76-53.333-53.76s-53.333 23.893-53.333 53.76v0zM512 640c-118.187 1.707-234.667-27.733-338.347-85.333l-2.987-42.667c0-52.48 12.373-104.107 35.84-151.040 101.12 15.36 203.093 23.040 305.493 23.040s204.373-7.68 305.493-23.040c23.467 46.933 35.84 98.56 35.84 151.040l-2.987 42.667c-103.68 57.6-220.16 87.040-338.347 85.333zM512 938.667c235.641 0 426.667-191.025 426.667-426.667s-191.025-426.667-426.667-426.667c-235.641 0-426.667 191.025-426.667 426.667s191.025 426.667 426.667 426.667z" />
<glyph unicode="&#xe90a;" glyph-name="star-full" d="M512 288l-264-160 70 300-232 202 306 26 120 282 120-282 306-26-232-202 70-300z" />
<glyph unicode="&#xe90b;" glyph-name="full-screen" d="M598 810h212v-212h-84v128h-128v84zM726 298v128h84v-212h-212v84h128zM214 598v212h212v-84h-128v-128h-84zM298 426v-128h128v-84h-212v212h84z" />
<glyph unicode="&#xe90c;" glyph-name="exit-full-screen" d="M682 682h128v-84h-212v212h84v-128zM598 214v212h212v-84h-128v-128h-84zM342 682v128h84v-212h-212v84h128zM214 342v84h212v-212h-84v128h-128z" />
@@ -46,4 +46,9 @@
<glyph unicode="&#xe91f;" glyph-name="menu-up" d="M512 682l256-256-60-60-196 196-196-196-60 60z" />
<glyph unicode="&#xe920;" glyph-name="menu-down" d="M708 658l60-60-256-256-256 256 60 60 196-196z" />
<glyph unicode="&#xe921;" glyph-name="switch-camera" d="M640 362l150 150-150 150v-108h-256v108l-150-150 150-150v108h256v-108zM854 854c46 0 84-40 84-86v-512c0-46-38-86-84-86h-684c-46 0-84 40-84 86v512c0 46 38 86 84 86h136l78 84h256l78-84h136z" />
<glyph unicode="&#xe922;" glyph-name="info" d="M512 938.667c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM554.667 298.667h-85.333v256h85.333v-256zM554.667 640h-85.333v85.333h85.333v-85.333z" />
<glyph unicode="&#xe923;" glyph-name="visibility" d="M512 640c70 0 128-58 128-128s-58-128-128-128-128 58-128 128 58 128 128 128zM512 298c118 0 214 96 214 214s-96 214-214 214-214-96-214-214 96-214 214-214zM512 832c214 0 396-132 470-320-74-188-256-320-470-320s-396 132-470 320c74 188 256 320 470 320z" />
<glyph unicode="&#xe924;" glyph-name="visibility-off" d="M506 640h6c70 0 128-58 128-128v-8zM322 606c-14-28-24-60-24-94 0-118 96-214 214-214 34 0 66 10 94 24l-66 66c-8-2-18-4-28-4-70 0-128 58-128 128 0 10 2 20 4 28zM86 842l54 54 756-756-54-54c-47.968 47.365-96.266 94.401-144 142-58-24-120-36-186-36-214 0-396 132-470 320 34 84 90 156 160 212-39.017 38.983-77.307 78.693-116 118zM512 726c-28 0-54-6-78-16l-92 92c52 20 110 30 170 30 214 0 394-132 468-320-32-80-82-148-146-202l-124 124c10 24 16 50 16 78 0 118-96 214-214 214z" />
<glyph unicode="&#xe925;" glyph-name="dialpad" d="M512 982c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM512 726c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM768 726c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM768 470c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM512 470c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM768 810c-46 0-86 40-86 86s40 86 86 86 86-40 86-86-40-86-86-86zM256 470c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM256 726c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM256 982c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM512 214c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86z" />
<glyph unicode="&#xe926;" glyph-name="gsm-bars-black" d="M896 1024c70.692 0 128-57.308 128-128v-768c0-70.692-57.308-128-128-128s-128 57.308-128 128v768c0 70.692 57.308 128 128 128zM512 768c70.692 0 128-57.308 128-128v-512c0-70.692-57.308-128-128-128s-128 57.308-128 128v512c0 70.692 57.308 128 128 128zM128 384v0c70.692 0 128-57.308 128-128v-128c0-70.692-57.308-128-128-128s-128 57.308-128 128v128c0 70.692 57.308 128 128 128v0z" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Binary file not shown.

1048
fonts/selection.json Normal file → Executable file

File diff suppressed because it is too large Load Diff

BIN
images/avatar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

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