Compare commits

...

196 Commits
2000 ... 2133

Author SHA1 Message Date
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
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
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
paweldomas
16d9ef5f1c [RN] export RTCIceCandidate
Required for P2P.
2017-04-23 13:54:12 -05:00
320 changed files with 13281 additions and 6097 deletions

View File

@@ -19,6 +19,7 @@
.*/node_modules/babel-core/.*
.*/node_modules/bower/.*
.*/node_modules/jsonlint/.*
.*/node_modules/promise/index.js.flow
.*/node_modules/styled-components/.*
[include]

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

@@ -16,6 +16,7 @@ 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.
app.js
modules/translation/translation.js
analytics.js

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,9 @@ 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/)
@@ -28,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

207
android/README.md Normal file
View File

@@ -0,0 +1,207 @@
# Jitsi Meet SDK for Android
This directory contains the source code of the Jitsi Meet app and the Jitsi Meet
SDK for Android.
## Jitsi Meet SDK
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();
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`.
#### getWelcomePageEnabled()
See JitsiMeetView.getWelcomePageEnabled.
#### loadURL(URL)
See JitsiMeetView.loadURL.
#### 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).
#### 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 the given URL and joins the room. If `null` is specified, the welcome page
is displayed instead.
#### 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` 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` HashMap contains an "error" key describing the error and a "url"
key with the conference URL.
#### onConferenceJoined
Called when a conference was joined.
The `data` HashMap contains a "url" key with the conference URL.
#### onConferenceLeft
Called when a conference was left.
The `data` HashMap contains a "url" key with the conference URL.
#### onConferenceWillJoin
Called before a conference is joined.
The `data` HashMap contains a "url" key with the conference URL.
#### onConferenceWillLeave
Called before a conference is left.
The `data` HashMap contains a "url" key with the conference URL.

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,41 @@
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
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId 'org.jitsi.meet'
minSdkVersion 16
targetSdkVersion 22
versionCode Integer.parseInt("${version}")
versionName "1.4.${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,36 @@
<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="16"
android:targetSdkVersion="23" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
<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:theme="@style/AppTheme">
<activity
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:name=".MainApplication"
android:theme="@style/AppTheme">
<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>
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>
</application>
</manifest>

View File

@@ -1,46 +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;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import android.os.Bundle;
public class MainActivity extends ReactActivity {
import org.jitsi.meet.sdk.JitsiMeetActivity;
/**
* 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 {
/**
* {@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.
*/
@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 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);
rootView.setBackgroundColor(0xFF111111);
return rootView;
}
};
}
/**
* 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";
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,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-alpha6'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
// in the individual module build.gradle files.
}
}
@@ -17,8 +19,30 @@ allprojects {
mavenLocal()
jcenter()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
// All of React Native (JS, Obj-C sources, Android binaries) is
// installed from npm.
url "$rootDir/../node_modules/react-native/android"
}
}
}
ext {
compileSdkVersion = 25
buildToolsVersion = "25.0.3"
minSdkVersion = 16
targetSdkVersion = 23
}
// 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')) {
android {
buildToolsVersion rootProject.ext.buildToolsVersion
}
}
}
}

View File

@@ -1,5 +1,6 @@
#Mon Jul 17 18:25:08 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-milestone-1-all.zip

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

@@ -0,0 +1,121 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
publishNonDefault true
}
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:23.0.1'
compile 'com.facebook.react:react-native:+'
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')
}
// 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)
}
}

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,21 @@
<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:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus"/>
<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,199 @@
/*
* 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;
/**
* Base Activity for applications integrating Jitsi Meet at a higher level. It
* contains all the required wiring between the <tt>JKConferenceView</tt> and
* the Activity lifecycle methods already implemented.
*
* In this activity we use a single <tt>JKConferenceView</tt> 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
* <tt>JKConferenceView</tt> 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);
/**
* 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#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 initializeView() {
view = new JitsiMeetView(this);
// In order to have the desired effect
// JitsiMeetView#setWelcomePageEnabled(boolean) must be invoked before
// JitsiMeetView#loadURL(URL).
view.setWelcomePageEnabled(welcomePageEnabled);
view.loadURL(null);
setContentView(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);
}
/**
* {@inheritDoc}
*/
@Override
protected void onActivityResult(
int requestCode,
int resultCode,
Intent data) {
if (requestCode == OVERLAY_PERMISSION_REQUEST_CODE
&& canRequestOverlayPermission()) {
if (Settings.canDrawOverlays(this)) {
initializeView();
}
}
}
/**
* {@inheritDoc}
*/
@Override
public void onBackPressed() {
if (!JitsiMeetView.onBackPressed()) {
// Invoke the default handler if it wasn't handled by React.
super.onBackPressed();
}
}
/**
* {@inheritDoc}
*/
@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;
}
initializeView();
}
/**
* {@inheritDoc}
*/
@Override
protected void onDestroy() {
super.onDestroy();
JitsiMeetView.onHostDestroy(this);
}
/**
* {@inheritDoc}
*/
@Override
public void onNewIntent(Intent intent) {
JitsiMeetView.onNewIntent(intent);
}
/**
* {@inheritDoc}
*/
@Override
protected void onPause() {
super.onPause();
JitsiMeetView.onHostPause(this);
}
/**
* {@inheritDoc}
*/
@Override
protected void onResume() {
super.onResume();
JitsiMeetView.onHostResume(this);
}
/**
*
* @see JitsiMeetView#setWelcomePageEnabled
*/
public void setWelcomePageEnabled(boolean welcomePageEnabled) {
if (view == null) {
this.welcomePageEnabled = welcomePageEnabled;
} else {
view.setWelcomePageEnabled(welcomePageEnabled);
}
}
}

View File

@@ -0,0 +1,276 @@
/*
* 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.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.common.LifecycleState;
import java.net.URL;
import java.util.Collections;
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>());
public static JitsiMeetView findViewByExternalAPIScope(
String externalAPIScope) {
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 <tt>ReactRootView</tt> instances will be tied to the one and
* only <tt>ReactInstanceManager</tt>.
*
* @param application - <tt>Application</tt> instance which is running.
*/
private static void initReactInstanceManager(Application application) {
reactInstanceManager
= ReactInstanceManager.builder()
.setApplication(application)
.setBundleAssetName("index.android.bundle")
.setJSMainModuleName("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.rnimmersive.RNImmersivePackage())
.addPackage(new org.jitsi.meet.sdk.audiomode.AudioModePackage())
.addPackage(
new org.jitsi.meet.sdk.externalapi.ExternalAPIPackage())
.addPackage(new org.jitsi.meet.sdk.proximity.ProximityPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
}
/**
* Activity lifecycle method which should be called from
* <tt>Activity.onBackPressed</tt> so we can do the required internal
* processing.
*
* @return - true if the back-press was processed, false otherwise. In case
* false is returned the application should call the parent's
* implementation.
*/
public static boolean onBackPressed() {
if (reactInstanceManager != null) {
reactInstanceManager.onBackPressed();
return true;
} else {
return false;
}
}
/**
* Activity lifecycle method which should be called from
* <tt>Activity.onDestroy</tt> so we can do the required internal
* processing.
*
* @param activity - <tt>Activity</tt> being destroyed.
*/
public static void onHostDestroy(Activity activity) {
if (reactInstanceManager != null) {
reactInstanceManager.onHostDestroy(activity);
}
}
/**
* Activity lifecycle method which should be called from
* <tt>Activity.onPause</tt> so we can do the required internal processing.
*
* @param activity - <tt>Activity</tt> being paused.
*/
public static void onHostPause(Activity activity) {
if (reactInstanceManager != null) {
reactInstanceManager.onHostPause(activity);
}
}
/**
* Activity lifecycle method which should be called from
* <tt>Activity.onResume</tt> so we can do the required internal processing.
*
* @param activity - <tt>Activity</tt> being resumed.
*/
public static void onHostResume(Activity activity) {
if (reactInstanceManager != null) {
reactInstanceManager.onHostResume(activity, null);
}
}
/**
* Activity lifecycle method which should be called from
* <tt>Activity.onNewIntent</tt> 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 - <tt>Intent</tt> instance which was received.
*/
public static void onNewIntent(Intent intent) {
if (reactInstanceManager != null) {
reactInstanceManager.onNewIntent(intent);
}
}
/**
* 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();
views.add(this);
}
/**
* 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 {@true} if the Welcome page is enabled; otherwise, {@code false}.
*/
public boolean getWelcomePageEnabled() {
return welcomePageEnabled;
}
/**
* 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) {
Bundle props = new Bundle();
// externalAPIScope
props.putString("externalAPIScope", externalAPIScope);
// url
if (url != null) {
props.putString("url", url.toString());
}
// welcomePageEnabled
props.putBoolean("welcomePageEnabled", welcomePageEnabled);
// TODO: ReactRootView#setAppProperties is only available on React
// Native 0.45, so destroy the current root view and create a new one.
if (reactRootView != null) {
removeView(reactRootView);
reactRootView = null;
}
reactRootView = new ReactRootView(getContext());
reactRootView
.startReactApplication(reactInstanceManager, "App", props);
reactRootView.setBackgroundColor(BACKGROUND_COLOR);
addView(reactRootView);
}
/**
* 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,60 @@
/*
* 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 {
/**
* {@inheritDoc}
*/
@Override
public void onConferenceFailed(Map<String, Object> data) {
}
/**
* {@inheritDoc}
*/
@Override
public void onConferenceJoined(Map<String, Object> data) {
}
/**
* {@inheritDoc}
*/
@Override
public void onConferenceLeft(Map<String, Object> data) {
}
/**
* {@inheritDoc}
*/
@Override
public void onConferenceWillJoin(Map<String, Object> data) {
}
/**
* {@inheritDoc}
*/
@Override
public void onConferenceWillLeave(Map<String, Object> data) {
}
}

View File

@@ -0,0 +1,61 @@
/*
* 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);
}

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.audiomode;
import android.annotation.TargetApi;
import android.content.BroadcastReceiver;

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.audiomode;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;

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.audiomode;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;

View File

@@ -0,0 +1,119 @@
/*
* 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.externalapi;
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 org.jitsi.meet.sdk.JitsiMeetView;
import org.jitsi.meet.sdk.JitsiMeetViewListener;
import java.util.HashMap;
/**
* 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.
*/
public class ExternalAPIModule extends ReactContextBaseJavaModule {
/**
* React Native module name.
*/
private static final String MODULE_NAME = "ExternalAPI";
/**
* 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 MODULE_NAME;
}
/**
* 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;
}
// TODO Converting a ReadableMap to a HashMap is not supported until
// React Native 0.46.
HashMap<String, Object> dataMap = new HashMap<>();
switch (name) {
case "CONFERENCE_FAILED":
dataMap.put("error", data.getString("error"));
dataMap.put("url", data.getString("url"));
listener.onConferenceFailed(dataMap);
break;
case "CONFERENCE_JOINED":
dataMap.put("url", data.getString("url"));
listener.onConferenceJoined(dataMap);
break;
case "CONFERENCE_LEFT":
dataMap.put("url", data.getString("url"));
listener.onConferenceLeft(dataMap);
break;
case "CONFERENCE_WILL_JOIN":
dataMap.put("url", data.getString("url"));
listener.onConferenceWillJoin(dataMap);
break;
case "CONFERENCE_WILL_LEAVE":
dataMap.put("url", data.getString("url"));
listener.onConferenceWillLeave(dataMap);
break;
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* 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.externalapi;
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 ExternalAPIModule}.
*/
public class ExternalAPIPackage 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 ExternalAPIModule(reactContext));
return modules;
}
/**
* {@inheritDoc}
*/
@Override
public List<ViewManager> createViewManagers(
ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}

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.proximity;
import android.content.Context;
import android.os.PowerManager;

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.proximity;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;

View File

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

View File

@@ -1,6 +1,6 @@
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-immersive'

63
app.js
View File

@@ -1,68 +1,49 @@
/* application specific logic */
import "jquery";
import "jquery-contextmenu";
import "jquery-ui";
import "strophe";
import "strophe-disco";
import "jQuery-Impromptu";
import "autosize";
import 'jquery';
import 'jquery-contextmenu';
import 'jquery-ui';
import 'strophe';
import 'strophe-disco';
import 'jQuery-Impromptu';
import 'autosize';
import 'aui';
import 'aui-experimental';
import 'aui-css';
import 'aui-experimental-css';
window.toastr = require("toastr");
window.toastr = require('toastr');
import conference from './conference';
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 remoteControl from './modules/remotecontrol/RemoteControl';
import settings from './modules/settings/Settings';
import translation from './modules/translation/translation';
import UI from './modules/UI/UI';
const APP = {
window.APP = {
API,
conference,
/**
* After the APP has been initialized provides utility methods for dealing
* with the conference room URL(address).
* @type ConferenceUrl
*/
ConferenceUrl: null,
// 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'
},
connection: null,
// Used for automated performance tests
// Used for automated performance tests.
connectionTimes: {
"index.loaded": window.indexLoadedTime
'index.loaded': window.indexLoadedTime
},
keyboardshortcut,
/**
* 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,
remoteControl,
settings,
translation,
@@ -76,5 +57,3 @@ const APP = {
// the execution of the Web app to start from app.js in order to reduce the
// complexity of the beginning step.
import './react';
module.exports = APP;

View File

@@ -29,22 +29,25 @@ import {
EMAIL_COMMAND,
lockStateChanged
} from './react/features/base/conference';
import {
updateDeviceList
} from './react/features/base/devices';
import { updateDeviceList } from './react/features/base/devices';
import {
isFatalJitsiConnectionError
} from './react/features/base/lib-jitsi-meet';
import { setVideoAvailable } from './react/features/base/media';
import {
localParticipantRoleChanged,
MAX_DISPLAY_NAME_LENGTH,
participantJoined,
participantLeft,
participantRoleChanged,
participantUpdated
} from './react/features/base/participants';
import {
showDesktopPicker
} from './react/features/desktop-picker';
replaceLocalTrack,
trackAdded,
trackRemoved
} from './react/features/base/tracks';
import { showDesktopPicker } from './react/features/desktop-picker';
import {
mediaPermissionPromptVisibilityChanged,
suspendDetected
@@ -81,8 +84,8 @@ import {VIDEO_CONTAINER_TYPE} from "./modules/UI/videolayout/VideoContainer";
* lib-jitsi-meet to detect and invoke
*/
window.JitsiMeetScreenObtainer = {
openDesktopPicker(onSourceChoose) {
APP.store.dispatch(showDesktopPicker(onSourceChoose));
openDesktopPicker(options, onSourceChoose) {
APP.store.dispatch(showDesktopPicker(options, onSourceChoose));
}
};
@@ -98,12 +101,6 @@ const commands = {
SHARED_VIDEO: "shared-video"
};
/**
* Max length of the display names. If we receive longer display name the
* additional chars are going to be cut.
*/
const MAX_DISPLAY_NAME_LENGTH = 50;
/**
* Open Connection. When authentication failed it shows auth dialog.
* @param roomName the room name to use
@@ -131,7 +128,8 @@ function connect(roomName) {
*/
function createInitialLocalTracksAndConnect(roomName) {
let audioAndVideoError,
audioOnlyError;
audioOnlyError,
videoOnlyError;
JitsiMeetJS.mediaDevices.addEventListener(
JitsiMeetJS.events.mediaDevices.PERMISSION_PROMPT_IS_SHOWN,
@@ -149,8 +147,14 @@ function createInitialLocalTracksAndConnect(roomName) {
return createLocalTracks({ devices: ['audio'] }, true);
})
.catch(err => {
// If audio failed too then just return empty array for tracks.
audioOnlyError = err;
// Try video only...
return createLocalTracks({ devices: ['video'] }, true);
})
.catch(err => {
videoOnlyError = err;
return [];
});
@@ -162,7 +166,8 @@ function createInitialLocalTracksAndConnect(roomName) {
// If both requests for 'audio' + 'video' and 'audio' only
// failed, we assume that there is some problems with user's
// microphone and show corresponding dialog.
APP.UI.showDeviceErrorDialog(audioOnlyError, null);
APP.UI.showDeviceErrorDialog(
audioOnlyError, videoOnlyError);
} else {
// If request for 'audio' + 'video' failed, but request for
// 'audio' only was OK, we assume that we had problems with
@@ -341,6 +346,7 @@ function createLocalTracks(options, checkForPermissionPrompt) {
.createLocalTracks({
// copy array to avoid mutations inside library
devices: options.devices.slice(0),
desktopSharingSources: options.desktopSharingSources,
resolution: config.resolution,
cameraDeviceId: typeof options.cameraDeviceId === 'undefined' ||
options.cameraDeviceId === null
@@ -532,7 +538,27 @@ export default {
audioMuted: false,
videoMuted: false,
isSharingScreen: false,
/**
* Indicates if the desktop sharing functionality has been enabled.
* It takes into consideration {@link isDesktopSharingDisabledByConfig}
* as well as the status returned by
* {@link JitsiMeetJS.isDesktopSharingEnabled()}. The latter can be false
* either if the desktop sharing is not supported by the current browser
* or if it was disabled through lib-jitsi-meet specific options (check
* config.js for listed options).
*/
isDesktopSharingEnabled: false,
/**
* Set to <tt>true</tt> if the desktop sharing functionality has been
* explicitly disabled in the config.
*/
isDesktopSharingDisabledByConfig: false,
/**
* The text displayed when the desktop sharing button is disabled through
* the config. The value is set through
* {@link interfaceConfig.DESKTOP_SHARING_BUTTON_DISABLED_TOOLTIP}.
*/
desktopSharingDisabledTooltip: null,
/*
* Whether the local "raisedHand" flag is on.
*/
@@ -589,8 +615,15 @@ export default {
ConnectionEvents.CONNECTION_FAILED,
_connectionFailedHandler);
APP.connection = connection = con;
this.isDesktopSharingEnabled =
JitsiMeetJS.isDesktopSharingEnabled();
// Desktop sharing related stuff:
this.isDesktopSharingDisabledByConfig
= config.disableDesktopSharing;
this.isDesktopSharingEnabled
= !this.isDesktopSharingDisabledByConfig
&& JitsiMeetJS.isDesktopSharingEnabled();
this.desktopSharingDisabledTooltip
= interfaceConfig.DESKTOP_SHARING_BUTTON_DISABLED_TOOLTIP;
eventEmitter.emit(
JitsiMeetConferenceEvents.DESKTOP_SHARING_ENABLED_CHANGED,
this.isDesktopSharingEnabled);
@@ -612,7 +645,18 @@ export default {
}
if (!tracks.find((t) => t.isVideoTrack())) {
APP.UI.setCameraButtonEnabled(false);
// Instead of disabling the button we want to show button
// muted, so that the user can have the opportunity to add
// the video later on, even if joined without it.
this.videoMuted = true;
APP.UI.setVideoMuted(this.getMyUserId(), this.videoMuted);
// FIXME this is a workaround for the situation where
// both audio and video permissions are rejected initially
// and the callback from _initDeviceList will never be
// executed (GUM not initialized - check lib-jitsi-meet).
// The goal here is to disable the video icon in case no
// video permissions were granted.
this.updateVideoIconEnabled();
}
this._initDeviceList();
@@ -1022,30 +1066,22 @@ export default {
* @returns {Promise}
*/
useVideoStream(newStream) {
return room.replaceTrack(localVideo, newStream)
return APP.store.dispatch(
replaceLocalTrack(localVideo, newStream, room))
.then(() => {
// We call dispose after doing the replace because
// dispose will try and do a new o/a after the
// track removes itself. Doing it after means
// the JitsiLocalTrack::conference member is already
// cleared, so it won't try and do the o/a
if (localVideo) {
localVideo.dispose();
}
localVideo = newStream;
if (newStream) {
this.videoMuted = newStream.isMuted();
this.isSharingScreen = newStream.videoType === 'desktop';
APP.UI.addLocalStream(newStream);
newStream.videoType === 'camera'
&& APP.UI.setCameraButtonEnabled(true);
} else {
this.videoMuted = false;
// No video is treated the same way as being video muted
this.videoMuted = true;
this.isSharingScreen = false;
}
APP.UI.setVideoMuted(this.getMyUserId(), this.videoMuted);
this.updateVideoIconEnabled();
APP.UI.updateDesktopSharingButtons();
});
},
@@ -1057,16 +1093,9 @@ export default {
* @returns {Promise}
*/
useAudioStream(newStream) {
return room.replaceTrack(localAudio, newStream)
return APP.store.dispatch(
replaceLocalTrack(localAudio, newStream, room))
.then(() => {
// We call dispose after doing the replace because
// dispose will try and do a new o/a after the
// track removes itself. Doing it after means
// the JitsiLocalTrack::conference member is already
// cleared, so it won't try and do the o/a
if (localAudio) {
localAudio.dispose();
}
localAudio = newStream;
if (newStream) {
this.audioMuted = newStream.isMuted();
@@ -1118,26 +1147,105 @@ export default {
},
videoSwitchInProgress: false,
toggleScreenSharing(shareScreen = !this.isSharingScreen) {
/**
* This fields stores a handler which will create a Promise which turns off
* the screen sharing and restores the previous video state (was there
* any video, before switching to screen sharing ? was it muted ?).
*
* Once called this fields is cleared to <tt>null</tt>.
* @type {Function|null}
*/
_untoggleScreenSharing: null,
/**
* Creates a Promise which turns off the screen sharing and restores
* the previous state described by the arguments.
*
* This method is bound to the appropriate values, after switching to screen
* sharing and stored in {@link _untoggleScreenSharing}.
*
* @param {boolean} didHaveVideo indicates if there was a camera video being
* used, before switching to screen sharing.
* @param {boolean} wasVideoMuted indicates if the video was muted, before
* switching to screen sharing.
* @return {Promise} resolved after the screen sharing is turned off, or
* rejected with some error (no idea what kind of error, possible GUM error)
* in case it fails.
* @private
*/
_turnScreenSharingOff(didHaveVideo, wasVideoMuted) {
this._untoggleScreenSharing = null;
this.videoSwitchInProgress = true;
APP.remoteControl.receiver.stop();
let promise = null;
if (didHaveVideo) {
promise = createLocalTracks({ devices: ['video'] })
.then(([stream]) => this.useVideoStream(stream))
.then(() => {
JitsiMeetJS.analytics.sendEvent(
'conference.sharingDesktop.stop');
logger.log('switched back to local video');
if (!localVideo && wasVideoMuted) {
return Promise.reject('No local video to be muted!');
} else if (wasVideoMuted && localVideo) {
return localVideo.mute();
}
})
.catch(error => {
logger.error('failed to switch back to local video', error);
return this.useVideoStream(null).then(() => {
// Still fail with the original err
return Promise.reject(error);
});
});
} else {
promise = this.useVideoStream(null);
}
return promise.then(
() => {
this.videoSwitchInProgress = false;
},
error => {
this.videoSwitchInProgress = false;
throw error;
});
},
/**
* Toggles between screensharing and camera video.
* @param {boolean} [shareScreen]
* @param {Object} [options] - Screen sharing options that will be passed to
* createLocalTracks.
* @param {Array<string>} [options.desktopSharingSources] - Array with the
* sources that have to be displayed in the desktop picker window ('screen',
* 'window', etc.).
* @return {Promise.<T>}
*/
toggleScreenSharing(options = {}) {
if (this.videoSwitchInProgress) {
logger.warn("Switch in progress.");
return;
return Promise.reject('Switch in progress.');
}
if (!this.isDesktopSharingEnabled) {
logger.warn("Cannot toggle screen sharing: not supported.");
return;
return Promise.reject(
'Cannot toggle screen sharing: not supported.');
}
if (this.isAudioOnly()) {
this._displayAudioOnlyTooltip('screenShare');
return;
return Promise.reject('No screensharing in audio only mode');
}
this.videoSwitchInProgress = true;
let externalInstallation = false;
if (!this._untoggleScreenSharing) {
this.videoSwitchInProgress = true;
let externalInstallation = false;
const didHaveVideo = Boolean(localVideo);
const wasVideoMuted = this.videoMuted;
if (shareScreen) {
this.screenSharingPromise = createLocalTracks({
return createLocalTracks({
desktopSharingSources: options.desktopSharingSources,
devices: ['desktop'],
desktopSharingExtensionExternalInstallation: {
interval: 500,
@@ -1162,6 +1270,11 @@ export default {
}
}
}).then(([stream]) => {
// Stores the "untoggle" handler which remembers whether was
// there any video before and whether was it muted.
this._untoggleScreenSharing
= this._turnScreenSharingOff
.bind(this, didHaveVideo, wasVideoMuted);
DSExternalInstallationInProgress = false;
// close external installation dialog on success.
if(externalInstallation)
@@ -1169,12 +1282,11 @@ export default {
stream.on(
TrackEvents.LOCAL_TRACK_STOPPED,
() => {
// if stream was stopped during screensharing session
// then we should switch to video
// otherwise we stopped it because we already switched
// to video, so nothing to do here
if (this.isSharingScreen) {
this.toggleScreenSharing(false);
// If the stream was stopped during screen sharing
// session then we should switch back to video.
if (this.isSharingScreen){
this._untoggleScreenSharing
&& this._untoggleScreenSharing();
}
}
);
@@ -1184,15 +1296,26 @@ export default {
JitsiMeetJS.analytics.sendEvent(
'conference.sharingDesktop.start');
logger.log('sharing local desktop');
}).catch((err) => {
}).catch(err => {
// close external installation dialog to show the error.
if(externalInstallation)
$.prompt.close();
this.videoSwitchInProgress = false;
this.toggleScreenSharing(false);
if (err.name === TrackErrors.CHROME_EXTENSION_USER_CANCELED) {
return;
return Promise.reject(err);
}
// Pawel: With this call I'm trying to preserve the original
// behaviour although it is not clear why would we "untoggle"
// on failure. I suppose it was to restore video in case there
// was some problem during "this.useVideoStream(desktopStream)".
// It's important to note that the handler will not be available
// if we fail early on trying to get desktop media (which makes
// sense, because the camera video is still being used, so
// nothing to "untoggle").
if (this._untoggleScreenSharing) {
this._untoggleScreenSharing();
}
logger.error('failed to share local desktop', err);
@@ -1201,7 +1324,7 @@ export default {
APP.UI.showExtensionRequiredDialog(
config.desktopSharingFirefoxExtensionURL
);
return;
return Promise.reject(err);
}
// Handling:
@@ -1226,21 +1349,7 @@ export default {
dialogTitleKey, dialogTxt, false);
});
} else {
APP.remoteControl.receiver.stop();
this.screenSharingPromise = createLocalTracks(
{ devices: ['video'] })
.then(
([stream]) => this.useVideoStream(stream)
).then(() => {
this.videoSwitchInProgress = false;
JitsiMeetJS.analytics.sendEvent(
'conference.sharingDesktop.stop');
logger.log('sharing local video');
}).catch((err) => {
this.useVideoStream(null);
this.videoSwitchInProgress = false;
logger.error('failed to share local video', err);
});
return this._untoggleScreenSharing();
}
},
/**
@@ -1327,38 +1436,16 @@ export default {
if(!track || track.isLocal())
return;
track.on(TrackEvents.TRACK_VIDEOTYPE_CHANGED, (type) => {
APP.UI.onPeerVideoTypeChanged(track.getParticipantId(), type);
});
APP.UI.addRemoteStream(track);
APP.store.dispatch(trackAdded(track));
});
room.on(ConferenceEvents.TRACK_REMOVED, (track) => {
if(!track || track.isLocal())
return;
APP.UI.removeRemoteStream(track);
APP.store.dispatch(trackRemoved(track));
});
room.on(ConferenceEvents.TRACK_MUTE_CHANGED, (track) => {
if(!track)
return;
const handler = (track.getType() === "audio")?
APP.UI.setAudioMuted : APP.UI.setVideoMuted;
let id;
const mute = track.isMuted();
if(track.isLocal()){
id = APP.conference.getMyUserId();
if(track.getType() === "audio") {
this.audioMuted = mute;
} else {
this.videoMuted = mute;
}
} else {
id = track.getParticipantId();
}
handler(id , mute);
});
room.on(ConferenceEvents.TRACK_AUDIO_LEVEL_CHANGED, (id, lvl) => {
if(this.isLocalId(id) && localAudio && localAudio.isMuted()) {
lvl = 0;
@@ -1565,10 +1652,21 @@ export default {
APP.UI.addListener(UIEvents.VIDEO_MUTED, muted => {
if (this.isAudioOnly() && !muted) {
this._displayAudioOnlyTooltip('videoMute');
return;
} else if (!localVideo && this.videoMuted && !muted) {
// Maybe try to create local video if there wasn't any ?
// This handles the case when user joined with no video
// (dismissed screen sharing screen), but decided to add it
// later on by clicking on muted video icon.
createLocalTracks({ devices: ['video'] }, false)
.then(([videoTrack]) => {
APP.conference.useVideoStream(videoTrack);
})
.catch(error => {
APP.UI.showDeviceErrorDialog(null, error);
});
} else {
muteLocalVideo(muted);
}
muteLocalVideo(muted);
});
room.on(ConnectionQualityEvents.LOCAL_STATS_UPDATED,
@@ -1873,34 +1971,42 @@ export default {
* @private
*/
_initDeviceList() {
if (JitsiMeetJS.mediaDevices.isDeviceListAvailable() &&
JitsiMeetJS.mediaDevices.isDeviceChangeAvailable()) {
JitsiMeetJS.mediaDevices.enumerateDevices(devices => {
// Ugly way to synchronize real device IDs with local
// storage and settings menu. This is a workaround until
// getConstraints() method will be implemented in browsers.
if (localAudio) {
APP.settings.setMicDeviceId(
localAudio.getDeviceId(), false);
}
JitsiMeetJS.mediaDevices.isDeviceListAvailable()
.then(isDeviceListAvailable => {
if (isDeviceListAvailable
&& JitsiMeetJS.mediaDevices.isDeviceChangeAvailable()) {
JitsiMeetJS.mediaDevices.enumerateDevices(devices => {
// Ugly way to synchronize real device IDs with local
// storage and settings menu. This is a workaround until
// getConstraints() method will be implemented
// in browsers.
if (localAudio) {
APP.settings.setMicDeviceId(
localAudio.getDeviceId(), false);
}
if (localVideo) {
APP.settings.setCameraDeviceId(
localVideo.getDeviceId(), false);
}
if (localVideo) {
APP.settings.setCameraDeviceId(
localVideo.getDeviceId(), false);
}
mediaDeviceHelper.setCurrentMediaDevices(devices);
APP.UI.onAvailableDevicesChanged(devices);
APP.store.dispatch(updateDeviceList(devices));
mediaDeviceHelper.setCurrentMediaDevices(devices);
APP.UI.onAvailableDevicesChanged(devices);
APP.store.dispatch(updateDeviceList(devices));
this.updateVideoIconEnabled();
});
this.deviceChangeListener = (devices) =>
window.setTimeout(
() => this._onDeviceListChanged(devices), 0);
JitsiMeetJS.mediaDevices.addEventListener(
JitsiMeetJS.events.mediaDevices.DEVICE_LIST_CHANGED,
this.deviceChangeListener);
}
})
.catch((error) => {
logger.warn(`Error getting device list: ${error}`);
});
this.deviceChangeListener = (devices) =>
window.setTimeout(
() => this._onDeviceListChanged(devices), 0);
JitsiMeetJS.mediaDevices.addEventListener(
JitsiMeetJS.events.mediaDevices.DEVICE_LIST_CHANGED,
this.deviceChangeListener);
}
},
/**
* Event listener for JitsiMediaDevicesEvents.DEVICE_LIST_CHANGED to
@@ -1957,9 +2063,10 @@ export default {
// If video was muted before, or we unplugged current device
// and selected new one, then mute new video track.
if (videoWasMuted ||
currentDevices.videoinput.length >
availableVideoInputDevices.length) {
if (!this.isSharingScreen &&
(videoWasMuted ||
currentDevices.videoinput.length >
availableVideoInputDevices.length)) {
muteLocalVideo(true);
}
}));
@@ -1968,8 +2075,32 @@ export default {
.then(() => {
mediaDeviceHelper.setCurrentMediaDevices(devices);
APP.UI.onAvailableDevicesChanged(devices);
this.updateVideoIconEnabled();
});
},
/**
* Determines whether or not the video button should be enabled.
*/
updateVideoIconEnabled() {
const videoMediaDevices
= mediaDeviceHelper.getCurrentMediaDevices().videoinput;
const videoDeviceCount
= videoMediaDevices ? videoMediaDevices.length : 0;
// The video functionality is considered available if there are any
// video devices detected or if there is local video stream already
// active which could be either screensharing stream or a video track
// created before the permissions were rejected (through browser
// config).
const available = videoDeviceCount > 0 || Boolean(localVideo);
logger.debug(
'Camera button enabled: ' + available,
'local video: ' + localVideo,
'video devices: ' + videoMediaDevices,
'device count: ' + videoDeviceCount);
APP.store.dispatch(setVideoAvailable(available));
},
/**
* Toggles the local "raised hand" status.
@@ -2051,7 +2182,7 @@ export default {
* @param email {string} the new email
*/
changeLocalEmail(email = '') {
email = email.trim();
email = String(email).trim();
if (email === APP.settings.getEmail()) {
return;
@@ -2075,7 +2206,7 @@ export default {
* @param url {string} the new url
*/
changeLocalAvatarUrl(url = '') {
url = url.trim();
url = String(url).trim();
if (url === APP.settings.getAvatarUrl()) {
return;
@@ -2125,18 +2256,6 @@ export default {
eventEmitter.removeListener(eventName, listener);
},
/**
* Checks if the participant given by participantId is currently in the
* last N set if there's one supported.
*
* @param participantId the identifier of the participant
* @returns {boolean} {true} if the participant given by the participantId
* is currently in the last N set or if there's no last N set at this point
* and {false} otherwise
*/
isInLastN(participantId) {
return room.isInLastN(participantId);
},
/**
* Changes the display name for the local user
* @param nickname {string} the new display name
@@ -2160,5 +2279,28 @@ export default {
room.setDisplayName(formattedNickname);
APP.UI.changeDisplayName(this.getMyUserId(), formattedNickname);
}
},
/**
* Returns the desktop sharing source id or undefined if the desktop sharing
* is not active at the moment.
*
* @returns {string|undefined} - The source id. If the track is not desktop
* track or the source id is not available, undefined will be returned.
*/
getDesktopSharingSourceId() {
return localVideo.sourceId;
},
/**
* Returns the desktop sharing source type or undefined if the desktop
* sharing is not active at the moment.
*
* @returns {'screen'|'window'|undefined} - The source type. If the track is
* not desktop track or the source type is not available, undefined will be
* returned.
*/
getDesktopSharingSourceType() {
return localVideo.sourceType;
}
};

View File

@@ -11,6 +11,13 @@ var config = { // eslint-disable-line no-unused-vars
//call_control: 'callcontrol.jitsi-meet.example.com',
//focus: 'focus.jitsi-meet.example.com', // defaults to 'focus.jitsi-meet.example.com'
},
testing: {
/**
* P2P test mode disables automatic switching to P2P when there are 2
* participants in the conference.
*/
p2pTestMode: false,
},
// 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
@@ -19,14 +26,10 @@ var config = { // eslint-disable-line no-unused-vars
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" }
],
/**
* Disables desktop sharing functionality.
*/
disableDesktopSharing: false,
// The ID of the jidesha extension for Chrome.
desktopSharingChromeExtId: null,
// Whether desktop sharing should be disabled on Chrome.
@@ -90,15 +93,36 @@ var config = { // eslint-disable-line no-unused-vars
disableSuspendVideo: true,
// disables or enables RTX (RFC 4588) (defaults to false).
disableRtx: false,
// Sets the preferred resolution (height) for local video. Defaults to 360.
// Sets the preferred resolution (height) for local video. Defaults to 720.
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
// Peer-To-Peer mode: used (if enabled) when there are just 2 participants.
p2p: {
// 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.
enabled: true,
// The STUN servers that will be used in the peer to peer connections
// useStunTurn: true, // use XEP-0215 to fetch STUN and TURN server
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
// 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"
}
};

View File

@@ -41,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;
}

View File

@@ -51,10 +51,8 @@
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;
@@ -62,9 +60,10 @@
videos. */
font-size: 0pt;
#filmstripLocalVideo {
padding-left: 0;
}
&#remoteVideos {
border: $thumbnailsBorder solid transparent;
padding-left: $defaultToolbarSize + 5;
}
&.hidden {
bottom: -196px;
@@ -136,7 +135,6 @@
&__videos-filmstripOnly {
margin-top: auto;
margin-bottom: auto;
padding-right: $defaultToolbarSize;
}
.remote-videos-container {

View File

@@ -25,6 +25,9 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-thumb-menu:before {
content: "\e5d4";
}
.icon-mic-camera-combined:before {
content: "\e903";
}
@@ -88,6 +91,9 @@
.icon-mic-disabled:before {
content: "\e912";
}
.icon-ninja:before {
content: "\e909";
}
.icon-raised-hand:before {
content: "\e91e";
}
@@ -148,3 +154,6 @@
.icon-telephone:before {
content: "\e0cd";
}
.icon-add:before {
content: "\e145";
}

View File

@@ -3,7 +3,8 @@
top: 0;
left: 0;
z-index: $jitsipopoverZ;
display: none;
display: table;
visibility: hidden;
max-width: 300px;
min-width: 100px;
text-align: left;
@@ -16,11 +17,31 @@
white-space: normal;
margin-top: -$popoverMenuPadding;
&__menu-padding {
height: $popoverMenuPadding;
width: 100px;
&__menu-padding,
&__menu-padding-top {
position: absolute;
width: 100px;
}
/**
* Invisible padding is added to the bottom of the popover to extend its
* height so it does not close when moving the mouse from the trigger
* element towards the popover itself.
*/
&__menu-padding {
bottom: -$popoverMenuPadding;
height: $popoverMenuPadding;
}
/**
* Invisible padding is added to the top of the popover to extend its height
* so it does not close automatically when its height is shrunk from showing
* less video statistics.
*/
&__menu-padding-top {
height: 20px;
top: -20px;
}
&__showmore {

View File

@@ -59,9 +59,9 @@
width: 100%;
.popupmenu__slider {
bottom: 50%;
position: absolute;
top: 50%;
transform: translate(0, -50%);
width: 100%;
}
}

View File

@@ -12,7 +12,7 @@
*/
.toast-title,
.toast-message .nickname {
.toast-message .title {
font-weight: bold;
margin: 0 0 3px;
@include text-truncate;
@@ -104,4 +104,4 @@
#toast-container .toast {
width: $notificationWidth;
margin: 0 0 8px;
}
}

View File

@@ -195,12 +195,15 @@
*/
&_filmstrip-only {
border-radius: 3px;
bottom: 0;
display: inline-block;
height: auto;
position: absolute;
right: 0;
width: $defaultToolbarSize;
width: $defaultFilmStripOnlyToolbarSize;
.button {
height: 37px;
line-height: 37px !important;
width: 37px;
}
.button:first-child {
border-top-left-radius: 3px;
@@ -222,6 +225,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;

View File

@@ -34,6 +34,7 @@ $tooltipBg: rgba(0,0,0, 0.7);
* Toolbar
*/
$defaultToolbarSize: 50px;
$defaultFilmStripOnlyToolbarSize: 37px;
$splitterToolbarButtonMargin: 18px;
$toolbarBackground: rgba(0, 0, 0, 0.5);
$toolbarBadgeBackground: #165ECC;
@@ -127,9 +128,9 @@ $toolbarZ: 400;
$tooltipsZ: 401;
$dropdownMaskZ: 900;
$dropdownZ: 901;
$jitsipopoverZ: 1010;
$centeredVideoLabelZ: 1011;
$notificationZ: 1012;
$centeredVideoLabelZ: 1010;
$notificationZ: 1011;
$jitsipopoverZ: 1012;
$popoverZ: 1015;
$overlayZ: 1016;

View File

@@ -65,15 +65,21 @@
left: 0;
top: auto;
right: auto;
transform: rotate(-90deg);
margin-bottom: 7px;
transform: translate3d(0,0,0);
}
#remoteVideos {
flex-direction: column-reverse;
height: 100%;
flex-grow: 1;
}
.videocontainer {
&__toolbar,
&__toptoolbar {
transform: translate3d(0,0,0);
}
/**
* Move status icons to the bottom right of the thumbnail.
*/
@@ -82,11 +88,35 @@
.toolbar-icon {
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

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;
@@ -48,14 +58,26 @@
padding: $toolbarPadding;
padding-bottom: 0;
.connection-indicator,
span.indicator {
margin-right: em(5, 8);
}
span.indicator {
display: none;
&:last-child {
margin-right: 0;
}
}
.connection-indicator,
span.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;
@@ -64,10 +86,6 @@
color: $thumbnailPictogramColor;
border: $thumbnailIndicatorBorder solid $thumbnailPictogramColor;
&:last-child {
margin-right: 0;
}
.indicatoricon {
@include absoluteAligning();
}
@@ -97,6 +115,11 @@
color: #FFFFFF;/*#15A1ED*/
overflow: hidden;
}
&_ninja
{
font-size: 1.5em;
}
}
.icon-connection,
@@ -134,8 +157,8 @@
-o-transform: scale(-1, 1);
}
#localVideoWrapper>video,
#localVideoWrapper>object {
#localVideoWrapper video,
#localVideoWrapper object {
border-radius: $borderRadius !important;
cursor: hand;
object-fit: cover;
@@ -148,6 +171,10 @@
text-align: center;
}
#largeVideoWrapper {
box-shadow: 0 0 20px -2px #444;
}
#largeVideo,
#largeVideoWrapper
{
@@ -156,8 +183,8 @@
#sharedVideo,
#etherpad,
#localVideoWrapper>video,
#localVideoWrapper>object,
#localVideoWrapper video,
#localVideoWrapper object,
#localVideoWrapper,
#largeVideoWrapper,
#largeVideoWrapper>video,
@@ -274,11 +301,11 @@
margin: 0px 0px 0px 5px;
}
#raisehandindicator {
.raisehandindicator {
background: $raiseHandBg;
}
#connectionindicator {
.connection-indicator {
background: $connectionIndicatorBg;
}
@@ -288,18 +315,23 @@
position: absolute;
top: 0px;
right: 0;
margin: 7px;
margin-top: 7px;
z-index: $zindex3;
width: 18px;
height: 13px;
color: #FFF;
font-size: 8pt;
font-size: 10pt;
>i{
cursor: hand;
}
}
/**
* Audio indicator on video thumbnails.
*/
.videocontainer>span.audioindicator {
.videocontainer>span.audioindicator,
.videocontainer>.audioindicator-container {
position: absolute;
display: inline-block;
left: 6px;

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

@@ -73,6 +73,7 @@
@import 'policy';
@import 'filmstrip';
@import 'unsupported-browser/main';
@import 'modals/invite/add-people';
@import 'vertical_filmstrip_overrides';
/* Modules END */

View File

@@ -79,13 +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

@@ -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

@@ -58,6 +58,7 @@ $auiDialogBg: #f5f5f5;
$auiDialogContentBg: $baseLight;
$auiBorderColor: #ccc;
$dialogTitleFontWeight: 400;
$dialogErrorText: #344563;
/**
* Inlay colors
@@ -70,9 +71,6 @@ $inlayFilmstripOnlyColor: #474747;
$inlayFilmstripOnlyBg: #fff;
// Main controls
$inputBackground: $controlBackground;
$inputBorderColor: #ccc;
$inputColor: $controlColor;
$placeHolderColor: #a7a7a7;
$readOnlyInputColor: #a7a7a7;
$defaultDarkSelectionColor: #ccc;

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:
* **room**: (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 '%'.
* **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.
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 = {
domain: "meet.jit.si",
room: "JitsiMeetAPIExample",
width: 700,
height: 700,
htmlElement: 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
@@ -234,6 +236,11 @@ 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 remove the embedded Jitsi Meet Conference with the following API function:
```javascript
api.dispose()

View File

@@ -10,6 +10,8 @@ First make sure the [React Native dependencies] are installed.
**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 +26,15 @@ 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 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.

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
```

Binary file not shown.

View File

@@ -8,6 +8,8 @@
<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" />
@@ -21,6 +23,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="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" />

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Binary file not shown.

View File

@@ -1,6 +1,116 @@
{
"IcoMoonType": "selection",
"icons": [
{
"icon": {
"paths": [
"M512 682c46 0 86 40 86 86s-40 86-86 86-86-40-86-86 40-86 86-86zM512 426c46 0 86 40 86 86s-40 86-86 86-86-40-86-86 40-86 86-86zM512 342c-46 0-86-40-86-86s40-86 86-86 86 40 86 86-40 86-86 86z"
],
"attrs": [],
"isMulticolor": false,
"isMulticolor2": false,
"tags": [
"more_vert"
],
"defaultCode": 58836,
"grid": 24
},
"attrs": [],
"properties": {
"ligatures": "more_vert",
"id": 502,
"order": 897,
"prevSize": 24,
"code": 58836,
"name": "thumb-menu"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 502
},
{
"icon": {
"paths": [
"M330.667 554.667c-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 554.667c26.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 384c-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 85.333c235.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"
],
"attrs": [
{}
],
"isMulticolor": false,
"isMulticolor2": false,
"tags": [
"ninja"
],
"grid": 24
},
"attrs": [
{}
],
"properties": {
"order": 850,
"id": 0,
"name": "ninja",
"prevSize": 24,
"code": 59657
},
"setIdx": 1,
"setId": 1,
"iconIdx": 40
},
{
"icon": {
"paths": [
"M282 460c62 120 162 220 282 282l94-94c12-12 30-16 44-10 48 16 100 24 152 24 24 0 42 18 42 42v150c0 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"
],
"attrs": [],
"isMulticolor": false,
"isMulticolor2": false,
"tags": [
"phone"
],
"defaultCode": 57549,
"grid": 24
},
"attrs": [],
"properties": {
"ligatures": "call, local_phone, phone",
"id": 1,
"order": 851,
"prevSize": 24,
"code": 57549,
"name": "phone"
},
"setIdx": 1,
"setId": 1,
"iconIdx": 41
},
{
"icon": {
"paths": [
"M810 554h-256v256h-84v-256h-256v-84h256v-256h84v256h256v84z"
],
"attrs": [],
"isMulticolor": false,
"isMulticolor2": false,
"tags": [
"add"
],
"defaultCode": 57669,
"grid": 24
},
"attrs": [],
"properties": {
"ligatures": "add",
"id": 12,
"order": 896,
"prevSize": 24,
"code": 57669,
"name": "add"
},
"setIdx": 1,
"setId": 1,
"iconIdx": 42
},
{
"icon": {
"paths": [
@@ -20,13 +130,13 @@
{}
],
"properties": {
"order": 109,
"order": 856,
"id": 0,
"name": "mic-camera-combined",
"prevSize": 32,
"code": 59651
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 0
},
@@ -49,13 +159,13 @@
{}
],
"properties": {
"order": 104,
"order": 857,
"id": 1,
"name": "feedback",
"prevSize": 32,
"code": 59677
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 1
},
@@ -78,13 +188,13 @@
{}
],
"properties": {
"order": 103,
"order": 858,
"id": 2,
"name": "toggle-filmstrip",
"prevSize": 32,
"code": 59676
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 2
},
@@ -104,13 +214,13 @@
"attrs": [],
"properties": {
"id": 3,
"order": 60,
"order": 859,
"ligatures": "account_circle",
"prevSize": 32,
"code": 59649,
"name": "avatar"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 3
},
@@ -130,13 +240,13 @@
"attrs": [],
"properties": {
"id": 4,
"order": 63,
"order": 860,
"ligatures": "call_end",
"prevSize": 32,
"code": 59653,
"name": "hangup"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 4
},
@@ -156,13 +266,13 @@
"attrs": [],
"properties": {
"id": 5,
"order": 61,
"order": 861,
"ligatures": "chat_bubble_outline",
"prevSize": 32,
"code": 59654,
"name": "chat"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 5
},
@@ -182,13 +292,13 @@
"attrs": [],
"properties": {
"id": 6,
"order": 99,
"order": 862,
"ligatures": "cloud_download",
"prevSize": 32,
"code": 59650,
"name": "download"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 6
},
@@ -208,13 +318,13 @@
"attrs": [],
"properties": {
"id": 7,
"order": 89,
"order": 863,
"ligatures": "create, edit, mode_edit",
"prevSize": 32,
"code": 59655,
"name": "edit"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 7
},
@@ -234,13 +344,13 @@
"attrs": [],
"properties": {
"id": 8,
"order": 85,
"order": 864,
"ligatures": "description",
"prevSize": 32,
"code": 59656,
"name": "share-doc"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 8
},
@@ -259,16 +369,16 @@
},
"attrs": [],
"properties": {
"id": 10,
"order": 98,
"id": 9,
"order": 865,
"ligatures": "eject",
"prevSize": 32,
"code": 59652,
"name": "kick"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 10
"iconIdx": 9
},
{
"icon": {
@@ -285,16 +395,16 @@
},
"attrs": [],
"properties": {
"id": 11,
"order": 106,
"id": 10,
"order": 866,
"ligatures": "expand_less",
"prevSize": 32,
"code": 59679,
"name": "menu-up"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 11
"iconIdx": 10
},
{
"icon": {
@@ -311,16 +421,16 @@
},
"attrs": [],
"properties": {
"id": 12,
"order": 107,
"id": 11,
"order": 867,
"ligatures": "expand_more",
"prevSize": 32,
"code": 59680,
"name": "menu-down"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 12
"iconIdx": 11
},
{
"icon": {
@@ -337,16 +447,16 @@
},
"attrs": [],
"properties": {
"id": 13,
"order": 94,
"id": 12,
"order": 868,
"ligatures": "fullscreen",
"prevSize": 32,
"code": 59659,
"name": "full-screen"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 13
"iconIdx": 12
},
{
"icon": {
@@ -363,16 +473,16 @@
},
"attrs": [],
"properties": {
"id": 14,
"order": 92,
"id": 13,
"order": 869,
"ligatures": "fullscreen_exit",
"prevSize": 32,
"code": 59660,
"name": "exit-full-screen"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 14
"iconIdx": 13
},
{
"icon": {
@@ -389,16 +499,16 @@
},
"attrs": [],
"properties": {
"id": 15,
"order": 101,
"id": 14,
"order": 870,
"ligatures": "grade, star",
"prevSize": 32,
"code": 59658,
"name": "star-full"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 15
"iconIdx": 14
},
{
"icon": {
@@ -415,16 +525,16 @@
},
"attrs": [],
"properties": {
"id": 16,
"order": 66,
"id": 15,
"order": 871,
"ligatures": "lock_open",
"prevSize": 32,
"code": 59661,
"name": "security"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 16
"iconIdx": 15
},
{
"icon": {
@@ -441,16 +551,16 @@
},
"attrs": [],
"properties": {
"id": 17,
"order": 65,
"id": 16,
"order": 872,
"ligatures": "lock_outline",
"prevSize": 32,
"code": 59662,
"name": "security-locked"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 17
"iconIdx": 16
},
{
"icon": {
@@ -467,16 +577,16 @@
},
"attrs": [],
"properties": {
"id": 18,
"order": 67,
"id": 17,
"order": 873,
"ligatures": "loop, sync",
"prevSize": 32,
"code": 59663,
"name": "reload"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 18
"iconIdx": 17
},
{
"icon": {
@@ -493,16 +603,16 @@
},
"attrs": [],
"properties": {
"id": 19,
"order": 68,
"id": 18,
"order": 874,
"ligatures": "mic",
"prevSize": 32,
"code": 59664,
"name": "microphone"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 19
"iconIdx": 18
},
{
"icon": {
@@ -519,16 +629,16 @@
},
"attrs": [],
"properties": {
"id": 20,
"order": 69,
"id": 19,
"order": 875,
"ligatures": "mic_none",
"prevSize": 32,
"code": 59665,
"name": "mic-empty"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 20
"iconIdx": 19
},
{
"icon": {
@@ -545,16 +655,16 @@
},
"attrs": [],
"properties": {
"id": 21,
"order": 70,
"id": 20,
"order": 876,
"ligatures": "mic_off",
"prevSize": 32,
"code": 59666,
"name": "mic-disabled"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 21
"iconIdx": 20
},
{
"icon": {
@@ -571,16 +681,16 @@
},
"attrs": [],
"properties": {
"id": 22,
"order": 105,
"id": 21,
"order": 877,
"ligatures": "pan_tool",
"prevSize": 32,
"code": 59678,
"name": "raised-hand"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 22
"iconIdx": 21
},
{
"icon": {
@@ -597,16 +707,16 @@
},
"attrs": [],
"properties": {
"id": 23,
"order": 100,
"id": 22,
"order": 878,
"ligatures": "people_outline",
"prevSize": 32,
"code": 59675,
"name": "contactList"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 23
"iconIdx": 22
},
{
"icon": {
@@ -623,16 +733,16 @@
},
"attrs": [],
"properties": {
"id": 24,
"order": 87,
"id": 23,
"order": 879,
"ligatures": "person_add",
"prevSize": 32,
"code": 59667,
"name": "link"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 24
"iconIdx": 23
},
{
"icon": {
@@ -649,16 +759,16 @@
},
"attrs": [],
"properties": {
"id": 25,
"order": 82,
"id": 24,
"order": 880,
"ligatures": "play_circle_outline",
"prevSize": 32,
"code": 59668,
"name": "shared-video"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 25
"iconIdx": 24
},
{
"icon": {
@@ -675,16 +785,16 @@
},
"attrs": [],
"properties": {
"id": 26,
"order": 81,
"id": 25,
"order": 881,
"ligatures": "settings",
"prevSize": 32,
"code": 59669,
"name": "settings"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 26
"iconIdx": 25
},
{
"icon": {
@@ -701,16 +811,16 @@
},
"attrs": [],
"properties": {
"id": 27,
"order": 76,
"id": 26,
"order": 882,
"ligatures": "star_border",
"prevSize": 32,
"code": 59670,
"name": "star"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 27
"iconIdx": 26
},
{
"icon": {
@@ -727,16 +837,16 @@
},
"attrs": [],
"properties": {
"id": 28,
"order": 108,
"id": 27,
"order": 883,
"ligatures": "switch_camera",
"prevSize": 32,
"code": 59681,
"name": "switch-camera"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 28
"iconIdx": 27
},
{
"icon": {
@@ -753,16 +863,16 @@
},
"attrs": [],
"properties": {
"id": 29,
"order": 93,
"id": 28,
"order": 884,
"ligatures": "tv",
"prevSize": 32,
"code": 59671,
"name": "share-desktop"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 29
"iconIdx": 28
},
{
"icon": {
@@ -779,16 +889,16 @@
},
"attrs": [],
"properties": {
"id": 30,
"order": 77,
"id": 29,
"order": 885,
"ligatures": "videocam",
"prevSize": 32,
"code": 59672,
"name": "camera"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 30
"iconIdx": 29
},
{
"icon": {
@@ -805,16 +915,16 @@
},
"attrs": [],
"properties": {
"id": 31,
"order": 78,
"id": 30,
"order": 886,
"ligatures": "videocam_off",
"prevSize": 32,
"code": 59673,
"name": "camera-disabled"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 31
"iconIdx": 30
},
{
"icon": {
@@ -831,16 +941,16 @@
},
"attrs": [],
"properties": {
"id": 32,
"order": 79,
"id": 31,
"order": 887,
"ligatures": "volume_up",
"prevSize": 32,
"code": 59674,
"name": "volume"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 32
"iconIdx": 31
},
{
"icon": {
@@ -880,15 +990,15 @@
{}
],
"properties": {
"order": 33,
"id": 33,
"order": 888,
"id": 32,
"name": "connection-lost",
"prevSize": 32,
"code": 59648
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 33
"iconIdx": 32
},
{
"icon": {
@@ -952,16 +1062,16 @@
}
],
"properties": {
"order": 37,
"id": 34,
"order": 889,
"id": 33,
"prevSize": 32,
"code": 58906,
"name": "connection",
"ligatures": ""
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 34
"iconIdx": 33
},
{
"icon": {
@@ -981,16 +1091,16 @@
},
"attrs": [],
"properties": {
"order": 43,
"id": 35,
"order": 890,
"id": 34,
"prevSize": 32,
"code": 58899,
"name": "recDisable",
"ligatures": ""
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 35
"iconIdx": 34
},
{
"icon": {
@@ -1011,16 +1121,16 @@
},
"attrs": [],
"properties": {
"order": 44,
"id": 36,
"order": 891,
"id": 35,
"prevSize": 32,
"code": 58900,
"name": "recEnable",
"ligatures": ""
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 36
"iconIdx": 35
},
{
"icon": {
@@ -1041,16 +1151,16 @@
},
"attrs": [],
"properties": {
"order": 53,
"id": 37,
"order": 892,
"id": 36,
"prevSize": 32,
"code": 58883,
"name": "presentation",
"ligatures": ""
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 37
"iconIdx": 36
},
{
"icon": {
@@ -1067,16 +1177,16 @@
},
"attrs": [],
"properties": {
"order": 115,
"order": 893,
"ligatures": "dialpad",
"id": 38,
"id": 37,
"prevSize": 32,
"code": 59685,
"name": "dialpad"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 38
"iconIdx": 37
},
{
"icon": {
@@ -1093,16 +1203,16 @@
},
"attrs": [],
"properties": {
"order": 114,
"order": 894,
"ligatures": "remove_red_eye, visibility",
"id": 39,
"id": 38,
"prevSize": 32,
"code": 59683,
"name": "visibility"
},
"setIdx": 0,
"setIdx": 1,
"setId": 1,
"iconIdx": 39
"iconIdx": 38
},
{
"icon": {
@@ -1119,43 +1229,16 @@
},
"attrs": [],
"properties": {
"order": 113,
"order": 895,
"ligatures": "visibility_off",
"id": 40,
"id": 39,
"prevSize": 32,
"code": 59684,
"name": "visibility-off"
},
"setIdx": 0,
"setId": 1,
"iconIdx": 40
},
{
"icon": {
"paths": [
"M282 460c62 120 162 220 282 282l94-94c12-12 30-16 44-10 48 16 100 24 152 24 24 0 42 18 42 42v150c0 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"
],
"attrs": [],
"isMulticolor": false,
"isMulticolor2": false,
"tags": [
"phone"
],
"defaultCode": 57549,
"grid": 24
},
"attrs": [],
"properties": {
"ligatures": "call, local_phone, phone",
"id": 120,
"order": 848,
"prevSize": 24,
"code": 57549,
"name": "phone"
},
"setIdx": 1,
"setId": 0,
"iconIdx": 120
"setId": 1,
"iconIdx": 39
}
],
"height": 1024,

View File

@@ -4,7 +4,6 @@
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--#include virtual="base.html" -->
<!--#include virtual="local.html" -->
<script>
window.indexLoadedTime = window.performance.now();
console.log("(TIME) index.html loaded:\t", indexLoadedTime);

View File

@@ -1,10 +1,13 @@
var interfaceConfig = { // eslint-disable-line no-unused-vars
CANVAS_EXTRA: 104,
CANVAS_RADIUS: 0,
SHADOW_COLOR: '#ffffff',
// TO FIX: this needs to be handled from SASS variables. There are some
// methods allowing to use variables both in css and js.
DEFAULT_BACKGROUND: '#474747',
/**
* In case the desktop sharing is disabled through the config the button
* will not be hidden, but displayed as disabled with this text us as
* a tooltip.
*/
DESKTOP_SHARING_BUTTON_DISABLED_TOOLTIP: null,
INITIAL_TOOLBAR_TIMEOUT: 20000,
TOOLBAR_TIMEOUT: 4000,
DEFAULT_REMOTE_DISPLAY_NAME: "Fellow Jitster",
@@ -36,14 +39,14 @@ var interfaceConfig = { // eslint-disable-line no-unused-vars
*/
TOOLBAR_BUTTONS: [
//main toolbar
'microphone', 'camera', 'desktop', 'invite', 'fullscreen', 'hangup',
'microphone', 'camera', 'desktop', 'invite', 'fullscreen', 'fodeviceselection', 'hangup', // jshint ignore:line
//extended toolbar
'profile', 'contacts', 'chat', 'recording', 'etherpad', 'sharedvideo', 'dialout', 'settings', 'raisehand', 'filmstrip'], // jshint ignore:line
'profile', 'addtocall', 'contacts', 'chat', 'recording', 'etherpad', 'sharedvideo', 'dialout', 'settings', 'raisehand', 'filmstrip'], // jshint ignore:line
/**
* Main Toolbar Buttons
* All of them should be in TOOLBAR_BUTTONS
*/
MAIN_TOOLBAR_BUTTONS: ['microphone', 'camera', 'desktop', 'invite', 'fullscreen', 'hangup'], // jshint ignore:line
MAIN_TOOLBAR_BUTTONS: ['microphone', 'camera', 'desktop', 'invite', 'fullscreen', 'fodeviceselection', 'hangup'], // jshint ignore:line
SETTINGS_SECTIONS: ['language', 'devices', 'moderator'],
// Determines how the video would fit the screen. 'both' would fit the whole
// screen, 'height' would fit the original video height to the height of the
@@ -93,5 +96,19 @@ var interfaceConfig = { // eslint-disable-line no-unused-vars
*
* @type {boolean}
*/
MOBILE_APP_PROMO: true
MOBILE_APP_PROMO: true,
/**
* Maximum coeficient of the ratio of the large video to the visible area
* after the large video is scaled to fit the window.
*
* @type {number}
*/
MAXIMUM_ZOOMING_COEFFICIENT: 1.3
/*
* If indicated some of the error dialogs may point to the support URL for
* help.
*/
// SUPPORT_URL: ""
};

32
ios/Podfile Normal file
View File

@@ -0,0 +1,32 @@
platform :ios, '9.0'
workspace 'jitsi-meet'
target 'JitsiMeet' do
project 'sdk/sdk.xcodeproj'
pod 'React', :path => '../node_modules/react-native', :subspecs => [
'Core',
'RCTActionSheet',
'RCTAnimation',
'RCTImage',
'RCTLinkingIOS',
'RCTNetwork',
'RCTText',
'RCTWebSocket',
]
pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
pod 'react-native-background-timer', :path => '../node_modules/react-native-background-timer'
pod 'react-native-keep-awake', :path => '../node_modules/react-native-keep-awake'
pod 'react-native-webrtc', :path => '../node_modules/react-native-webrtc'
pod 'RNVectorIcons', :path => '../node_modules/react-native-vector-icons'
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
end
end

123
ios/README.md Normal file
View File

@@ -0,0 +1,123 @@
# Jitsi Meet SDK for iOS
This directory contains the source code of the Jitsi Meet app and the Jitsi Meet
SDK for iOS.
## Jitsi Meet SDK
JitsiMeet is an iOS framework which embodies the whole Jitsi Meet experience and
makes it reusable by third-party apps.
To get started:
1. Add a `JitsiMeetView` to your app using a Storyboard or Interface Builder,
for example.
2. Then, once the view has loaded, set the delegate in your controller and load
the desired URL:
```objc
- (void)viewDidLoad {
[super viewDidLoad];
JitsiMeetView *view = (JitsiMeetView *) self.view;
view.delegate = self;
[view loadURL:nil];
}
```
### JitsiMeetView class
The `JitsiMeetView` class is the entry point to the SDK. It a subclass of
`UIView` which renders a full conference in the designated area.
#### delegate
Property for getting / setting the `JitsiMeetViewDelegate` on `JitsiMeetView`.
#### welcomePageEnabled
Property for getting / setting whether the Welcome page is enabled. If NO, a
black empty view will be rendered when not in a conference. Defaults to NO.
NOTE: Must be set before calling `loadURL` for it to take effect.
#### loadURL(URL)
```objc
[meetView loadURL:[NSURL URLWithString:@"https://meet.jit.si/test123"]];
```
Loads the given URL and joins the room. If `null` is specified, the welcome page
is displayed instead.
#### Universal / deep linking
In order to support Universal / deep linking, `JitsiMeetView` offers 2 class
methods that you app's delegate should call in order for the app to follow those
links.
```objc
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler
{
return [JitsiMeetView application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
{
return [JitsiMeetView application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation];
}
```
### JitsiMeetViewDelegate
This delegate is optional, and can be set on the `JitsiMeetView` instance using
the `delegate` property.
It provides information about the conference state: was it joined, left, did it
fail?
All methods in this delegate are optional.
##### conferenceFailed
Called when a joining a conference was unsuccessful or when there was an error
while in a conference.
The `data` dictionary contains an "error" key describing the error and a "url"
key with the conference URL.
#### conferenceJoined
Called when a conference was joined.
The `data` dictionary contains a "url" key with the conference URL.
#### conferenceLeft
Called when a conference was left.
The `data` dictionary contains a "url" key with the conference URL.
#### conferenceWillJoin
Called before a conference is joined.
The `data` dictionary contains a "url" key with the conference URL.
#### conferenceWillLeave
Called before a conference is left.
The `data` dictionary contains a "url" key with the conference URL.

View File

@@ -1,16 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;
@end

View File

@@ -1,101 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "AppDelegate.h"
#import <React/RCTAssert.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTLinkingManager.h>
#import <React/RCTRootView.h>
/**
* A <tt>RCTFatalHandler</tt> implementation which swallows JavaScript errors.
* In the Release configuration, React Native will (intentionally) raise an
* unhandled NSException for an unhandled JavaScript error. This will
* effectively kill the application. <tt>_RCTFatal</tt> is suitable to be in
* accord with the Web i.e. not kill the application.
*/
RCTFatalHandler _RCTFatal = ^(NSError *error) {
id jsStackTrace = error.userInfo[RCTJSStackTraceKey];
@try {
NSString *name
= [NSString stringWithFormat:@"%@: %@",
RCTFatalExceptionName,
error.localizedDescription];
NSString *message
= RCTFormatError(error.localizedDescription, jsStackTrace, 75);
[NSException raise:name format:@"%@", message];
} @catch (NSException *e) {
if (!jsStackTrace) {
@throw;
}
}
};
@implementation AppDelegate
// https://facebook.github.io/react-native/docs/linking.html
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler
{
return [RCTLinkingManager application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#if !DEBUG
// In the Release configuration, React Native will (intentionally) raise an
// unhandled NSException for an unhandled JavaScript error. This will
// effectively kill the application. In accord with the Web, do not kill the
// application.
if (!RCTGetFatalHandler()) {
RCTSetFatalHandler(_RCTFatal);
}
#endif
NSURL *jsCodeLocation
= [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios"
fallbackResource:nil];
RCTRootView *rootView
= [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"App"
initialProperties:nil
launchOptions:launchOptions];
// Set a background color which is in accord with the JavaScript and Android
// parts of the application and causes less perceived visual flicker than the
// default background color.
rootView.backgroundColor
= [[UIColor alloc] initWithRed:.07f green:.07f blue:.07f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
// https://facebook.github.io/react-native/docs/linking.html
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
{
return [RCTLinkingManager application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation];
}
@end

View File

@@ -1,24 +0,0 @@
#import "RCTBridgeModule.h"
#import <UIKit/UIKit.h>
@interface Proximity : NSObject<RCTBridgeModule>
@end
@implementation Proximity
RCT_EXPORT_MODULE();
/**
* Enables / disables the proximity sensor monitoring. On iOS enabling the
* proximity sensor automatically dims the screen and disables touch controls,
* so there is nothing else to do (unlike on Android)!
*
* @param enabled {@code YES} to enable proximity (sensor) monitoring;
* {@code NO}, otherwise.
*/
RCT_EXPORT_METHOD(setEnabled:(BOOL)enabled) {
[[UIDevice currentDevice] setProximityMonitoringEnabled:enabled];
}
@end

View File

@@ -0,0 +1,433 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
0B26BE6E1EC5BC3C00EEFB41 /* JitsiMeet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B26BE6D1EC5BC3C00EEFB41 /* JitsiMeet.framework */; };
0B26BE6F1EC5BC3C00EEFB41 /* JitsiMeet.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0B26BE6D1EC5BC3C00EEFB41 /* JitsiMeet.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
0B412F1F1EDEE6E800B1A0A6 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B412F1E1EDEE6E800B1A0A6 /* ViewController.m */; };
0B412F211EDEE95300B1A0A6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0B412F201EDEE95300B1A0A6 /* Main.storyboard */; };
0BD6B4371EF82A6B00D1F4CD /* WebRTC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BD6B4361EF82A6B00D1F4CD /* WebRTC.framework */; };
0BD6B4381EF82A6B00D1F4CD /* WebRTC.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0BD6B4361EF82A6B00D1F4CD /* WebRTC.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
0B26BE701EC5BC3C00EEFB41 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
0B26BE6F1EC5BC3C00EEFB41 /* JitsiMeet.framework in Embed Frameworks */,
0BD6B4381EF82A6B00D1F4CD /* WebRTC.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0B26BE6D1EC5BC3C00EEFB41 /* JitsiMeet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = JitsiMeet.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0B412F1D1EDEE6E800B1A0A6 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
0B412F1E1EDEE6E800B1A0A6 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
0B412F201EDEE95300B1A0A6 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
0BD6B4361EF82A6B00D1F4CD /* WebRTC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebRTC.framework; path = "../../node_modules/react-native-webrtc/ios/WebRTC.framework"; sourceTree = "<group>"; };
13B07F961A680F5B00A75B9A /* jitsi-meet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "jitsi-meet.app"; sourceTree = BUILT_PRODUCTS_DIR; };
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
B3B083EB1D4955FF0069CEE7 /* app.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = app.entitlements; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0B26BE6E1EC5BC3C00EEFB41 /* JitsiMeet.framework in Frameworks */,
0BD6B4371EF82A6B00D1F4CD /* WebRTC.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
0B26BE711EC5BC4D00EEFB41 /* Frameworks */ = {
isa = PBXGroup;
children = (
0B26BE6D1EC5BC3C00EEFB41 /* JitsiMeet.framework */,
0BD6B4361EF82A6B00D1F4CD /* WebRTC.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
13B07FAE1A68108700A75B9A /* src */ = {
isa = PBXGroup;
children = (
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
13B07FB01A68108700A75B9A /* AppDelegate.m */,
13B07FB51A68108700A75B9A /* Images.xcassets */,
13B07FB61A68108700A75B9A /* Info.plist */,
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
13B07FB71A68108700A75B9A /* main.m */,
0B412F201EDEE95300B1A0A6 /* Main.storyboard */,
0B412F1D1EDEE6E800B1A0A6 /* ViewController.h */,
0B412F1E1EDEE6E800B1A0A6 /* ViewController.m */,
);
path = src;
sourceTree = "<group>";
};
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
B3B083EB1D4955FF0069CEE7 /* app.entitlements */,
0B26BE711EC5BC4D00EEFB41 /* Frameworks */,
83CBBA001A601CBA00E9B192 /* Products */,
13B07FAE1A68108700A75B9A /* src */,
);
indentWidth = 2;
sourceTree = "<group>";
tabWidth = 2;
};
83CBBA001A601CBA00E9B192 /* Products */ = {
isa = PBXGroup;
children = (
13B07F961A680F5B00A75B9A /* jitsi-meet.app */,
);
name = Products;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
13B07F861A680F5B00A75B9A /* jitsi-meet */ = {
isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "jitsi-meet" */;
buildPhases = (
0BBA83C41EC9F7600075A103 /* Run React packager */,
13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */,
0B26BE701EC5BC3C00EEFB41 /* Embed Frameworks */,
B35383AD1DDA0083008F406A /* Adjust embedded framework architectures */,
0BB7DA181EC9E695007AAE98 /* Adjust ATS */,
);
buildRules = (
);
dependencies = (
);
name = "jitsi-meet";
productName = "Jitsi Meet";
productReference = 13B07F961A680F5B00A75B9A /* jitsi-meet.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
83CBB9F71A601CBA00E9B192 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0820;
ORGANIZATIONNAME = Facebook;
TargetAttributes = {
13B07F861A680F5B00A75B9A = {
DevelopmentTeam = BQNXB4G3KQ;
SystemCapabilities = {
com.apple.SafariKeychain = {
enabled = 1;
};
};
};
};
};
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "app" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 83CBB9F61A601CBA00E9B192;
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
13B07F861A680F5B00A75B9A /* jitsi-meet */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
13B07F8E1A680F5B00A75B9A /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0B412F211EDEE95300B1A0A6 /* Main.storyboard in Resources */,
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
0BB7DA181EC9E695007AAE98 /* Adjust ATS */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Adjust ATS";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "../scripts/fixup-ats.sh";
};
0BBA83C41EC9F7600075A103 /* Run React packager */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run React packager";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "../scripts/run-packager.sh";
};
B35383AD1DDA0083008F406A /* Adjust embedded framework architectures */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Adjust embedded framework architectures";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "../scripts/fixup-frameworks.sh";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
13B07F871A680F5B00A75B9A /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0B412F1F1EDEE6E800B1A0A6 /* ViewController.m in Sources */,
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
isa = PBXVariantGroup;
children = (
13B07FB21A68108700A75B9A /* Base */,
);
name = LaunchScreen.xib;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = app.entitlements;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = NO;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"../../node_modules/react-native-webrtc/ios",
);
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
);
INFOPLIST_FILE = src/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
"-lc++",
);
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.JitsiMeet.ios;
PRODUCT_NAME = "jitsi-meet";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = app.entitlements;
CURRENT_PROJECT_VERSION = 1;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"../../node_modules/react-native-webrtc/ios",
);
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
);
INFOPLIST_FILE = src/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
"-lc++",
);
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.JitsiMeet.ios;
PRODUCT_NAME = "jitsi-meet";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
83CBBA201A601CBA00E9B192 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_BITCODE = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
);
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
83CBBA211A601CBA00E9B192 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
ENABLE_BITCODE = NO;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
);
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "jitsi-meet" */ = {
isa = XCConfigurationList;
buildConfigurations = (
13B07F941A680F5B00A75B9A /* Debug */,
13B07F951A680F5B00A75B9A /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "app" */ = {
isa = XCConfigurationList;
buildConfigurations = (
83CBBA201A601CBA00E9B192 /* Debug */,
83CBBA211A601CBA00E9B192 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
}

View File

@@ -14,10 +14,10 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "83CBBA2D1A601D0E00E9B192"
BuildableName = "libReact.a"
BlueprintName = "React"
ReferencedContainer = "container:../node_modules/react-native/React/React.xcodeproj">
BlueprintIdentifier = "0BD906E41EC0C00300C8C18E"
BuildableName = "JitsiMeet.framework"
BlueprintName = "JitsiMeet"
ReferencedContainer = "container:../sdk/sdk.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
@@ -31,7 +31,7 @@
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "jitsi-meet.app"
BlueprintName = "jitsi-meet"
ReferencedContainer = "container:jitsi-meet.xcodeproj">
ReferencedContainer = "container:app.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
@@ -49,7 +49,7 @@
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "jitsi-meet.app"
BlueprintName = "jitsi-meet"
ReferencedContainer = "container:jitsi-meet.xcodeproj">
ReferencedContainer = "container:app.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
@@ -72,7 +72,7 @@
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "jitsi-meet.app"
BlueprintName = "jitsi-meet"
ReferencedContainer = "container:jitsi-meet.xcodeproj">
ReferencedContainer = "container:app.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
@@ -91,7 +91,7 @@
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "jitsi-meet.app"
BlueprintName = "jitsi-meet"
ReferencedContainer = "container:jitsi-meet.xcodeproj">
ReferencedContainer = "container:app.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>

View File

@@ -1,18 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

23
ios/app/src/AppDelegate.h Normal file
View File

@@ -0,0 +1,23 @@
/*
* 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.
*/
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;
@end

49
ios/app/src/AppDelegate.m Normal file
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.
*/
#import "AppDelegate.h"
#import <JitsiMeet/JitsiMeet.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
return [JitsiMeetView application:application
didFinishLaunchingWithOptions:launchOptions];
}
#pragma mark Linking delegate methods
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {
return [JitsiMeetView application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
return [JitsiMeetView application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation];
}
@end

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12120" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="u7g-vg-A8m">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="xSm-U5-Hdu">
<objects>
<viewController id="u7g-vg-A8m" customClass="ViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="d40-fc-Y8P"/>
<viewControllerLayoutGuide type="bottom" id="1KD-Ho-g0H"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="QpR-jB-WOw" customClass="JitsiMeetView">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="ZIj-K3-jVH" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="28" y="138"/>
</scene>
</scenes>
</document>

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

Before

Width:  |  Height:  |  Size: 167 KiB

After

Width:  |  Height:  |  Size: 167 KiB

View File

Before

Width:  |  Height:  |  Size: 278 KiB

After

Width:  |  Height:  |  Size: 278 KiB

View File

@@ -61,17 +61,14 @@
<string></string>
<key>NSMicrophoneUsageDescription</key>
<string>Participate in conferences with audio.</string>
<key>UIAppFonts</key>
<array>
<string>jitsi.ttf</string>
<string>FontAwesome.ttf</string>
</array>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
<string>fetch</string>
<string>voip</string>
</array>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>

View File

@@ -0,0 +1,23 @@
/*
* 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.
*/
#import <UIKit/UIKit.h>
#import <JitsiMeet/JitsiMeet.h>
@interface ViewController : UIViewController<JitsiMeetViewDelegate>
@end

View File

@@ -0,0 +1,43 @@
/*
* 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.
*/
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidLoad {
[super viewDidLoad];
JitsiMeetView *view = (JitsiMeetView *) self.view;
view.delegate = self;
// 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.
view.welcomePageEnabled = YES;
[view loadURL:nil];
}
@end

28
ios/app/src/main.m Normal file
View File

@@ -0,0 +1,28 @@
/*
* 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.
*/
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(
argc, argv,
nil,
NSStringFromClass([AppDelegate class]));
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,12 @@
<Workspace
version = "1.0">
<FileRef
location = "group:jitsi-meet.xcodeproj">
location = "group:app/app.xcodeproj">
</FileRef>
<FileRef
location = "group:sdk/sdk.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

36
ios/scripts/fixup-ats.sh Executable file
View File

@@ -0,0 +1,36 @@
#!/bin/bash
# This script gets executed from Xcode to disable ATS (App Transport Security)
# on Debug builds. Doing this allows loading resources over HTTP, such as the
# JS bundle.
set -x
case "$CONFIGURATION" in
Debug)
# Speed up build times by skipping the creation of the offline package for debug
# builds on the simulator since the packager is supposed to be running anyways.
if [[ "$PLATFORM_NAME" == *simulator ]]; then
echo "Skipping bundling for Simulator platform"
exit 0;
fi
DEV=true
;;
"")
echo "$0 must be invoked by Xcode"
exit 1
;;
*)
DEV=false
;;
esac
DEST=$CONFIGURATION_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH
if [[ "$CONFIGURATION" = "Debug" && ! "$PLATFORM_NAME" == *simulator ]]; then
PLISTBUDDY='/usr/libexec/PlistBuddy'
PLIST=$TARGET_BUILD_DIR/$INFOPLIST_PATH
`$PLISTBUDDY -c "Add NSAppTransportSecurity:NSAllowsArbitraryLoads bool true" "$PLIST"` || true
fi

39
ios/scripts/fixup-frameworks.sh Executable file
View File

@@ -0,0 +1,39 @@
#!/bin/bash
# This script gets executed from Xcode to fixup the embedded frameworks and
# bundle the necessary architectures.
APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"
# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
EXTRACTED_ARCHS=()
for ARCH in $ARCHS
do
if lipo -info "$FRAMEWORK_EXECUTABLE_PATH" | grep -q -v "^Non-fat"
then
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
fi
done
if [ -n "$EXTRACTED_ARCHS" ]
then
echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"
echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
fi
done

16
ios/scripts/run-packager.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/bash
# This script is executed from Xcode to start the React packager for Debug
# targets.
if [[ "$CONFIGURATION" = "Debug" ]]; then
if nc -w 5 -z localhost 8081 ; then
if ! curl -s "http://localhost:8081/status" | grep -q "packager-status:running" ; then
echo "Port 8081 already in use, packager is either not running or not running correctly"
exit 2
fi
else
open -g "$SRCROOT/../../node_modules/react-native/packager/launchPackager.command" || echo "Can't start packager automatically"
fi
fi

View File

@@ -0,0 +1,436 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
0B412F181EDEC65D00B1A0A6 /* JitsiMeetView.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B412F161EDEC65D00B1A0A6 /* JitsiMeetView.h */; settings = {ATTRIBUTES = (Public, ); }; };
0B412F191EDEC65D00B1A0A6 /* JitsiMeetView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B412F171EDEC65D00B1A0A6 /* JitsiMeetView.m */; };
0B412F221EDEF6EA00B1A0A6 /* JitsiMeetViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B412F1B1EDEC80100B1A0A6 /* JitsiMeetViewDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
0B93EF7B1EC608550030D24D /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B93EF7A1EC608550030D24D /* CoreText.framework */; };
0B93EF7E1EC9DDCD0030D24D /* RCTBridgeWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B93EF7C1EC9DDCD0030D24D /* RCTBridgeWrapper.h */; };
0B93EF7F1EC9DDCD0030D24D /* RCTBridgeWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B93EF7D1EC9DDCD0030D24D /* RCTBridgeWrapper.m */; };
0BA13D311EE83FF8007BEF7F /* ExternalAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BA13D301EE83FF8007BEF7F /* ExternalAPI.m */; };
0BCA495F1EC4B6C600B793EE /* AudioMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495C1EC4B6C600B793EE /* AudioMode.m */; };
0BCA49601EC4B6C600B793EE /* POSIX.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495D1EC4B6C600B793EE /* POSIX.m */; };
0BCA49611EC4B6C600B793EE /* Proximity.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495E1EC4B6C600B793EE /* Proximity.m */; };
0BCA496C1EC4BBF900B793EE /* jitsi.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 0BCA496B1EC4BBF900B793EE /* jitsi.ttf */; };
0BD906EA1EC0C00300C8C18E /* JitsiMeet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BD906E81EC0C00300C8C18E /* JitsiMeet.h */; settings = {ATTRIBUTES = (Public, ); }; };
0F65EECE1D95DA94561BB47E /* libPods-JitsiMeet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 03F2ADC957FF109849B7FCA1 /* libPods-JitsiMeet.a */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
03F2ADC957FF109849B7FCA1 /* libPods-JitsiMeet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-JitsiMeet.a"; sourceTree = BUILT_PRODUCTS_DIR; };
0B412F161EDEC65D00B1A0A6 /* JitsiMeetView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JitsiMeetView.h; sourceTree = "<group>"; };
0B412F171EDEC65D00B1A0A6 /* JitsiMeetView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JitsiMeetView.m; sourceTree = "<group>"; };
0B412F1B1EDEC80100B1A0A6 /* JitsiMeetViewDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeetViewDelegate.h; sourceTree = "<group>"; };
0B93EF7A1EC608550030D24D /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; };
0B93EF7C1EC9DDCD0030D24D /* RCTBridgeWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTBridgeWrapper.h; sourceTree = "<group>"; };
0B93EF7D1EC9DDCD0030D24D /* RCTBridgeWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTBridgeWrapper.m; sourceTree = "<group>"; };
0BA13D301EE83FF8007BEF7F /* ExternalAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExternalAPI.m; sourceTree = "<group>"; };
0BCA495C1EC4B6C600B793EE /* AudioMode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioMode.m; sourceTree = "<group>"; };
0BCA495D1EC4B6C600B793EE /* POSIX.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = POSIX.m; sourceTree = "<group>"; };
0BCA495E1EC4B6C600B793EE /* Proximity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Proximity.m; sourceTree = "<group>"; };
0BCA49631EC4B76D00B793EE /* WebRTC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebRTC.framework; path = "../../node_modules/react-native-webrtc/ios/WebRTC.framework"; sourceTree = "<group>"; };
0BCA496B1EC4BBF900B793EE /* jitsi.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = jitsi.ttf; path = ../../fonts/jitsi.ttf; sourceTree = "<group>"; };
0BD906E51EC0C00300C8C18E /* JitsiMeet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JitsiMeet.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0BD906E81EC0C00300C8C18E /* JitsiMeet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeet.h; sourceTree = "<group>"; };
0BD906E91EC0C00300C8C18E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
98E09B5C73D9036B4ED252FC /* Pods-JitsiMeet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.debug.xcconfig"; sourceTree = "<group>"; };
9C77CA3CC919B081F1A52982 /* Pods-JitsiMeet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.release.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
0BD906E11EC0C00300C8C18E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0B93EF7B1EC608550030D24D /* CoreText.framework in Frameworks */,
0F65EECE1D95DA94561BB47E /* libPods-JitsiMeet.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
0BCA49681EC4BBE500B793EE /* Resources */ = {
isa = PBXGroup;
children = (
0BCA496B1EC4BBF900B793EE /* jitsi.ttf */,
);
name = Resources;
sourceTree = "<group>";
};
0BD906DB1EC0C00300C8C18E = {
isa = PBXGroup;
children = (
9C3C6FA2341729836589B856 /* Frameworks */,
C5E72ADFC30ED96F9B35F076 /* Pods */,
0BD906E61EC0C00300C8C18E /* Products */,
0BCA49681EC4BBE500B793EE /* Resources */,
0BD906E71EC0C00300C8C18E /* src */,
);
sourceTree = "<group>";
};
0BD906E61EC0C00300C8C18E /* Products */ = {
isa = PBXGroup;
children = (
0BD906E51EC0C00300C8C18E /* JitsiMeet.framework */,
);
name = Products;
sourceTree = "<group>";
};
0BD906E71EC0C00300C8C18E /* src */ = {
isa = PBXGroup;
children = (
0BCA495C1EC4B6C600B793EE /* AudioMode.m */,
0BA13D301EE83FF8007BEF7F /* ExternalAPI.m */,
0BD906E91EC0C00300C8C18E /* Info.plist */,
0BD906E81EC0C00300C8C18E /* JitsiMeet.h */,
0B412F161EDEC65D00B1A0A6 /* JitsiMeetView.h */,
0B412F171EDEC65D00B1A0A6 /* JitsiMeetView.m */,
0B412F1B1EDEC80100B1A0A6 /* JitsiMeetViewDelegate.h */,
0B93EF7C1EC9DDCD0030D24D /* RCTBridgeWrapper.h */,
0B93EF7D1EC9DDCD0030D24D /* RCTBridgeWrapper.m */,
0BCA495D1EC4B6C600B793EE /* POSIX.m */,
0BCA495E1EC4B6C600B793EE /* Proximity.m */,
);
path = src;
sourceTree = "<group>";
};
9C3C6FA2341729836589B856 /* Frameworks */ = {
isa = PBXGroup;
children = (
0B93EF7A1EC608550030D24D /* CoreText.framework */,
0BCA49631EC4B76D00B793EE /* WebRTC.framework */,
03F2ADC957FF109849B7FCA1 /* libPods-JitsiMeet.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
C5E72ADFC30ED96F9B35F076 /* Pods */ = {
isa = PBXGroup;
children = (
98E09B5C73D9036B4ED252FC /* Pods-JitsiMeet.debug.xcconfig */,
9C77CA3CC919B081F1A52982 /* Pods-JitsiMeet.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
0BD906E21EC0C00300C8C18E /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
0B412F181EDEC65D00B1A0A6 /* JitsiMeetView.h in Headers */,
0B93EF7E1EC9DDCD0030D24D /* RCTBridgeWrapper.h in Headers */,
0B412F221EDEF6EA00B1A0A6 /* JitsiMeetViewDelegate.h in Headers */,
0BD906EA1EC0C00300C8C18E /* JitsiMeet.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
0BD906E41EC0C00300C8C18E /* JitsiMeet */ = {
isa = PBXNativeTarget;
buildConfigurationList = 0BD906ED1EC0C00300C8C18E /* Build configuration list for PBXNativeTarget "JitsiMeet" */;
buildPhases = (
26796D8589142D80C8AFDA51 /* [CP] Check Pods Manifest.lock */,
0BD906E01EC0C00300C8C18E /* Sources */,
0BD906E11EC0C00300C8C18E /* Frameworks */,
0BD906E21EC0C00300C8C18E /* Headers */,
0BD906E31EC0C00300C8C18E /* Resources */,
0BCA49651EC4B77500B793EE /* Package React bundle */,
C7BC10B338C94EEB98048E64 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
);
name = JitsiMeet;
productName = "Jitsi Meet SDK";
productReference = 0BD906E51EC0C00300C8C18E /* JitsiMeet.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
0BD906DC1EC0C00300C8C18E /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0830;
ORGANIZATIONNAME = Jitsi;
TargetAttributes = {
0BD906E41EC0C00300C8C18E = {
CreatedOnToolsVersion = 8.3.2;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = 0BD906DF1EC0C00300C8C18E /* Build configuration list for PBXProject "sdk" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 0BD906DB1EC0C00300C8C18E;
productRefGroup = 0BD906E61EC0C00300C8C18E /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
0BD906E41EC0C00300C8C18E /* JitsiMeet */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
0BD906E31EC0C00300C8C18E /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0BCA496C1EC4BBF900B793EE /* jitsi.ttf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
0BCA49651EC4B77500B793EE /* Package React bundle */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Package React bundle";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "export NODE_BINARY=node\n../../node_modules/react-native/packager/react-native-xcode.sh";
};
26796D8589142D80C8AFDA51 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
C7BC10B338C94EEB98048E64 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet-resources.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
0BD906E01EC0C00300C8C18E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0B93EF7F1EC9DDCD0030D24D /* RCTBridgeWrapper.m in Sources */,
0BA13D311EE83FF8007BEF7F /* ExternalAPI.m in Sources */,
0BCA49601EC4B6C600B793EE /* POSIX.m in Sources */,
0BCA495F1EC4B6C600B793EE /* AudioMode.m in Sources */,
0BCA49611EC4B6C600B793EE /* Proximity.m in Sources */,
0B412F191EDEC65D00B1A0A6 /* JitsiMeetView.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
0BD906EB1EC0C00300C8C18E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_BITCODE = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
0BD906EC1EC0C00300C8C18E /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_BITCODE = NO;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
0BD906EE1EC0C00300C8C18E /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 98E09B5C73D9036B4ED252FC /* Pods-JitsiMeet.debug.xcconfig */;
buildSettings = {
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = src/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.JitsiMeetSDK.ios;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
};
name = Debug;
};
0BD906EF1EC0C00300C8C18E /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9C77CA3CC919B081F1A52982 /* Pods-JitsiMeet.release.xcconfig */;
buildSettings = {
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = src/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.JitsiMeetSDK.ios;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
0BD906DF1EC0C00300C8C18E /* Build configuration list for PBXProject "sdk" */ = {
isa = XCConfigurationList;
buildConfigurations = (
0BD906EB1EC0C00300C8C18E /* Debug */,
0BD906EC1EC0C00300C8C18E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
0BD906ED1EC0C00300C8C18E /* Build configuration list for PBXNativeTarget "JitsiMeet" */ = {
isa = XCConfigurationList;
buildConfigurations = (
0BD906EE1EC0C00300C8C18E /* Debug */,
0BD906EF1EC0C00300C8C18E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 0BD906DC1EC0C00300C8C18E /* Project object */;
}

View File

@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0830"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0BD906E41EC0C00300C8C18E"
BuildableName = "JitsiMeet.framework"
BlueprintName = "JitsiMeet"
ReferencedContainer = "container:sdk.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0BD906E41EC0C00300C8C18E"
BuildableName = "JitsiMeet.framework"
BlueprintName = "JitsiMeet"
ReferencedContainer = "container:sdk.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0BD906E41EC0C00300C8C18E"
BuildableName = "JitsiMeet.framework"
BlueprintName = "JitsiMeet"
ReferencedContainer = "container:sdk.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
<PostActions>
<ExecutionAction
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
<ActionContent
title = "Run Script"
scriptText = "exec &gt; /tmp/${PROJECT_NAME}_archive.log 2&gt;&amp;1&#10;&#10;UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal&#10;&#10;if [ &quot;true&quot; == ${ALREADYINVOKED:-false} ]&#10;then&#10;echo &quot;RECURSION: Detected, stopping&quot;&#10;else&#10;export ALREADYINVOKED=&quot;true&quot;&#10;&#10;# make sure the output directory exists&#10;mkdir -p &quot;${UNIVERSAL_OUTPUTFOLDER}&quot;&#10;&#10;echo &quot;Building for iPhoneSimulator&quot;&#10;xcodebuild -workspace &quot;${WORKSPACE_PATH}&quot; -scheme &quot;${TARGET_NAME}&quot; -configuration ${CONFIGURATION} -sdk iphonesimulator -destination &apos;platform=iOS Simulator,name=iPhone 6&apos; ONLY_ACTIVE_ARCH=NO ARCHS=&apos;i386 x86_64&apos; BUILD_DIR=&quot;${BUILD_DIR}&quot; BUILD_ROOT=&quot;${BUILD_ROOT}&quot; ENABLE_BITCODE=YES OTHER_CFLAGS=&quot;-fembed-bitcode&quot; BITCODE_GENERATION_MODE=bitcode clean build&#10;&#10;# Step 1. Copy the framework structure (from iphoneos build) to the universal folder&#10;echo &quot;Copying to output folder&quot;&#10;cp -R &quot;${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/${FULL_PRODUCT_NAME}&quot; &quot;${UNIVERSAL_OUTPUTFOLDER}/&quot;&#10;&#10;# Step 2. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory&#10;SIMULATOR_SWIFT_MODULES_DIR=&quot;${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/Modules/${TARGET_NAME}.swiftmodule/.&quot;&#10;if [ -d &quot;${SIMULATOR_SWIFT_MODULES_DIR}&quot; ]; then&#10;cp -R &quot;${SIMULATOR_SWIFT_MODULES_DIR}&quot; &quot;${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Modules/${TARGET_NAME}.swiftmodule&quot;&#10;fi&#10;&#10;# Step 3. Create universal binary file using lipo and place the combined executable in the copied framework directory&#10;echo &quot;Combining executables&quot;&#10;lipo -create -output &quot;${UNIVERSAL_OUTPUTFOLDER}/${EXECUTABLE_PATH}&quot; &quot;${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${EXECUTABLE_PATH}&quot; &quot;${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/${EXECUTABLE_PATH}&quot;&#10;&#10;# Step 4. Create universal binaries for embedded frameworks&#10;#for SUB_FRAMEWORK in $( ls &quot;${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Frameworks&quot; ); do&#10;#BINARY_NAME=&quot;${SUB_FRAMEWORK%.*}&quot;&#10;#lipo -create -output &quot;${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}&quot; &quot;${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${SUB_FRAMEWORK}/${BINARY_NAME}&quot; &quot;${ARCHIVE_PRODUCTS_PATH}${INSTALL_PATH}/${TARGET_NAME}.framework/Frameworks/${SUB_FRAMEWORK}/${BINARY_NAME}&quot;&#10;#done&#10;&#10;# Step 5. Convenience step to copy the framework to the project&apos;s directory&#10;echo &quot;Copying to project dir&quot;&#10;yes | cp -Rf &quot;${UNIVERSAL_OUTPUTFOLDER}/${FULL_PRODUCT_NAME}&quot; &quot;${PROJECT_DIR}&quot;&#10;&#10;open &quot;${PROJECT_DIR}&quot;&#10;&#10;fi">
<EnvironmentBuildable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0BD906E41EC0C00300C8C18E"
BuildableName = "JitsiMeet.framework"
BlueprintName = "JitsiMeet"
ReferencedContainer = "container:sdk.xcodeproj">
</BuildableReference>
</EnvironmentBuildable>
</ActionContent>
</ExecutionAction>
</PostActions>
</ArchiveAction>
</Scheme>

View File

@@ -1,3 +1,19 @@
/*
* 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.
*/
#import "RCTBridgeModule.h"
#import "RCTLog.h"

77
ios/sdk/src/ExternalAPI.m Normal file
View File

@@ -0,0 +1,77 @@
/*
* 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.
*/
#import "RCTBridgeModule.h"
#import "JitsiMeetView+Private.h"
@interface ExternalAPI : NSObject<RCTBridgeModule>
@end
@implementation ExternalAPI
RCT_EXPORT_MODULE();
/**
* Dispatches an event that occurred on JavaScript to the view's delegate.
*
* @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
*/
RCT_EXPORT_METHOD(sendEvent:(NSString *)name
data:(NSDictionary *)data
scope:(NSString *)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 viewForExternalAPIScope:scope];
if (!view) {
return;
}
id delegate = view.delegate;
if (!delegate) {
return;
}
if ([name isEqualToString:@"CONFERENCE_FAILED"]
&& [delegate respondsToSelector:@selector(conferenceFailed:)]) {
[delegate conferenceFailed:data];
} else if ([name isEqualToString:@"CONFERENCE_JOINED"]
&& [delegate respondsToSelector:@selector(conferenceJoined:)]) {
[delegate conferenceJoined:data];
} else if ([name isEqualToString:@"CONFERENCE_LEFT"]
&& [delegate respondsToSelector:@selector(conferenceLeft:)]) {
[delegate conferenceLeft:data];
} else if ([name isEqualToString:@"CONFERENCE_WILL_JOIN"]
&& [delegate respondsToSelector:@selector(conferenceWillJoin:)]) {
[delegate conferenceWillJoin:data];
} else if ([name isEqualToString:@"CONFERENCE_WILL_LEAVE"]
&& [delegate respondsToSelector:@selector(conferenceWillLeave:)]) {
[delegate conferenceWillLeave:data];
}
}
@end

29
ios/sdk/src/Info.plist Normal file
View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
<key>JitsiMeetFonts</key>
<array>
<string>FontAwesome.ttf</string>
<string>jitsi.ttf</string>
</array>
</dict>
</plist>

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