Compare commits

...

263 Commits

Author SHA1 Message Date
Aaron van Meerten
e48ddc28eb updated node-sass version for npm 10 2018-11-20 16:39:41 -06:00
Bettenbuk Zoltan
71edea8aac Rearrange recording feature files 2018-11-20 14:42:33 +01:00
Bettenbuk Zoltan
2b1cb75e40 [RN] Update react-native-calendar-events lib
This is required to get rid of a warning after react native update. See related commit in lib.
2018-11-19 14:35:22 +01:00
damencho
216782d606 Commit from translate.jitsi.org by user damencho.: 583 of 583 strings translated (0 fuzzy). 2018-11-14 03:33:01 +00:00
Emil Ivov
c707b82419 Replacing Atlassian with 8x8 2018-11-11 08:43:34 -06:00
Bettenbuk Zoltan
3fdf944763 Fix eslint/jsdoc warnings (doc change only!) 2018-11-08 15:52:34 +01:00
virtuacoplenny
56100d0d5c Merge pull request #3594 from mmoanis/update-docs
Update docs for AbstractRecordButton _mapStateToProps
2018-11-07 09:20:05 -08:00
Leonard Kim
486e8e35d9 ref: move all prop type declaration to flow
For the most part the changes are taking the "static propTypes" declaration off
of components and declaring them as Flow types. Sometimes to support flow some
method signatures had to be added. There are some exceptions in which more had
to be done to tame the beast:
- AbstractVideoTrack: put in additional truthy checks for videoTrack.
- Video: add truthy checks for the _videoElement ref.
- shouldRenderVideoTrack function: Some component could pass null for the
  videoTrack argument and Flow wanted that called out explicitly.
- DisplayName: Add a truthy check for the input ref before acting on it.
- NumbersList: Move array checks inline for Flow to comprehend array methods
  could be called. Add type checks in the Object.entries loop as the value is
  assumed to be a mixed type by Flow.
- AbstractToolbarButton: add additional truthy check for passed in type.
2018-11-07 17:38:10 +01:00
Bettenbuk Zoltan
554974a36d [RN] Fix YouTube channel name list 2018-11-07 16:48:56 +01:00
mmoanis
cd943319d6 Update docs for AbstractRecordButton _mapStateToProps 2018-11-06 11:36:00 +01:00
Дамян Минков
837f496e8f Moves muc definition to be last.
Fixes common problem where people following https://github.com/jitsi/jicofo#secure-domain have a syntax error, forgetting the comma after muc definition.
2018-11-06 09:55:32 +01:00
Aaron van Meerten
c43f7c8979 Merge pull request #3589 from jitsi/max-occupants
Adds max occupant module.
2018-11-03 11:37:14 -05:00
damencho
c9c9f7eac0 Adds max occupant module. 2018-11-03 10:45:59 -05:00
Leonard Kim
5ccc397e47 chore(deps): update react-i18next from 4.8.0 to 7.13.0
None of the breaking changes seemed to affect current
usage of react-i18next and light testing of features
and language switching did not produce issues.

This update is a pre-requisite for removing deprecated react
lifecycle methods, as older versions of react-i18next
have a higher order component that uses the deprecated
componentWillMount, and that issue has been fixed since 7.8.0.
2018-10-29 20:49:53 +01:00
hristoterezov
00cd82d976 fix(analytics-ga): Ignore some events 2018-10-22 16:18:47 -05:00
hristoterezov
61deb74444 fix(welcome-page): Change text 2018-10-22 16:18:30 -05:00
Hristo Terezov
b30008e3a5 feat(welcome-page): Redesign. (#3559)
* feat(welcome-page): Redesign.

* Style adjustments.
2018-10-22 13:49:18 -05:00
bgrozev
62b6737a3f fix: Filter more events for google analytics. (#3557) 2018-10-18 17:15:27 -05:00
damencho
cd77a9176c Make sure we do only one replacement, not one over another for messages. 2018-10-18 23:37:07 +02:00
damencho
2a61968566 Fixes small video's top toolbar background in dark theme. 2018-10-18 09:51:10 +02:00
yanas
be4813e10d Revert "feat(cleanup): remove no longer used FontAwesome"
This reverts commit d3c5756f7a.
2018-10-17 16:27:18 -05:00
Saúl Ibarra Corretgé
ae890dc093 deps: update react-native-webrtc (M69) 2018-10-16 16:32:26 +02:00
Saúl Ibarra Corretgé
9407f562f6 [iOS] Simplify dynamically loading fonts 2018-10-16 14:33:48 +02:00
Saúl Ibarra Corretgé
011a46ce2d [RN] Don't bundle fonts we don't use 2018-10-16 14:33:48 +02:00
Saúl Ibarra Corretgé
8e0bd36ece deps: update react-native-vector-icons 2018-10-16 14:33:48 +02:00
Saúl Ibarra Corretgé
6f8743af3a doc: update Google SignIn integration documentation 2018-10-16 14:01:11 +02:00
paweldomas
58d220d645 deps: update LJM to fix grey overlay
Updates LJM to fix grey overlay with "user is having connectivity
issues" caused by remote track overwrite.
2018-10-16 09:58:42 +02:00
Saúl Ibarra Corretgé
d3c5756f7a feat(cleanup): remove no longer used FontAwesome 2018-10-15 14:14:25 -05:00
Saúl Ibarra Corretgé
5ff1ce5a60 [iOS] Don't show google signin button on iOS <= 10
It doesn't seem to work properly.
2018-10-12 13:17:29 -05:00
Saúl Ibarra Corretgé
843f08f38e [RN] Don't show a beta label for recordings 2018-10-12 12:03:32 -05:00
Saúl Ibarra Corretgé
418575136f [RN] Don't use webClientId on mobile
That is only required if we'd want our backend to authenticate on behalf of our
users. If the app is to authenticate directly it's not needed.
2018-10-12 13:08:20 +02:00
Saúl Ibarra Corretgé
8c97ce2ee9 deps: update react-native-google-signin 2018-10-12 13:08:20 +02:00
Saúl Ibarra Corretgé
b2245729cc [iOS] Update Podfile.lock 2018-10-12 13:08:20 +02:00
Saúl Ibarra Corretgé
cc2b5a261b deps: update lib-jitsi-meet 2018-10-10 18:07:36 +02:00
Saúl Ibarra Corretgé
13c4ec884b deps: update package-lock.json
It's impossible to avoid conflicts on a long lived PR like this. Sigh.
2018-10-10 18:07:36 +02:00
Saúl Ibarra Corretgé
7162080d00 feat(flow): tame the beast 2018-10-10 18:07:36 +02:00
Saúl Ibarra Corretgé
b71adbdf70 deps: update React Native to version 0.57 2018-10-10 18:07:36 +02:00
Saúl Ibarra Corretgé
2ae2f04f0a feat(eslint): tame the beast 2018-10-10 18:07:36 +02:00
Saúl Ibarra Corretgé
4424c456a9 deps: update eslint
This is required due to the Babel update.
2018-10-10 18:07:36 +02:00
Saúl Ibarra Corretgé
cfa1e2f90d deps: update to Babel 7 2018-10-10 18:07:36 +02:00
Saúl Ibarra Corretgé
d290d28248 feat(Audio): fix react warning 2018-10-10 18:07:36 +02:00
Saúl Ibarra Corretgé
0474031a78 deps: update react and styled-components 2018-10-10 18:07:36 +02:00
paweldomas
a57a5ca49d chore(Travis): use XCode 10 image 2018-10-09 17:54:40 -05:00
Bettenbuk Zoltan
d8c1f107da [RN] Add swipe to delete feature 2018-10-09 13:35:06 +02:00
Saúl Ibarra Corretgé
9d27c36d80 config: remove no longer used option 2018-10-08 11:31:47 -05:00
Saúl Ibarra Corretgé
057b300074 feat(Participant): reuse avatar URL generation logic
It was moved to js-utils, so make use of it.
2018-10-05 17:15:00 +02:00
Bettenbuk Zoltan
e164a23cf0 [RN] Fix start recording dialog after dropbox changes 2018-10-04 12:10:28 -05:00
Bettenbuk Zoltan
61456b0d99 Handle all day events in calendar 2018-10-04 16:21:51 +02:00
damencho
df55448a2c Fixes chat image links to reflect html base. 2018-10-03 14:44:33 -05:00
Bettenbuk Zoltan
6953569629 Fix sticky recording labels 2018-10-03 12:52:21 +02:00
hristoterezov
4d2614660c fix(recording): Show the button when the dropbox integration is disabled 2018-10-02 13:50:05 -05:00
Bettenbuk Zoltan
60f7ba7301 [RN] Remove mobile notifications 2018-10-02 20:47:41 +02:00
Bettenbuk Zoltan
e5cc732b72 [RN] Add ExpandedLabel 2018-10-02 20:47:41 +02:00
Bettenbuk Zoltan
d604cdfe27 Turn TranscribingLabel a self-containing component 2018-10-02 20:47:41 +02:00
Lars Spaenij
dc90800e50 Removed unnecessary string wrapping (#3490)
* Removed unnecessary string wrapping
2018-10-01 22:39:16 -05:00
Saúl Ibarra Corretgé
6f17988d17 [iOS] Fix warning (#3491)
When a native iOS module implements `constantsToExport` it must define
`requiresMainQueueSetup`. In this case we don't do any UI stuff so it doesn't
need to be initialized in the main thread.
2018-10-01 21:47:48 -05:00
Saúl Ibarra Corretgé
c54db8337d [iOS] Unify openURL methods and mark the old one deprecated (#3489)
Make sure both methods offer the same behavior and mark the old one as
deprecated so SDK users get a warning.
2018-09-28 14:54:09 -05:00
Дамян Минков
9a1e9fff98 Updates quick-install with instructions for systemd config. (#3488)
Fixes too many open files.
2018-09-27 16:58:10 -05:00
hristoterezov
a214be0dfe doc(dropbox): Add documentation for the mobile app. 2018-09-27 01:42:59 -05:00
hristoterezov
39a22effb1 fix(build.gradle): Move dropboxAppKey definition to defaultConfig 2018-09-27 01:42:59 -05:00
hristoterezov
ca600928f5 feat(build.gradle): Use the Dropbox app key specified in Info.plist. 2018-09-27 01:42:59 -05:00
hristoterezov
60decf7692 ref(dropbox): Consistency for the naming around the app key. 2018-09-27 01:42:59 -05:00
hristoterezov
467452d110 fix(deeplinking): After braking it with the dropbox implementation. 2018-09-27 01:42:59 -05:00
hristoterezov
af37141e3d feat(dropbox): For mobile.
This involves redesign of the web recording dialog in order to look the
same as the mobile one.
2018-09-27 01:42:59 -05:00
hristoterezov
ae7a882188 feat(Switch): Implement 2018-09-27 01:42:59 -05:00
hristoterezov
a49e590e7c feat(LoadingIndicator): Implementation for web. 2018-09-27 01:42:59 -05:00
hristoterezov
1928efda11 fix(web/Text): p->span 2018-09-27 01:42:59 -05:00
hristoterezov
57bf165ebd doc(config): dropbox 2018-09-27 01:42:59 -05:00
hristoterezov
38517127c3 feat(dropbox): Implement react-native module. 2018-09-27 01:42:59 -05:00
Pratik Shah
b7b43e8d9c feat(chat): convert to use React
- Change "features/chat" to support listening for new chat messages
  and storing them, removing that logic from conference.js.
- Combine chat.scss and side_toolbar_container.css, and remove unused
  scss files. Chat is the only side panel so the two concepts have
  been merged.
- Remove direct access to the chat feature from non-react and non-redux
  flows.
- Modify the i18n translate function to take in an options object.
  By default the option "wait" is set to true, but that causes
  components to mount after the parent has been notified of
  an update, which means autoscrolling down to the latest rendered
  messages does not work. With "wait" set to false, the children
  will mount and then the parent will trigger componentDidUpdate.
- Create react components for chat. Chat is the side panel
  plus the entiren chat feature. ChatInput is a child of Chat and
  is used for composing messages. ChatMessage displays one message
  and extends PureComponent to limit re-renders.
- Fix a bug where the toolbar was not showing automatically when
  chat is closed and a new message is received.
- Import react-transition-group to time the animation of the
  side panel showing/hiding and unmounting the Chat component.
  This gets around the issue of having to control autofocus if the
  component were always mounted and visibility toggled, but
  introduces not being able to store previous scroll state
  (without additional work or re-work).
2018-09-26 14:48:10 -05:00
Zoltan Bettenbuk
8adc8a090a [RN] Fix duplicated notifications (#3479) 2018-09-26 11:06:26 -05:00
jakob
8c23d43a3a doc: add ubuntu universe repo note to quickinstall
Recent Ubuntus come with only main repositories enabled. See #3427.
2018-09-25 11:12:04 -05:00
bgrozev
5773bc48ed fix: Filters out e2e_rtt events for google analytics. (#3476) 2018-09-25 11:00:46 -05:00
paweldomas
9613755055 fix(Travis/iOS): use '-quiet' with 'xcodebuild' commands
This reduces 'xcodebuild' verbosity and fixed problem with exceeding 4MB
of logs size imposed by Travis CI.
2018-09-24 14:34:11 -05:00
virtuacoplenny
1fbc68d0cc Merge pull request #3471 from saghul/update-ljm
deps: update lib-jitsi-meet dependency
2018-09-21 09:01:42 -07:00
Bettenbuk Zoltan
2cbe7922f6 [RN] Dialogs: Replace legacy common style with common container 2018-09-21 15:22:27 +02:00
Saúl Ibarra Corretgé
a712e26ee2 deps: update lib-jitsi-meet dependency 2018-09-21 15:18:46 +02:00
Saúl Ibarra Corretgé
b673c4a11a feat(permissions): adjust to changes in permissions checking 2018-09-21 11:35:16 +02:00
paweldomas
8282873de5 fix(travis): tail last 500 lines of logs only on failure
This is a workaround suggested by Travis support to workaround the
"The job exceeded the maximum log length, and has been terminated."
error.

Another option would be to upload the logs somewhere, but actually it
might be more convenient not having to scroll down all those logs. We
can revisit this case if some problems will be encountered (like for
example if there's need to see something in the middle).
2018-09-20 14:49:19 -05:00
Saúl Ibarra Corretgé
2101f70a09 cleanup: remove no longer used code 🔥🔥🔥
The code for handling device availability has been disabled for a long time,
plus it's ill named since it represents 2 abstractions: lack of permissions and
lack of devices.

Time for it to rest in the git graveyard.
2018-09-19 15:12:31 +00:00
hristoterezov
717fade79c ref(proguard): Create common proguard config. 2018-09-18 14:37:05 -05:00
hristoterezov
959e687ed4 feat(proguard): Add crashlytics rules 2018-09-18 14:37:05 -05:00
hristoterezov
5f5adc3fa8 feat(proguard): enable 2018-09-18 14:37:05 -05:00
bgrozev
f317f993fd chore: Updates lib-jitsi-meet to 51a982a7c8b9c3e89be75b0fdf7fedf4748a7345. (#3463) 2018-09-18 12:45:05 -05:00
Zoltan Bettenbuk
b2baab573e Package lock changes for atlaskit (#3462) 2018-09-18 10:20:23 -05:00
virtuacoplenny
12ed711cce Merge pull request #3457 from bgrozev/update-lib-jitsi-meet
chore: Updates lib-jitsi-meet to 615934a78afb3b501976263f5f916efed7af…
2018-09-17 20:50:11 -07:00
Boris Grozev
dfbd8d71ad chore: Updates lib-jitsi-meet to 615934a78afb3b501976263f5f916efed7af0080. 2018-09-17 22:10:48 -05:00
bgrozev
d051d3450d Displays the region participants are connected to (#3451)
* feat: Displays the server region in the stats panels.

* feat: Displays the server count in the local stats panel.

* ref: Renames a variable.

* fix: Makes bridgeCount a number, clarifies docs.

* chore: Updates lib-jitsi-meet to 1ac6df97e3aa5ff880129a95754d491d89ea8c25.
2018-09-17 13:21:03 -05:00
Leonard Kim
7c88de20fe feat(deps): update atlaskit/tabs to 8.0.8
There are (at least) two changes that are breaking:
- defaultTab is gone
- The re-rendering logic looks to have been re-written so that
  passing in a new array of tabs causes a re-render, which can
  reset the currently selected tab.

The fixes involved removing defaultTab from each tab configuration,
as it is no longer respected anyway. Also, instead of letting Tabs
be uncontrolled and allowing it to set its own selected, which
would result in the first tab automatically being selected on
Tabs re-render, use Tabs a controlled prop to dicate which
tab is selected; this is accomplished by specifying a selected
prop.
2018-09-14 14:50:08 -05:00
Leonard Kim
7b71482b03 feat(deps): update atlaskit/dropdown-menu to 6.1.12
This is a pre-requisite to updating atlaskit/tabs to 8.0.8.
Without updating, clicking a dropdown menu within a tab
component within a modal, such as the language selector in
the settings dialog, will lock the browser.
2018-09-14 14:50:08 -05:00
bgrozev
2339f232a5 Merge pull request #3435 from jitsi/recording_analytics
feat(recording): Add analytics.
2018-09-14 14:45:33 -05:00
Leonard Kim
3bb3b4500d provide the exact classname match the tests are looking for 2018-09-14 14:40:41 -05:00
Leonard Kim
0fca0f392d feat(filmstrip): reactify the filmstrip toggle button 2018-09-14 14:40:41 -05:00
virtuacoplenny
c25d6eb9a8 [RN] Implement tile view
* feat(tile-view): initial implementation for mobile

- Create a tile view component for displaying thumbnails in a
  two-dimensional grid.
- Update the existing TileViewButton so it shows a label in the
  overflow menu.
- Modify conference so it can display TileView while hiding
  Filmstrip.
- Modify Thumbnail so its width/height can be set and to prevent
  pinning while in tile view mode.

* use style array for thumbnail styles

* change ternary to math.min for expressiveness

* use dimensiondetector

* pass explicit disableTint prop

* use makeAspectRatioAware instead of aspectRatio prop

* update docs

* fix docs again (fix laziest copy/paste job I've ever done)

* large-video: rename onPress prop to onClick

* change forEach to for...of

* use truthy check fallthrough logic instead of explicit if

* put tile view button second to last in menu

* move spacer to a constant

* the magical incantation to make flow shut up
2018-09-13 17:20:22 +02:00
virtuacoplenny
37ff77cd5b Merge pull request #3416 from zbettenbuk/calendar-invite
[RN] Add calendar invite
2018-09-12 10:03:27 -07:00
Дамян Минков
fd30481ac2 Disable buttons only when token features is enabled. Fixes #3355. (#3443)
* Disable buttons only when token features is enabled. Fixes #3355.

* squash: update disabled check.

* squash: update disabled and disabledByFeatures.
2018-09-11 15:33:45 -07:00
Bettenbuk Zoltan
2d87757aaa [RN] Add invite function to calendar 2018-09-11 23:27:11 +02:00
Bettenbuk Zoltan
126e2d6e14 Move DialogContainer to BaseApp to have dialogs on the welcome screen too 2018-09-11 23:27:11 +02:00
virtuacoplenny
32fbcb17b9 Merge pull request #3442 from virtuacoplenny/lenny/subtitles-blown-away
fix(subtitles): fix typo that was blowing away subtitles on update
2018-09-11 13:41:34 -07:00
hristoterezov
d3bf0b7862 feat(recording): Add analytics. 2018-09-11 13:35:38 -05:00
Leonard Kim
17f4b24a3f fix(notification): change title for kick notification 2018-09-11 13:10:04 -05:00
virtuacoplenny
e63cd8c81b feat(tile-view): exit tile view on pin (#3430)
* feat(tile-view): exit tile view on pin

* Try out this other ux impl
2018-09-11 13:09:07 -05:00
Leonard Kim
282e66b2dc fix(subtitles): fix typo that was blowing away subtitles on update 2018-09-11 11:08:15 -07:00
Leonard Kim
72922130a2 fix(calendar): allow text to wrap and grow tile
Long meeting titles and urls can force text outside of the
tile.
2018-09-11 10:30:24 -05:00
Leonard Kim
514175b1af chore(deps): update most atlaskit dependencies
Update the following to the latest:
avatar
button
checkbox
field-text
field-text-area
icon
inline-message
layer-manager
lozenge
modal-dialog (one version before breaking changes)
multi-select
spinner
theme
tooltip

The following were not updated:
- droplist was removed because usage could not be found
- flag was not updated due to regressions with stacking animations
- inline-dialog was not updated because it requires (likely simple)
  fixing of position props
2018-09-11 10:27:00 -05:00
damencho
ceb8d7b03d Commit from translate.jitsi.org by user damencho.: 562 of 562 strings translated (0 fuzzy). 2018-09-11 14:43:48 +00:00
paweldomas
22803f36e9 chore(package.json): bump react-native-callstats to 3.53.4 2018-09-07 20:16:06 -05:00
Дамян Минков
7674e90d4d Adds dial in default number and pin to the text for calendar/share. (#3421)
* Adds dial in default number and pin to the text for calendar/share.

* Handles fail to fetch numbers or conference id.
2018-09-07 17:48:58 -05:00
Lyubo Marinov
1d128e027a Coding style: utilize default values
Since they are a language feature, they make the source code more easily
comprehensible than `if (typeof XXX === 'undefined') { XXX = ...; }`.
2018-09-07 16:48:16 -05:00
paweldomas
ee9f304345 fix(RN): show the CC button only when transcribing is available 2018-09-07 16:48:16 -05:00
Leonard Kim
f148b50100 fix(calendar): join button goes to meeting 2018-09-06 15:21:14 -05:00
paweldomas
95785a9585 ref(Notification.native): remove unnecessary View
The styles.actionColumn does not exist. It looks the same without the
extra View.
2018-09-05 18:43:49 -05:00
paweldomas
26d906fa46 feat(RN): displays transcription subtitles 2018-09-05 18:43:49 -05:00
paweldomas
eac069c930 ref(Conference.native): move notifications container
Moves NotificationContainer to the toolbox and filmstrip container, so
that there's no need to manually calculate the positions.
2018-09-05 18:43:49 -05:00
paweldomas
5119f41af6 ref(NotificationsContainer.native): simplify
The outer container is not necessary if 'justifyContent: flex-end' is
used with the absolute fill on the main container.
2018-09-05 18:43:49 -05:00
paweldomas
e2771b53bb feat(transcriptions): add ClosedCaptionButton.native 2018-09-05 18:43:49 -05:00
paweldomas
008fb868a6 feat(transcriptions): add TranscribingLabel.native 2018-09-05 18:43:49 -05:00
paweldomas
6dea107bcd ref(conference.js): unify "user joined/left" handling on web and RN
Extracts methods which share the common logic. There are still some
leftovers on the web side left which are not used on RN. But this can be
a first step.
2018-09-05 18:43:49 -05:00
Bettenbuk Zoltan
d10d61fb7a [RN] Add Google Sign In to live streaming 2018-09-05 23:09:56 +02:00
Bettenbuk Zoltan
9fe2b834eb [Android] Implement Activity.onActivityResult 2018-09-05 23:09:56 +02:00
Saúl Ibarra Corretgé
a327a5d804 [RN] Drop the react-native-permissions dependency
It causes false positives when submitting the app to the Store. Use the new
permissions API in react-native-webrtc instead.
2018-09-05 14:56:00 -05:00
Saúl Ibarra Corretgé
288bb59f71 deps: update react-native-webrtc dependency
It includes a W3C-ish permissions API which we will leverage.
2018-09-05 14:56:00 -05:00
Saúl Ibarra Corretgé
f3d623e0ca android: move calendar permission handling to the SDK
Since this is a feature implemented in the SDK, it makes sense that all the
plumbing required to make it work it's in the SDK itself.
2018-09-05 14:56:00 -05:00
Saúl Ibarra Corretgé
388c906312 android: implement the PermissionAwareActivity interface
This makes the PermissionsAndroid builtin module work.

Introduce the JitsiMeetActivityInterface, which defines the interface that
activities using JitsiMeetView directly must implement in order to ensure full
functionality.
2018-09-05 14:56:00 -05:00
virtuacoplenny
2043845d52 Merge pull request #3419 from virtuacoplenny/lenny/queue-replace-track
Queue replaceLocalTrack
2018-09-05 10:20:12 -07:00
Lyubo Marinov
024671165a [RN] No VideoQualityLabel in Picture-in-Picture 2018-09-05 00:22:19 -05:00
Lyubo Marinov
aba0912abf [RN] No upcoming-meeting notification in Picture-in-Picture 2018-09-05 00:22:19 -05:00
Lyubo Marinov
e446acb045 Coding style: consistency, documentation comments, formatting 2018-09-05 00:22:19 -05:00
Leonard Kim
3927f29ba8 fix(tracks): enqueue track replacement
The process for doing a replaceLocalTrack is async. Is it
possible to trigger replaceLocalTrack multiple times before
each call is finished. This leads to situations where
replaceLocalTrack is called multiple times with oldTrack being
null and a new track. In this scenario, each new track will be
added, causing UI issues such as the local participant's
large video not displaying for remote participants.

The action replaceLocalTrack is used when unmuting audio or
video, when creating new tracks on device switch, and when
toggling screensharing. These actions can collide with each
other. One way to fix this would be to queue replaceLocalTrack.
2018-09-04 09:39:02 -07:00
Leonard Kim
dafcde5060 ref(video-layout): remove instance variable for gating show/hide
The instance variable is not accurate. By default isVisible is
set to false but nothing sets the video container to actually
not be visible. As such it is possible for the video element
itself to autoplay, thereby making video visible, while the
isVisible boolean is still false. The fix chosen is to remove
instance variable and always respect calls to show/hide so
that the video container can be set to hidden.
2018-09-04 09:39:02 -07:00
Leonard Kim
3b754fa219 fix(tracks): mute tracks before using when created on device list change 2018-09-04 08:51:02 -07:00
Geert Stappers
4283d8b342 doc: describe what BOSH is 2018-09-04 17:34:38 +02:00
yanas
31cc63b757 Add join button to calendar events. (#3408)
* Add joing button to the calendar events.

* Add space between calendar lines.

* Adjust recent list name.

* Fixes test failure.

* Restyle mobile recent list message.

* Add analytics events.

* Addressing PR review comments.
2018-08-31 18:03:35 -07:00
Lyubo Marinov
79bd5cce00 react-native-webrtc: "android: prevent crash when checking camera facing mode (#37)" 2018-08-31 16:27:51 -05:00
Saúl Ibarra Corretgé
4fd8172126 [Android] Add LeakCanary
LeakCanary is a memory leak detection library which will run only in Debug mode.
2018-08-31 16:27:51 -05:00
virtuacoplenny
fe7652ec90 feat(tile-view): persist setting in local storage (#3379)
* feat(tile-view): persist setting in local storage

* comment
2018-08-31 10:36:01 -05:00
virtuacoplenny
72776e3a23 chore(deps): update lib for duplicate device list event fix (#3413) 2018-08-30 19:35:11 -07:00
Saúl Ibarra Corretgé
8addf0f436 deps: update react-native-fast-image (#3411)
Fixes a memory leak in Android: https://github.com/DylanVann/react-native-fast-image/pull/214

We are using our fork which is 4.0.14 + the leak fix because the last version
(5.0.3 at the time of this writing) contains a bug that prevents us for using
it: https://github.com/DylanVann/react-native-fast-image/issues/208
2018-08-30 18:19:04 -05:00
damencho
73146e77cc Commit from translate.jitsi.org by user damencho.: 447 of 447 strings translated (0 fuzzy). 2018-08-30 19:14:54 +00:00
damencho
28115b963d Commit from translate.jitsi.org by user damencho.: 447 of 447 strings translated (0 fuzzy). 2018-08-30 19:11:12 +00:00
jitsi-pootle
15819f7974 New files added from translate.jitsi.org based on templates 2018-08-30 19:07:20 +00:00
Leonard Kim
deb58798ba fix(tile-view): stop using border on active-speaker, shadow only
The border changes the tile sizing, due to box-sizing, and that
messes with the video aspect ratio.
2018-08-29 12:41:42 -05:00
Leonard Kim
07ccb0a386 fix(tile-view): hide any horizontal overflow 2018-08-29 12:41:42 -05:00
Saúl Ibarra Corretgé
8d6e1b1872 deps: update lib-jitsi-meet
Required due to API changes for promises support.
2018-08-29 09:22:28 -05:00
Saúl Ibarra Corretgé
80dadd0218 [RN] Update react-native-webrtc for promises support 2018-08-29 09:22:28 -05:00
Saúl Ibarra Corretgé
955e0a3382 [RN] Simplify RTCPeerConnection.setRemoteDescription override 2018-08-29 09:22:28 -05:00
Saúl Ibarra Corretgé
1354731fc5 [RN] Update WebRTC polyfills 2018-08-29 09:22:28 -05:00
Saúl Ibarra Corretgé
3ca704d81d [RN] Update react-native-webrtc and remove no longer needed polyfills 2018-08-29 09:22:28 -05:00
Lyubo Marinov
3ad27961e5 [iOS] Fix Jitsi Meet v1.18.x "Missing Purpose String in Info.plist File" issues reported by App Store Connect
App Store Connect reported the following issues in (and rejected the binary
of) Jitsi Meet 1.18.x:

NSBluetoothPeripheralUsageDescription
NSAppleMusicUsageDescription
NSMotionUsageDescription
NSSpeechRecognitionUsageDescription

Starting spring 2019, all apps submitted to the App Store that access user
data will be required to include a purpose string for the following:

NSLocationAlwaysUsageDescription
NSLocationWhenInUseUsageDescription
2018-08-28 10:00:55 +02:00
yanas
86caf52d08 Welcome page calendar ui improvements (#3405)
* Welcome page calendar ui improvements

* Addressing PR review comments.
2018-08-27 17:56:17 -07:00
yanas
f2cb15ba44 [WiP] Calendar integration ui (#3395)
Calendar integration ui
2018-08-27 10:13:59 -05:00
Lyubo Marinov
d62974b433 [RN] Update react-native-calendar-events (continued)
PR https://github.com/wmcmahan/react-native-calendar-events/pull/186 has
been merged upstream.
2018-08-26 21:53:42 -05:00
Saúl Ibarra Corretgé
8ff33684f7 [RN] Update react-native-calendar-events
Fixes a crash on Android. Upstream PR: https://github.com/wmcmahan/react-native-calendar-events/pull/186
2018-08-26 20:30:30 -05:00
bgrozev
b8179102c5 Merge pull request #3396 from nikvaessen/pr_independend_subtitles_cherry
independently display subtitles based on participants choice
2018-08-24 12:38:11 -05:00
linkmauve
c23c798f7a Display the correct display name in the menu (#3388)
The current code was splitting it on a space, which made nicknames such as “Link Mauve” appear as “Link”, whereas it gets displayed correctly everywhere else in the UI.
2018-08-22 12:35:48 -07:00
Nik
3c27d2ee54 independently display subtitles based on participants choice 2018-08-22 19:49:58 +02:00
Дамян Минков
7267f386dc Implements calendar entries edit. (#3382)
* Implements calendar entries edit.

Share text generation between calendar-sync and the share-room feature.

* Fixing comments.

* Clone the event element we modify on update.
2018-08-17 12:34:41 -07:00
Saúl Ibarra Corretgé
dba7f2d429 [RN] Remove no longer needed polyfills (#3377)
- navigator.{platform,plugins} were needed by the no longer existing screenshare
  adapter
- document.implementation is already polyfilled by xmldom
2018-08-16 23:03:53 -05:00
Saúl Ibarra Corretgé
a896d8f076 [RN] Fix normalizing BOSH URLs (#3376)
If a relative BOSH URL is found (as docker-jitsi-meet does) construct a full URL
based on the location URL and context root.

Also remove some default options since we need the config file anyway, so I see
no point in doing the extra work.
2018-08-16 23:03:15 -05:00
Hristo Terezov
99d285519d chore(lib-jitsi-meet): Update version. (#3381) 2018-08-16 16:58:54 -07:00
hristoterezov
2704b2f822 fix(dropbox): Address code review comments. 2018-08-16 13:53:43 -05:00
hristoterezov
62544188bd feat(recording): Add analytics event and logging. 2018-08-16 13:53:43 -05:00
hristoterezov
df0e107ea6 feat(recording): Implement dropbox integration 2018-08-16 13:53:43 -05:00
Saúl Ibarra Corretgé
f10d42f8e4 Fix processing context root
Yours truly refactored routing in https://github.com/jitsi/jitsi-meet/pull/3222
and broke it. When a bare room is entered the pathname was not updated when
applying the default URL.
2018-08-16 12:02:14 +02:00
Дамян Минков
7eda31315f Google & Microsoft calendar API integration (#3340)
* Refactor calendar-sync feature to be loaded on web.

For the web part it just adds new property to enable/disable calendar web integration, disabled by default.

* Initial implementation of retrieving google calendar events.

* Initial implementation of retrieving microsoft calendar events.

* Fixes comments.

* Rework to use the promise part of microsoft-graph-client api.

* Moves dispatching some actions, fixing comments.

* Makes sure we do not initializeClient google-api client multiple times.

* Do not try to login when fetching calendar entries.

The case where there is a calendar type google selected, but not logged in, trying to login on loading welcome page will show a warning that it tried to open a popup, which was denied by browser.

* Updates profile display data on sign in.

* Propagate google-api state to calendar-sync only if we use google cal.

* Adds sign out action.

* Clears the event listener when the popup closes.

* Clears calendarIntegrationInstance on signOut.

* WIP: UI for calendar settings, refactor auth flows

* Clean up some unused constants, functions and exports.

* break circular dependency of function and constant

* Exports only isCalendarEnabled from functions.

* Checks isSignedIn when doing fetchCalendarEntries on web.

* address comments

List microsoftApiApplicationClientID in undocument config.

remove unused SET_CALENDAR_TYPE action

use helper for calendar enabled in bootstrap

reorder actions

reorder imports

change order of signin -> set type -> update profile

add logging for signout error

reword setting dialog desc to avoid redundancy

add jsdoc to microsoft button props

reorder calendar constants

move default state to reducer (not reused anywhere)

update comment about calendar-sync due to removal of getCalendarState

update comment for getCalendarIntegration

remove vague comment

alpha order reducer, return default state on reset

alpha order persistence registry

remove unnecessary getType from apis

update comments in microsoftCalendar

alpha order google-api exports, use api.get in loadGoogleAPI

set jsdoc for google signin props

alpha order googleapi methods

fix calendartab docs

* Moves fetching calendar from APP_WILL_MOUNT to SET_CONFIG.

The web part needs configuration in order to refresh tokens (Microsoft).

* Fixes storing token expire time and refreshing tokens in Microsoft impl.

* Address comments

updateProfile changed to getCurrentEmail

rename result to results

stop storing integration in redux, store if ready for use

use existing helpers to parse redirect url

* update jsdocs, get google app id from redux

* clear integration instead of actual sign out
2018-08-15 13:11:54 -07:00
virtuacoplenny
87c010a9bd fix(subtitles): adjust styling for tile view (#3365)
- Increase z-index so the subtitles display over tiles.
- Add a background to the subtitle text.
- In general make the subtitles narrower.
2018-08-14 17:44:21 -07:00
linkmauve
8d0d92a437 Log the amount of local tracks properly
This changes a log message from “initialized with %s local tracks 2” to “initialized with 2 local tracks”.
2018-08-14 10:53:47 +02:00
linkmauve
faada0abae Print a nicer log message on participant join/part
This makes the logs more readable.
2018-08-14 10:53:18 +02:00
Ritwik Heda
1d99abc4a4 removes need for eslint-disable-next-line react/jsx-wrap-multilines and eslint-diable-line no extra-parens 2018-08-12 17:06:35 -05:00
Lyubo Marinov
9aed4df6d2 react-native-webrtc: android: pass correct constraints map to VideoCaptureController 2018-08-11 18:03:05 -05:00
Saúl Ibarra Corretgé
d92b720704 [RN] Update calendar-events dependency
Includes a fix for not running expensive operations on the main thread.
2018-08-10 15:11:37 +02:00
bgrozev
25aaa74edc Merge pull request #3223 from ztl8702/local-recording
Feature: Local recording (Ready for review)
2018-08-08 19:35:11 -05:00
Boris Grozev
195462a1a8 Merge branch 'master' into pr/3223 2018-08-08 15:35:40 -05:00
bgrozev
9c03e95bf1 npm: Updates lib-jitsi-meet to 4a28a196160411d657518022de8bded7c02ad679. (#3357) 2018-08-08 14:42:32 -05:00
virtuacoplenny
c353e9377f feat(tile-view): initial implementation for tile view (#3317)
* feat(tile-view): initial implementation for tile view

- Modify the classname on the app root so layout can adjust
  depending on the desired layout mode--vertical filmstrip,
  horizontal filmstrip, and tile view.
- Create a button for toggling tile view.
- Add a StateListenerRegistry to automatically update the
  selected participant and max receiver frame height on tile
  view toggle.
- Rezise thumbnails when switching in and out of tile view.
- Move the local video when switching in and out of tile view.
- Update reactified pieces of thumbnails when switching in and
  out of tile view.
- Cap the max receiver video quality in tile view based on tile
  size.
- Use CSS to hide UI components that should not display in tile
  view.
- Signal follow me changes.

* change local video id for tests

* change approach: leverage more css

* squash: fix some formatting

* squash: prevent pinning, hide pin border in tile view

* squash: change logic for maxReceiverQuality due to sidestepping resizing logic

* squash: fix typo, columns configurable, remove unused constants

* squash: resize with js again

* squash: use yana's math for calculating tile size
2018-08-08 13:48:23 -05:00
Radium Zheng
913c56c408 fix comments and docs 2018-08-08 11:58:38 +10:00
bgrozev
2f1223f721 fix: Handles the case of e2eRtt being undefined. (#3354) 2018-08-07 18:39:10 -07:00
Radium Zheng
4f1aaf89bf update package-lock.json 2018-08-08 09:26:49 +10:00
Radium Zheng
df6df1c6c3 refactor: AbstractAudioContextAdapter
move duplicate code from WavAdapter and FlacAdapter to a base class
2018-08-08 09:19:53 +10:00
Radium Zheng
1e804e552e fix: FlacAdapter get sampleRate 2018-08-08 09:19:53 +10:00
Radium Zheng
b284f25fde Refactor how download works. Cleaner filenames. 2018-08-08 09:19:53 +10:00
Radium Zheng
49bdd53bee Fix issue on mobile platforms 2018-08-08 09:19:53 +10:00
Radium Zheng
0827e02de9 use official repo for libflac.js 2018-08-08 09:19:53 +10:00
Radium Zheng
0410af9e5e add guard before APP in middleware.js 2018-08-08 09:19:28 +10:00
Radium Zheng
5a051024e6 clean up WavAdapter 2018-08-08 09:19:28 +10:00
Radium Zheng
e2def5f88b simplify Promise chaining in FlacAdapter 2018-08-08 09:19:28 +10:00
Radium Zheng
1078fa9d05 remove 'localRecording' from interface_config.js 2018-08-08 09:19:28 +10:00
Radium Zheng
dda7568a48 UI: refine LocalRecordingInfoDialog 2018-08-08 09:19:28 +10:00
Radium Zheng
4550848eac fix comments in flac-related codebase 2018-08-08 09:19:28 +10:00
Radium Zheng
7822831b1e UI: add a "Local Recording" label 2018-08-08 09:19:28 +10:00
Radium Zheng
e03126e422 fix sampleRate issues in flac and wav 2018-08-08 09:19:28 +10:00
Radium Zheng
61652c69b3 SessionManager 2018-08-08 09:19:28 +10:00
Radium Zheng
b6e1a49d33 Switching microphone on the fly: flac and wav support 2018-08-08 09:19:28 +10:00
Radium Zheng
e0ac3efb5c comment out section in config.js 2018-08-08 09:19:28 +10:00
Radium Zheng
65c76dcde5 Muting support
fix Promise in setMuted
2018-08-08 09:19:28 +10:00
Radium Zheng
5daa91ec1b update libflac.js to 4 and use proper fork 2018-08-08 09:19:28 +10:00
Radium Zheng
473ba28171 feature flag 2018-08-08 09:18:16 +10:00
Radium Zheng
52b55d65a0 change LocalRecordingInfoDialog 2018-08-08 09:18:16 +10:00
Radium Zheng
8ebf2b7e47 analytics: keyboard shortcut 2018-08-08 09:18:16 +10:00
Radium Zheng
cc38fcc5d0 register shortcuts in the middleware 2018-08-08 09:18:16 +10:00
Radium Zheng
a277421ecb WIP: Convert inline dialog to modal dialog 2018-08-08 09:18:16 +10:00
Radium Zheng
2f2e69a6f5 Add keyboard shortcuts for LocalRecordingInfoDialog
Which key should we use? Using "L" for now.
2018-08-08 09:18:16 +10:00
Radium Zheng
0490a3cf73 Refactor RecordingController 2018-08-08 09:18:16 +10:00
Radium Zheng
bfc8ecfaa6 changed one comment line 2018-08-08 09:18:16 +10:00
Radium Zheng
42c827434c clean up in LocalRecordingInfoDialog 2018-08-08 09:18:16 +10:00
Radium Zheng
0f3b67e53e reducer should be a pure function 2018-08-08 09:18:16 +10:00
Radium Zheng
2dfb107c57 UI strings: durationNA and moderater's finish message 2018-08-08 09:18:16 +10:00
Radium Zheng
f8c01646c7 Temp fix: newly joined clients miss the commands
When newly joined clients register for XMPP events upon
CONFERENCE_JOINED, those events that is carried by presence (e.g. START_COMMAND) was
already fired.
Temporary solution is to let the client send a ping message after
registering XMPP event listeners. The moderator will respond with
pong, which forces the presence to be resent.
2018-08-08 09:18:16 +10:00
Radium Zheng
0f0f9ea1b2 bug fix: multiple StartCommands
Situation when the RecordingController receives a new START_COMMAND
while it is initializing the recording adapter for the previous
START_COMMAND.
2018-08-08 09:18:16 +10:00
Radium Zheng
ce308eaa8b refactor: remove ensureInitialized 2018-08-08 09:18:16 +10:00
Radium Zheng
337cea6488 don't use params to switch actionType 2018-08-08 09:18:16 +10:00
Radium Zheng
e125861b29 refactor: use createLocalTracks instead of gUM; fix some docs; 2018-08-08 09:18:16 +10:00
Radium Zheng
3241c7a929 guard LocalRecordingButton with _shouldShowButton 2018-08-08 09:18:16 +10:00
Radium Zheng
55a2ef30a0 a11y label 2018-08-08 09:18:16 +10:00
Radium Zheng
ae0bd9e64e remove excessive comments in flacEncodeWorker.js 2018-08-08 09:18:16 +10:00
Radium Zheng
9c769a650e fix a missing doc string in Toolbox.js; reorder props alphabetically 2018-08-08 09:18:16 +10:00
Radium Zheng
07bc70c2f5 Implement local recording
index.js of local recording

local-recording(ui): recording button

local-recording(encoding): flac support with libflac.js

Fixes in RecordingController; integration with UI

local-recording(controller): coordinate recording on different clients

local-recording(controller): allow recording on remote participants

local-recording(controller): global singleton

local-recording(controller): use middleware to init LocalRecording

cleanup and documentation in RecordingController

local-recording(refactor): "Delegate" -> "Adapter"

code style

stop eslint and flow from complaining

temp save: client status

fix linter issues

fix some docs; remove global LocalRecording instance

use node.js packaging for libflac.js; remove vendor/ folder

code style: flacEncodeWorker.js

use moment.js to do time diff

remove the use of console.log

code style: flac related files

remove excessive empty lines; and more docs

remove the use of clockTick for UI updates

initalize flacEncodeWorker properly, to avoid premature audio data transmission

move the realization of recordingController events
from LocalRecordingButton to middleware

i18n strings

minor markup changes in LocalRecordingInfoDialog

fix documentation
2018-08-08 09:18:16 +10:00
bgrozev
2ee1bf9351 feat: Displays the E2E RTT in the connection stats table. (#3344)
* feat: Displays the E2E RTT in the connection stats table.

* fix: Whitelists the ping config properties.

* ref: Addresses feedback.

* npm: Updates lib-jitsi-meet to e097a1189ed99838605d90b959e129155bc0e50a.

* ref: Moves the e2ertt and region to the existing stats object.
2018-08-07 11:31:51 -07:00
Nik
7e1d97665a fix: only access nested json values when corrent payload type (#3352) 2018-08-07 09:03:31 -07:00
Zoltan Bettenbuk
b978851a0f [RN] Fix streaming on mobile (#3351) 2018-08-06 17:30:32 -07:00
Nik
ef49817eaf fix: add a timer which automatically clears subtitles (#3349) 2018-08-06 14:30:50 -07:00
virtuacoplenny
cac8888b37 feat(welcome-page): be able to open settings dialog (#3327)
* feat(welcome-page): be able to open settings dialog

- Create a getter for getting a settings tab's props so the device
  selection tab can get updated available devices.
- Be able to call a function from a tab after it has mounted. This is
  used for device selection to essentially call enumerateDevices on
  the welcome page so the device selectors are populated.
- Remove event UIEvents.AUDIO_OUTPUT_DEVICE_CHANGED. Instead directly call
  setAudioOutputDeviceId where possible.
- Fix initialization of the audioOutputDeviceId in settings by defaulting
  the audio output device to the one set in settings.

* squash: updateAvailableDevices -> getAvailableDevices, add comment for propsUpdateFunction
2018-08-06 10:24:59 -05:00
Praveen Gupta
81853d971a [WEB] Show final translated speech to text results as subtitles (#3276)
* Shows final translated speech to text results as subtitles

* Use conference from redux state and removes addTranscriptMessage
2018-08-06 11:24:37 +02:00
Lyubo Marinov
b9c5ed3b03 Fixes typo, comment 2018-08-05 17:18:14 -05:00
Lyubo Marinov
0892e0b644 Remove duplication 2018-08-05 17:04:19 -05:00
Bettenbuk Zoltan
b41bf22be7 Replace console with logger 2018-08-05 17:04:19 -05:00
Saúl Ibarra Corretgé
a1cc9bce91 [RN] Drop no longer needed polyfills
They were required only on Android because of its old JSC version. With the JSC
version bump they are no longer required.
2018-08-05 17:04:19 -05:00
Saúl Ibarra Corretgé
8d3cecad86 [Android] Update JSC version
The JSC version used by React Native is about 3 years old, and doesn't implement
things like Symbol or Typed Arrays, which require polyfills. These polyfills are
sometimes a los less performant, as is the case for Typed Arrays.

Bumping an updated JSC version makes both platforms consistent when it comes to
the JavaScript platform.
2018-08-05 17:04:16 -05:00
hristoterezov
bd8559fad6 fix(invite): IFrame api when invalid invitees are passed. 2018-08-03 12:42:38 -05:00
hristoterezov
fb75180632 ref(RecentList): Improvements after review. 2018-08-03 11:25:03 -05:00
Ritwik Heda
046b06e436 added recent list 2018-08-03 11:25:03 -05:00
Дамян Минков
af7c69a1aa Moves google-api in its own feature. (#3339)
* Moves google-api in its own feature.

* Stores the profile email in redux.
2018-08-02 14:56:36 -07:00
Saúl Ibarra Corretgé
7ad0639f7a [RN] Fix setting audio mode for audio-only calls
When a call is tarted in audio only mode due to the switch on the welcome page,
the wrong audio mode was chosen.
2018-08-01 22:12:08 +02:00
paweldomas
54a1853e60 fix(ios/Podfile.lock): bump SDWebImage/Core version 2018-07-31 14:07:17 -05:00
Saúl Ibarra Corretgé
27021ea271 [RN] Replace cached image implementation
Use react-native-fastimage, which uses 2 full-native image impleentations using
well known and mature (native) libraries.

This gets us rid of 2 libraries which were observerd as a source of bugs and
created trouble with dependencies: react-native-fetch-blob and
react-native-img-cache. They are also no longer well maintained.
2018-07-31 14:07:17 -05:00
Saúl Ibarra Corretgé
f5a667ad9e feat(Avatar): simplified code 2018-07-31 14:07:17 -05:00
paweldomas
2b9ce40533 feat(travis): bump image version 2018-07-31 12:54:01 -05:00
paweldomas
d3dd833f21 fix(ios/travis-ci) try pod update
With the fastimage lib Travis complains about:

CocoaPods could not find compatible versions for pod "SDWebImage/Core"
2018-07-31 12:54:01 -05:00
Neil Brown
1cc372868b Update quick-install.md
Tweaks for clarity.
2018-07-31 11:35:18 +02:00
bgrozev
a6956c7c34 Commit from translate.jitsi.org by user bgrozev.: 447 of 447 strings translated (0 fuzzy). 2018-07-30 14:27:03 -05:00
Leonard Kim
aaaa3e05d1 ref(thumbnail): pass in position of remote menu popover 2018-07-30 11:48:52 -05:00
Saúl Ibarra Corretgé
467a5aaae3 ios: run audio mode operations on a dedicated thread
There is no reason for them to run on the main thread, it's safe to call
AVFoundation functions on threads other than the main thread.

The previous code made an incorrect claim about the thread in which the audio
route change notification selector is called: it's called on a secondary thread:
https://developer.apple.com/documentation/avfoundation/avaudiosessionroutechangenotification
2018-07-27 15:39:39 -05:00
Saúl Ibarra Corretgé
243dd16285 android: run all audio and bluetooth operation on a dedicated thread 2018-07-27 15:39:39 -05:00
Saúl Ibarra Corretgé
92001f4d37 android: run WiFi stats operations on a dedicated thread 2018-07-27 15:39:39 -05:00
paweldomas
6a31c59081 ref(media/VideoTrack.native): remove fade animation 2018-07-27 12:08:54 +02:00
paweldomas
11c5b220a1 fix(participants/Avatar.native): disable fade animation
The Image adds a fade effect without asking, so lets explicitly disable
it. More info here:
https://github.com/facebook/react-native/issues/10194
2018-07-27 12:08:54 +02:00
virtuacoplenny
590ad90cd1 ref(video-layout): resize thumbnails first when resizing video area (#3308) 2018-07-26 11:45:04 -07:00
Nik
ca62e902bc Merge pull request #3312 from nikvaessen/master
comment out transcribingEnabled property; in code defaults to false
2018-07-26 19:51:38 +02:00
virtuacoplenny
34d1eb6768 ref(filmstrip): create an empty container for local filmstrip move (#3303)
* ref(filmstrip): create an empty container for local filmstrip move

This might be necessary for tile view. To support making the
local video display at the end of remote videos while in tile
view, but separateed from scrollable remote videos, moving
the local video might be necessary. By creating an empty
container, there is a target for local video to move to.

* squash: rename id
2018-07-26 12:51:15 -05:00
Nik Vaessen
b6b21e5410 comment out transcribingEnabled property; in code defaults to false 2018-07-26 19:10:40 +02:00
Nik
b8daf0a9f9 [WEB] add UI for transcription (#3213)
* [WEB] add UI for transcription

* add analytics event for button, do not use global APP object

* use props instead of state, use local conference to kick participant

* put imports in alphabetical order

* add translation for TranscribingLabel

* fix merge conflict

* add closed caption button

* purge OverFlowMenuItem which starts and stops Transcription

* readd closed caption icon and fix small issues due to purge

* delete unused icon in _font.scss
2018-07-26 09:33:40 -07:00
virtuacoplenny
39f1958300 ref(filmstrip): apply filmstrip class to Conference root (#3294)
* ref(filmstrip): apply filmstrip class to Conference root

Instead of apply the layout class to the body, it can be
applied to Conference. This will allow easier switching
between tile filmstrip and horizontal/vertical filmstrip.

* squash: fix typo filstrip
2018-07-25 13:00:00 -07:00
Leonard Kim
0b1224495b ref(video-quality): update video quality post redux update
Move away from middleware and instead update video quality
when the selected video quality updates in redux. This also
lead to removing of automatically exiting audio only because
with the change it's not so readily possible to tell if the
user switched off audio only by re-selecting the already
preferred video quality. Removing this automagic removed
some additional checking done for mobile.
2018-07-25 12:17:13 -07:00
Leonard Kim
ee7d180cbb feat(video-quality): be able to set an internal max
The internal max will be used for tile view. Whatever the
user has set for preferred video quality, the internal
maximum will be respected. This allows for the case where
the user prefers high definition video, but in tile view
it only makes sense to send low definition; ux wise the
user is allowed to continue messing with the video quality
slider.
2018-07-25 12:17:13 -07:00
Leonard Kim
4d3383c620 ref(video-quality): rename receiveVideoQuality to preferredReceiverVideoQuality
- "preferred" is being appended because in tile view there is a
  concept of what the user prefers to be the maximum video quality
  but there is also a maximum respected internall. For example,
  the user may prefer HD, but in tile view the tiles may be small
  so internall the preferred would be set to LD.
- "receive" is being renamed to "receiver" to be consistent with
  the naming in lib-jitsi-meet.
2018-07-25 12:17:13 -07:00
Pablo Saavedra
fd78203ff8 noticeMessage is not shown (refs #3295)
* Get back the Notice class
* Add Notice component in the Conference web view
* Notice is not exported in index.js. Only used internally by
  Conference.
* noticeMessage value obtained from features/base/config
  * using mapStateToProps
  * value is stored in the internal _message property
* Notice component, orignal in `toolbox` is moved from
  `toolbox/components` to `conference/components`
* Notice component only implemented and renderable in web views
* Dummy `conference/components/Notice.naive.js`

This patch is partially based in the removed logic included
originally in:

    commit 59a74153dc
    (tag: jitsi-meet_1886, tag: jitsi-meet_1885, tag: 1797, tag: 1796)
    Author: Ilya Daynatovich <shupuercha@gmail.com>
    Date:   Mon Mar 20 11:04:54 2017 -0500

      Toolbar notice as React Component

In reply to: Saúl Ibarra Corretgé @saghul> comments

Signed-off-by: Pablo Saavedra <psaavedra@igalia.com>
2018-07-25 14:16:47 -05:00
virtuacoplenny
a36b341865 ref(popover): allow for popover content from the right (#3302)
* ref(popover): allow for popover content from the right

Popovers contents can display to the left of the trigger
and above the trigger. Add the ability to display to the
right of the trigger my adding mouseover padding. This
may be needed for tile view, depending on where the triggers
are located.

* squash: abstract common css proprties into placeholder class
2018-07-25 13:28:36 -05:00
Saúl Ibarra Corretgé
3d6e18394e deps: update url-polyfill dependency
The previous location no longer exists. This is a fork of the original package,
which is actively maintained.

Fixes: #3304
2018-07-25 11:27:54 -05:00
virtuacoplenny
9a6e5c67f5 feat(tile-view): add new toolbar icon (#3292) 2018-07-25 08:22:18 -07:00
virtuacoplenny
50ea847905 Refactor welcome page in prep for branding (#3230)
* fix(welcome-page): css tweaks in prep for branded welcome page

- Watermarks should no longer depend on toolbar size. The left watermark made
  room for the toolbar when the toolbar was on the left side of the screen, but
  the toolbar has been moved to the bottom. The right watermark...well it'll
  clash with the vertical filmstrip but at least the margins will be consistent
  with the left watermark.
- Apply new font-family so fonts are more likely to be consistent across the
  app. Design likes SF UI and keeps requesting it so use it by default.
- Change sizings of welcome page header to be more responsive. This will help
  the header be scrollable when there is no additional content and the header
  overflows.
- Change colors of the welcome page header and remove background image that
  was in the header. Leave in the dom for the background image in case other
  deployments need to continue showing an image.
- Add a period to the title of the welcome page.
- Move watermarks dom location as it is not part of the header; it's part of the
  whole page.

* [squash] Size and font adjustments. Renaming.
2018-07-24 14:26:17 -05:00
virtuacoplenny
b54a9e2bf7 chore(deps): update lib for selecting participants and maxFrameHeight caching (#3291) 2018-07-23 14:20:30 -07:00
virtuacoplenny
918fb1dfc6 ref(utils): use web reportError helper (#3283) 2018-07-21 08:16:32 -07:00
Дамян Минков
9f015df61d Commit from translate.jitsi.org by user damencho.: 446 of 447 strings translated (0 fuzzy). (#3257) 2018-07-20 15:07:29 -05:00
575 changed files with 30034 additions and 15444 deletions

View File

@@ -38,7 +38,23 @@ node_modules/react-native/flow-github/
[options]
emoji=true
esproposal.optional_chaining=enable
esproposal.nullish_coalescing=enable
module.system=haste
module.system.haste.use_name_reducers=true
# get basename
module.system.haste.name_reducers='^.*/\([a-zA-Z0-9$_.-]+\.js\(\.flow\)?\)$' -> '\1'
# strip .js or .js.flow suffix
module.system.haste.name_reducers='^\(.*\)\.js\(\.flow\)?$' -> '\1'
# strip .ios suffix
module.system.haste.name_reducers='^\(.*\)\.ios$' -> '\1'
module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1'
module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1'
module.system.haste.paths.blacklist=.*/__tests__/.*
module.system.haste.paths.blacklist=.*/__mocks__/.*
module.system.haste.paths.blacklist=<PROJECT_ROOT>/node_modules/react-native/Libraries/Animated/src/polyfills/.*
module.system.haste.paths.whitelist=<PROJECT_ROOT>/node_modules/react-native/Libraries/.*
munge_underscores=true
@@ -67,4 +83,4 @@ module.file_ext=.jsx
module.file_ext=.json
[version]
^0.67.0
^0.78.0

View File

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

View File

@@ -2,6 +2,7 @@ BUILD_DIR = build
CLEANCSS = ./node_modules/.bin/cleancss
DEPLOY_DIR = libs
LIBJITSIMEET_DIR = node_modules/lib-jitsi-meet/
LIBFLAC_DIR = node_modules/libflacjs/dist/min/
NODE_SASS = ./node_modules/.bin/node-sass
NPM = npm
OUTPUT_DIR = .
@@ -19,7 +20,7 @@ compile:
clean:
rm -fr $(BUILD_DIR)
deploy: deploy-init deploy-appbundle deploy-lib-jitsi-meet deploy-css deploy-local
deploy: deploy-init deploy-appbundle deploy-lib-jitsi-meet deploy-libflac deploy-css deploy-local
deploy-init:
rm -fr $(DEPLOY_DIR)
@@ -33,6 +34,8 @@ deploy-appbundle:
$(BUILD_DIR)/do_external_connect.min.map \
$(BUILD_DIR)/external_api.min.js \
$(BUILD_DIR)/external_api.min.map \
$(BUILD_DIR)/flacEncodeWorker.min.js \
$(BUILD_DIR)/flacEncodeWorker.min.map \
$(BUILD_DIR)/device_selection_popup_bundle.min.js \
$(BUILD_DIR)/device_selection_popup_bundle.min.map \
$(BUILD_DIR)/dial_in_info_bundle.min.js \
@@ -50,6 +53,12 @@ deploy-lib-jitsi-meet:
$(LIBJITSIMEET_DIR)/modules/browser/capabilities.json \
$(DEPLOY_DIR)
deploy-libflac:
cp \
$(LIBFLAC_DIR)/libflac4-1.3.2.min.js \
$(LIBFLAC_DIR)/libflac4-1.3.2.min.js.mem \
$(DEPLOY_DIR)
deploy-css:
$(NODE_SASS) $(STYLES_MAIN) $(STYLES_BUNDLE) && \
$(CLEANCSS) $(STYLES_BUNDLE) > $(STYLES_DESTINATION) ; \
@@ -58,7 +67,7 @@ deploy-css:
deploy-local:
([ ! -x deploy-local.sh ] || ./deploy-local.sh)
dev: deploy-init deploy-css deploy-lib-jitsi-meet
dev: deploy-init deploy-css deploy-lib-jitsi-meet deploy-libflac
$(WEBPACK_DEV_SERVER)
source-package:

View File

@@ -130,7 +130,7 @@ equivalent to these of a direct one-to-one WebRTC call. This is what's unique to
Jitsi Meet in terms of security.
The [meet.jit.si](https://meet.jit.si) service is maintained by the Jitsi team
at [Atlassian](https://atlassian.com).
at [8x8](https://8x8.com).
## Mobile app
Jitsi Meet is also available as a React Native app for Android and iOS.

View File

@@ -126,6 +126,15 @@
return;
}
const ignoredEvents
= [ 'e2e_rtt', 'rtp.stats', 'rtt.by.region', 'available.device',
'stream.switch.delay', 'ice.state.changed', 'ice.duration' ];
// Temporary removing some of the events that are too noisy.
if (ignoredEvents.indexOf(event.action) !== -1) {
return;
}
const gaEvent = {
'eventCategory': 'jitsi-meet',
'eventAction': this._extractAction(event),

View File

@@ -491,3 +491,29 @@ Picture-in-Picture style scenario, in a rectangle too small to accommodate its
Jitsi Meet SDK automatically enables (unless explicitly disabled by a
`setPictureInPictureEnabled(false)` call) Android's native Picture-in-Picture
mode iff the platform is supported i.e. Android >= Oreo.
## Dropbox integration
To setup the Dropbox integration, follow these steps:
1. Add the following to the app's AndroidManifest.xml and change `<APP_KEY>` to
your Dropbox app key:
```
<activity
android:configChanges="keyboard|orientation"
android:launchMode="singleTask"
android:name="com.dropbox.core.android.AuthActivity">
<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="db-<APP_KEY>" />
</intent-filter>
</activity>
```
2. Add the following to the app's strings.xml and change `<APP_KEY>` to your
Dropbox app key:
```
<string name="dropbox_app_key"><APP_KEY></string>
```

View File

@@ -2,6 +2,7 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId 'org.jitsi.meet'
@@ -27,9 +28,13 @@ android {
}
buildTypes {
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-debug.pro'
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-release.pro'
}
}
@@ -40,7 +45,69 @@ android {
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "com.android.support:support-v4:${rootProject.ext.supportLibVersion}"
implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
implementation 'com.google.android.gms:play-services-auth:15.0.0'
implementation project(':sdk')
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.1'
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.1'
}
gradle.projectsEvaluated {
// Dropbox integration
//
def plistParser = new XmlSlurper(
/* validating */ false,
/* namespaceAware */ false,
/* allowDocTypeDeclaration */ true)
plistParser.setFeature(
'http://apache.org/xml/features/nonvalidating/load-external-dtd',
false)
def plist = plistParser.parse('../ios/app/src/Info.plist')
def dropboxScheme = plist.dict.array.dict.array.string.find { string ->
string.text().startsWith('db-')
}
def dropboxAppKey = dropboxScheme?.text() - 'db-'
if (dropboxAppKey) {
android.defaultConfig.resValue('string', 'dropbox_app_key', "${dropboxAppKey}")
def dropboxActivity = """
<activity
android:configChanges="keyboard|orientation"
android:launchMode="singleTask"
android:name="com.dropbox.core.android.AuthActivity">
<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="db-${dropboxAppKey}" />
</intent-filter>
</activity>""";
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
output.processManifest.doLast {
def f = new File(manifestOutputDirectory, 'AndroidManifest.xml')
if (!f.isFile()) {
f = new File(new File(manifestOutputDirectory, output.dirName), 'AndroidManifest.xml')
}
if (f.exists()) {
def charset = 'UTF-8'
def s = f.getText(charset)
s = s.replace('</application>', "${dropboxActivity}</application>")
f.write(s, charset)
}
}
}
}
}
}
if (project.file('google-services.json').exists()) {
apply plugin: 'com.google.gms.google-services'
}

View File

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

View File

@@ -0,0 +1,6 @@
-include proguard-rules.pro
# Crashlytics
-keepattributes *Annotation*
-keepattributes SourceFile,LineNumberTable
-keep public class * extends java.lang.Exception

View File

@@ -16,10 +16,6 @@
# public *;
#}
# Disabling obfuscation is useful if you collect stack traces from production crashes
# (unless you are using a system that supports de-obfuscate the stack traces).
-dontobfuscate
# React Native
# Keep our interfaces so they can be used by other ProGuard rules.
@@ -68,3 +64,26 @@
-dontwarn java.nio.file.*
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-dontwarn okio.**
# FastImage
-keep public class com.dylanvann.fastimage.** {*;}
# We added the following when we switched minifyEnabled on. Probably because we
# ran the app and hit problems...
-keep class com.facebook.react.bridge.CatalystInstanceImpl { *; }
-keep class com.facebook.react.bridge.ExecutorToken { *; }
-keep class com.facebook.react.bridge.JavaScriptExecutor { *; }
-keep class com.facebook.react.bridge.ModuleRegistryHolder { *; }
-keep class com.facebook.react.bridge.ReadableType { *; }
-keep class com.facebook.react.bridge.queue.NativeRunnable { *; }
-keep class com.facebook.react.devsupport.** { *; }
-keep class org.webrtc.** { *; }
-dontwarn com.facebook.react.devsupport.**
-dontwarn com.google.appengine.**
-dontwarn com.squareup.okhttp.**
-dontwarn javax.servlet.**
# ^^^ We added the above when we switched minifyEnabled on.

View File

@@ -5,6 +5,7 @@
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:name=".MainApplication"
android:theme="@style/AppTheme">
<activity
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize"

View File

@@ -27,11 +27,9 @@ import org.jitsi.meet.sdk.invite.AddPeopleControllerListener;
import org.jitsi.meet.sdk.invite.InviteController;
import org.jitsi.meet.sdk.invite.InviteControllerListener;
import com.calendarevents.CalendarEventsPackage;
import com.facebook.react.bridge.UiThreadUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -229,20 +227,4 @@ public class MainActivity extends JitsiMeetActivity {
addPeopleController.endAddPeople();
}
}
@Override
public void onRequestPermissionsResult(
int requestCode,
String[] permissions,
int[] grantResults) {
CalendarEventsPackage.onRequestPermissionsResult(
requestCode,
permissions,
grantResults);
super.onRequestPermissionsResult(
requestCode,
permissions,
grantResults);
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright @ 2018-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 android.app.Application;
import com.squareup.leakcanary.LeakCanary;
/**
* Simple {@link Application} for hooking up LeakCanary:
* https://github.com/square/leakcanary
*/
public class MainApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
if (!LeakCanary.isInAnalyzerProcess(this)) {
LeakCanary.install(this);
}
}
}

View File

@@ -7,7 +7,8 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.android.tools.build:gradle:3.1.4'
classpath 'com.google.gms:google-services:3.2.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files.
@@ -16,8 +17,10 @@ buildscript {
allprojects {
repositories {
maven { url "https://maven.google.com" }
google()
jcenter()
maven { url "$rootDir/../node_modules/jsc-android/dist" }
// React Native (JS, Obj-C sources, Android binaries) is installed from
// npm.
maven { url "$rootDir/../node_modules/react-native/android" }
@@ -34,6 +37,12 @@ allprojects {
def version = new groovy.json.JsonSlurper().parseText(file.text).version
details.useVersion version
}
if (details.requested.group == 'org.webkit'
&& details.requested.name == 'android-jsc') {
def file = new File("$rootDir/../node_modules/jsc-android/package.json")
def version = new groovy.json.JsonSlurper().parseText(file.text).version
details.useVersion "r${version.tokenize('.')[0]}"
}
}
}
}
@@ -144,10 +153,11 @@ allprojects {
}
ext {
buildToolsVersion = "26.0.2"
compileSdkVersion = 26
minSdkVersion = 16
buildToolsVersion = "27.0.3"
compileSdkVersion = 27
minSdkVersion = 21
targetSdkVersion = 26
supportLibVersion = "27.1.1"
// The Maven artifact groupdId of the third-party react-native modules which
// Jitsi Meet SDK for Android depends on and which are not available in
@@ -170,3 +180,8 @@ subprojects { subproject ->
}
}
}
task wrapper(type: Wrapper) {
gradleVersion = '4.4'
distributionUrl = distributionUrl.replace("bin", "all")
}

View File

@@ -17,5 +17,4 @@
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
android.useDeprecatedNdk=true
version=1
version=1

Binary file not shown.

View File

@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

110
android/gradlew vendored
View File

@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/usr/bin/env sh
##############################################################################
##
@@ -6,47 +6,6 @@
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
@@ -61,9 +20,49 @@ while [ -h "$PRG" ] ; do
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -90,7 +89,7 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@@ -114,6 +113,7 @@ fi
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
@@ -154,11 +154,19 @@ if $cygwin ; then
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
APP_ARGS=$(save "$@")
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

14
android/gradlew.bat vendored
View File

@@ -8,14 +8,14 @@
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
@@ -46,10 +46,9 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
@@ -60,11 +59,6 @@ set _SKIP=2
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line

View File

@@ -19,132 +19,144 @@ android {
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
implementation fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:27.0.2'
compile 'com.facebook.react:react-native:+'
implementation "com.android.support:support-v4:${rootProject.ext.supportLibVersion}"
implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
compile project(':react-native-background-timer')
compile project(':react-native-fetch-blob')
compile project(':react-native-immersive')
compile project(':react-native-keep-awake')
compile project(':react-native-linear-gradient')
compile project(':react-native-locale-detector')
compile project(':react-native-sound')
compile project(':react-native-vector-icons')
compile project(':react-native-webrtc')
compile project(':react-native-calendar-events')
implementation 'com.dropbox.core:dropbox-core-sdk:3.0.8'
api 'com.facebook.react:react-native:+'
testCompile 'junit:junit:4.12'
}
// Build process helpers
//
void runBefore(String dependentTaskName, Task task) {
Task dependentTask = tasks.findByPath(dependentTaskName);
if (dependentTask != null) {
dependentTask.dependsOn task
implementation project(':react-native-background-timer')
implementation project(':react-native-calendar-events')
implementation(project(':react-native-fast-image')) {
exclude group: 'com.android.support'
}
implementation(project(":react-native-google-signin")) {
exclude group: 'com.google.android.gms'
exclude group: 'com.android.support'
}
implementation project(':react-native-immersive')
implementation project(':react-native-keep-awake')
implementation project(':react-native-linear-gradient')
implementation project(':react-native-locale-detector')
implementation project(':react-native-sound')
implementation project(':react-native-vector-icons')
implementation project(':react-native-webrtc')
testImplementation 'junit:junit:4.12'
}
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.
// Here we bundle all assets, resources and React files. We cannot use the
// react.gradle file provided by react-native because it's designed to be used
// in an application (it taps into applicationVariants, but the SDK is a library
// so we need libraryVariants instead).
android.libraryVariants.all { def variant ->
// Create variant and target names
def targetName = variant.name.capitalize()
def targetPath = variant.dirName
// React js bundle directories
def jsBundleDir = file("$buildDir/generated/assets/react/${targetPath}")
def resourcesDir = file("$buildDir/generated/res/react/${targetPath}")
def jsBundleFile = file("$jsBundleDir/index.android.bundle")
def currentBundleTask = tasks.create(
name: "bundle${targetName}JsAndAssets",
type: Exec) {
group = "react"
description = "bundle JS and assets for ${targetName}."
// Create dirs if they are not there (e.g. the "clean" task just ran)
doFirst {
jsBundleDir.deleteDir()
jsBundleDir.mkdirs()
resourcesDir.deleteDir()
resourcesDir.mkdirs()
}
// 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
// Set up dev mode
def devEnabled = !targetName.toLowerCase().contains("release")
// Run the bundler
commandLine(
"node",
"node_modules/react-native/local-cli/cli.js",
"bundle",
"--platform", "android",
"--dev", "${devEnabled}",
"--reset-cache",
"--entry-file", "index.android.js",
"--bundle-output", jsBundleFile,
"--assets-dest", resourcesDir)
// Disable bundling on dev builds
enabled !devEnabled
}
currentBundleTask.ext.generatedResFolders = files(resourcesDir).builtBy(currentBundleTask)
currentBundleTask.ext.generatedAssetsFolders = files(jsBundleDir).builtBy(currentBundleTask)
variant.registerGeneratedResFolders(currentBundleTask.generatedResFolders)
variant.mergeResources.dependsOn(currentBundleTask)
def assetsDir = variant.mergeAssets.outputDir
variant.mergeAssets.doLast {
// Bundle fonts
//
def currentFontTask = tasks.create(
name: "copy${buildNameCapitalized}Fonts",
type: Copy) {
copy {
from("${projectDir}/../../fonts/jitsi.ttf")
from("${projectDir}/../../node_modules/react-native-vector-icons/Fonts/")
into("${bundlePath}/assets/fonts")
into("${assetsDir}/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)
def currentSoundsTask = tasks.create(
name: "copy${buildNameCapitalized}Sounds",
type: Copy) {
from("${projectDir}/../../sounds/joined.wav")
from("${projectDir}/../../sounds/left.wav")
from("${projectDir}/../../sounds/outgoingRinging.wav")
from("${projectDir}/../../sounds/outgoingStart.wav")
from("${projectDir}/../../sounds/recordingOn.mp3")
from("${projectDir}/../../sounds/recordingOff.mp3")
from("${projectDir}/../../sounds/rejected.wav")
into("${bundlePath}/assets/sounds")
}
currentSoundsTask.dependsOn("merge${buildNameCapitalized}Resources")
currentSoundsTask.dependsOn("merge${buildNameCapitalized}Assets")
runBefore("processArmeabi-v7a${buildNameCapitalized}Resources", currentSoundsTask)
runBefore("processX86${buildNameCapitalized}Resources", currentSoundsTask)
runBefore("processUniversal${buildNameCapitalized}Resources", currentSoundsTask)
runBefore("process${buildNameCapitalized}Resources", currentSoundsTask)
// Bundle JavaScript and React resources.
// (adapted from react-native/react.gradle)
// Bundle sounds
//
// 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
copy {
from("${projectDir}/../../sounds/joined.wav")
from("${projectDir}/../../sounds/left.wav")
from("${projectDir}/../../sounds/outgoingRinging.wav")
from("${projectDir}/../../sounds/outgoingStart.wav")
from("${projectDir}/../../sounds/recordingOn.mp3")
from("${projectDir}/../../sounds/recordingOff.mp3")
from("${projectDir}/../../sounds/rejected.wav")
into("${assetsDir}/sounds")
}
// Hook bundle${productFlavor}${buildType}JsAndAssets into the android build process
currentBundleTask.dependsOn("merge${buildNameCapitalized}Resources")
currentBundleTask.dependsOn("merge${buildNameCapitalized}Assets")
// Copy React assets
//
if (currentBundleTask.enabled) {
copy {
from(jsBundleDir)
into(assetsDir)
}
}
}
runBefore("processArmeabi-v7a${buildNameCapitalized}Resources", currentBundleTask)
runBefore("processX86${buildNameCapitalized}Resources", currentBundleTask)
runBefore("processUniversal${buildNameCapitalized}Resources", currentBundleTask)
runBefore("process${buildNameCapitalized}Resources", currentBundleTask)
variant.mergeResources.doLast {
// Copy React resources
//
if (currentBundleTask.enabled) {
copy {
from(resourcesDir)
into(variant.mergeResources.outputDir)
}
}
}
}
publishing {
publications {
aarArchive(MavenPublication) {

View File

@@ -25,8 +25,6 @@ import android.content.pm.PackageManager;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.facebook.react.bridge.Arguments;
@@ -41,6 +39,8 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Module implementing a simple API to select the appropriate audio device for a
@@ -118,10 +118,11 @@ class AudioModeModule
private BluetoothHeadsetMonitor bluetoothHeadsetMonitor;
/**
* {@link Handler} for running all operations on the main thread.
* {@link ExecutorService} for running all audio operations on a dedicated
* thread.
*/
private final Handler mainThreadHandler
= new Handler(Looper.getMainLooper());
private static final ExecutorService executor
= Executors.newSingleThreadExecutor();
/**
* {@link Runnable} for running audio device detection the main thread.
@@ -228,7 +229,7 @@ class AudioModeModule
// Do an initial detection on Android >= M.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mainThreadHandler.post(onAudioDeviceChangeRunner);
runInAudioThread(onAudioDeviceChangeRunner);
} else {
// On Android < M, detect if we have an earpiece.
PackageManager pm = reactContext.getPackageManager();
@@ -268,7 +269,7 @@ class AudioModeModule
*/
@ReactMethod
public void getAudioDevices(final Promise promise) {
mainThreadHandler.post(new Runnable() {
runInAudioThread(new Runnable() {
@Override
public void run() {
WritableMap map = Arguments.createMap();
@@ -305,7 +306,7 @@ class AudioModeModule
* Only used on Android >= M.
*/
void onAudioDeviceChange() {
mainThreadHandler.post(onAudioDeviceChangeRunner);
runInAudioThread(onAudioDeviceChangeRunner);
}
/**
@@ -333,7 +334,7 @@ class AudioModeModule
* Only used on Android < M.
*/
void onHeadsetDeviceChange() {
mainThreadHandler.post(new Runnable() {
runInAudioThread(new Runnable() {
@Override
public void run() {
// XXX: isWiredHeadsetOn is not deprecated when used just for
@@ -383,6 +384,14 @@ class AudioModeModule
}
}
/**
* Helper function to run operations on a dedicated thread.
* @param runnable
*/
public void runInAudioThread(Runnable runnable) {
executor.execute(runnable);
}
/**
* Sets the user selected audio device as the active audio device.
*
@@ -390,7 +399,7 @@ class AudioModeModule
*/
@ReactMethod
public void setAudioDevice(final String device) {
mainThreadHandler.post(new Runnable() {
runInAudioThread(new Runnable() {
@Override
public void run() {
if (!availableDevices.contains(device)) {
@@ -461,7 +470,7 @@ class AudioModeModule
}
}
};
mainThreadHandler.post(r);
runInAudioThread(r);
}
/**

View File

@@ -24,8 +24,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
/**
@@ -55,12 +53,6 @@ class BluetoothHeadsetMonitor {
*/
private boolean headsetAvailable = false;
/**
* {@link Handler} for running all operations on the main thread.
*/
private final Handler mainThreadHandler
= new Handler(Looper.getMainLooper());
/**
* Helper for running Bluetooth operations on the main thread.
*/
@@ -200,6 +192,6 @@ class BluetoothHeadsetMonitor {
* {@link AudioModeModule#onAudioDeviceChange()} callback.
*/
private void updateDevices() {
mainThreadHandler.post(updateDevicesRunnable);
audioModeModule.runInAudioThread(updateDevicesRunnable);
}
}

View File

@@ -27,6 +27,7 @@ import android.view.KeyEvent;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.modules.core.PermissionListener;
import java.net.URL;
@@ -42,7 +43,7 @@ import java.net.URL;
* {@code JitsiMeetView} static methods.
*/
public class JitsiMeetActivity
extends AppCompatActivity {
extends AppCompatActivity implements JitsiMeetActivityInterface {
/**
* The request code identifying requests for the permission to draw on top
@@ -174,7 +175,12 @@ public class JitsiMeetActivity
if (Settings.canDrawOverlays(this)) {
initializeContentView();
}
return;
}
ReactActivityLifecycleCallbacks.onActivityResult(
this, requestCode, resultCode, data);
}
@Override
@@ -260,6 +266,15 @@ public class JitsiMeetActivity
ReactActivityLifecycleCallbacks.onNewIntent(intent);
}
// https://developer.android.com/reference/android/support/v4/app/ActivityCompat.OnRequestPermissionsResultCallback
@Override
public void onRequestPermissionsResult(
final int requestCode,
final String[] permissions,
final int[] grantResults) {
ReactActivityLifecycleCallbacks.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
protected void onResume() {
super.onResume();
@@ -283,6 +298,14 @@ public class JitsiMeetActivity
}
}
/**
* Implementation of the {@code PermissionAwareActivity} interface.
*/
@Override
public void requestPermissions(String[] permissions, int requestCode, PermissionListener listener) {
ReactActivityLifecycleCallbacks.requestPermissions(this, permissions, requestCode, listener);
}
/**
*
* @see JitsiMeetView#setDefaultURL(URL)

View File

@@ -0,0 +1,15 @@
package org.jitsi.meet.sdk;
import android.support.v4.app.ActivityCompat;
import com.facebook.react.modules.core.PermissionAwareActivity;
/**
* This interface serves as the umbrella interface that applications not using
* {@code JitsiMeetActivity} must implement in order to ensure full
* functionality.
*/
public interface JitsiMeetActivityInterface
extends ActivityCompat.OnRequestPermissionsResultCallback,
PermissionAwareActivity {
}

View File

@@ -16,11 +16,16 @@
package org.jitsi.meet.sdk;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import com.calendarevents.CalendarEventsPackage;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.Callback;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.modules.core.PermissionListener;
/**
* Helper class to encapsulate the work which needs to be done on
@@ -28,6 +33,37 @@ import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
* it.
*/
public class ReactActivityLifecycleCallbacks {
/**
* {@link Activity} lifecycle method which should be called from
* {@code Activity#onActivityResult} so we are notified about results of external intents
* started/finished.
*
* @param activity {@code Activity} activity from where the result comes from.
* @param requestCode {@code int} code of the request.
* @param resultCode {@code int} code of the result.
* @param data {@code Intent} the intent of the activity.
*/
public static void onActivityResult(
Activity activity,
int requestCode,
int resultCode,
Intent data) {
ReactInstanceManager reactInstanceManager
= ReactInstanceManagerHolder.getReactInstanceManager();
if (reactInstanceManager != null) {
reactInstanceManager.onActivityResult(activity, requestCode, resultCode, data);
}
}
/**
* Needed for making sure this class working with the "PermissionsAndroid"
* React Native module.
*/
private static PermissionListener permissionListener;
private static Callback permissionsCallback;
/**
* {@link Activity} lifecycle method which should be called from
* {@link Activity#onBackPressed} so we can do the required internal
@@ -107,6 +143,11 @@ public class ReactActivityLifecycleCallbacks {
if (reactInstanceManager != null) {
reactInstanceManager.onHostResume(activity, defaultBackButtonImpl);
}
if (permissionsCallback != null) {
permissionsCallback.invoke();
permissionsCallback = null;
}
}
/**
@@ -126,4 +167,29 @@ public class ReactActivityLifecycleCallbacks {
reactInstanceManager.onNewIntent(intent);
}
}
public static void onRequestPermissionsResult(
final int requestCode,
final String[] permissions,
final int[] grantResults) {
CalendarEventsPackage.onRequestPermissionsResult(
requestCode,
permissions,
grantResults);
permissionsCallback = new Callback() {
@Override
public void invoke(Object... args) {
if (permissionListener != null
&& permissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
permissionListener = null;
}
}
};
}
@TargetApi(Build.VERSION_CODES.M)
public static void requestPermissions(Activity activity, String[] permissions, int requestCode, PermissionListener listener) {
permissionListener = listener;
activity.requestPermissions(permissions, requestCode);
}
}

View File

@@ -45,6 +45,7 @@ class ReactInstanceManagerHolder {
new PictureInPictureModule(reactContext),
new ProximityModule(reactContext),
new WiFiStatsModule(reactContext),
new org.jitsi.meet.sdk.dropbox.Dropbox(reactContext),
new org.jitsi.meet.sdk.invite.InviteModule(reactContext),
new org.jitsi.meet.sdk.net.NAT64AddrInfoModule(reactContext)
);
@@ -119,15 +120,16 @@ class ReactInstanceManagerHolder {
.setApplication(application)
.setBundleAssetName("index.android.bundle")
.setJSMainModulePath("index.android")
.addPackage(new co.apptailor.googlesignin.RNGoogleSigninPackage())
.addPackage(new com.BV.LinearGradient.LinearGradientPackage())
.addPackage(new com.calendarevents.CalendarEventsPackage())
.addPackage(new com.corbt.keepawake.KCKeepAwakePackage())
.addPackage(new com.dylanvann.fastimage.FastImageViewPackage())
.addPackage(new com.facebook.react.shell.MainReactPackage())
.addPackage(new com.i18n.reactnativei18n.ReactNativeI18n())
.addPackage(new com.oblador.vectoricons.VectorIconsPackage())
.addPackage(new com.ocetnik.timer.BackgroundTimerPackage())
.addPackage(new com.oney.WebRTCModule.WebRTCModulePackage())
.addPackage(new com.RNFetchBlob.RNFetchBlobPackage())
.addPackage(new com.rnimmersive.RNImmersivePackage())
.addPackage(new com.zmxv.RNSound.RNSoundPackage())
.addPackage(new ReactPackageAdapter() {

View File

@@ -19,8 +19,6 @@ package org.jitsi.meet.sdk;
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.facebook.react.bridge.Promise;
@@ -36,6 +34,8 @@ import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Module exposing WiFi statistics.
@@ -64,10 +64,10 @@ class WiFiStatsModule
public final static int SIGNAL_LEVEL_SCALE = 101;
/**
* {@link Handler} for running all operations on the main thread.
* {@link ExecutorService} for running all operations on a dedicated thread.
*/
private final Handler mainThreadHandler
= new Handler(Looper.getMainLooper());
private static final ExecutorService executor
= Executors.newSingleThreadExecutor();
/**
* Initializes a new module instance. There shall be a single instance of
@@ -203,6 +203,6 @@ class WiFiStatsModule
}
}
};
mainThreadHandler.post(r);
executor.execute(r);
}
}

View File

@@ -0,0 +1,184 @@
package org.jitsi.meet.sdk.dropbox;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.text.TextUtils;
import com.dropbox.core.DbxException;
import com.dropbox.core.DbxRequestConfig;
import com.dropbox.core.v2.DbxClientV2;
import com.dropbox.core.v2.users.FullAccount;
import com.dropbox.core.v2.users.SpaceAllocation;
import com.dropbox.core.v2.users.SpaceUsage;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.dropbox.core.android.Auth;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableMap;
import java.util.HashMap;
import java.util.Map;
/**
* Implements the react-native module for the dropbox integration.
*/
public class Dropbox
extends ReactContextBaseJavaModule
implements LifecycleEventListener {
private String appKey;
private String clientId;
private final boolean isEnabled;
private Promise promise;
public Dropbox(ReactApplicationContext reactContext) {
super(reactContext);
appKey
= reactContext.getString(
org.jitsi.meet.sdk.R.string.dropbox_app_key);
isEnabled = !TextUtils.isEmpty(appKey);
clientId = generateClientId();
reactContext.addLifecycleEventListener(this);
}
/**
* Executes the dropbox auth flow.
*
* @param promise The promise used to return the result of the auth flow.
*/
@ReactMethod
public void authorize(final Promise promise) {
if (isEnabled) {
Auth.startOAuth2Authentication(this.getCurrentActivity(), appKey);
this.promise = promise;
} else {
promise.reject(
new Exception("Dropbox integration isn't configured."));
}
}
/**
* Generate a client identifier for the dropbox sdk.
*
* @returns a client identifier for the dropbox sdk.
* @see {https://dropbox.github.io/dropbox-sdk-java/api-docs/v3.0.x/com/dropbox/core/DbxRequestConfig.html#getClientIdentifier--}
*/
private String generateClientId() {
Context context = getReactApplicationContext();
PackageManager packageManager = context.getPackageManager();
ApplicationInfo applicationInfo = null;
PackageInfo packageInfo = null;
try {
String packageName = context.getPackageName();
applicationInfo = packageManager.getApplicationInfo(packageName, 0);
packageInfo = packageManager.getPackageInfo(packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
}
String applicationLabel
= applicationInfo == null
? "JitsiMeet"
: packageManager.getApplicationLabel(applicationInfo).toString()
.replaceAll("\\s", "");
String version = packageInfo == null ? "dev" : packageInfo.versionName;
return applicationLabel + "/" + version;
}
@Override
public Map<String, Object> getConstants() {
Map<String, Object> constants = new HashMap<>();
constants.put("ENABLED", isEnabled);
return constants;
}
/**
* Resolves the current user dropbox display name.
*
* @param token A dropbox access token.
* @param promise The promise used to return the result of the auth flow.
*/
@ReactMethod
public void getDisplayName(final String token, final Promise promise) {
DbxRequestConfig config = DbxRequestConfig.newBuilder(clientId).build();
DbxClientV2 client = new DbxClientV2(config, token);
// Get current account info
try {
FullAccount account = client.users().getCurrentAccount();
promise.resolve(account.getName().getDisplayName());
} catch (DbxException e) {
promise.reject(e);
}
}
@Override
public String getName() {
return "Dropbox";
}
/**
* Resolves the current user space usage.
*
* @param token A dropbox access token.
* @param promise The promise used to return the result of the auth flow.
*/
@ReactMethod
public void getSpaceUsage(final String token, final Promise promise) {
DbxRequestConfig config = DbxRequestConfig.newBuilder(clientId).build();
DbxClientV2 client = new DbxClientV2(config, token);
try {
SpaceUsage spaceUsage = client.users().getSpaceUsage();
WritableMap map = Arguments.createMap();
map.putString("used", String.valueOf(spaceUsage.getUsed()));
SpaceAllocation allocation = spaceUsage.getAllocation();
long allocated = 0;
if (allocation.isIndividual()) {
allocated += allocation.getIndividualValue().getAllocated();
}
if (allocation.isTeam()) {
allocated += allocation.getTeamValue().getAllocated();
}
map.putString("allocated", String.valueOf(allocated));
promise.resolve(map);
} catch (DbxException e) {
promise.reject(e);
}
}
@Override
public void onHostDestroy() {}
@Override
public void onHostPause() {}
@Override
public void onHostResume() {
String token = Auth.getOAuth2Token();
if (token != null && this.promise != null) {
this.promise.resolve(token);
this.promise = null;
}
}
}

View File

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

View File

@@ -3,8 +3,10 @@ rootProject.name = 'jitsi-meet'
include ':app', ':sdk'
include ':react-native-background-timer'
project(':react-native-background-timer').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-background-timer/android')
include ':react-native-fetch-blob'
project(':react-native-fetch-blob').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fetch-blob/android')
include ':react-native-fast-image'
project(':react-native-fast-image').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fast-image/android')
include ':react-native-google-signin'
project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-google-signin/android')
include ':react-native-immersive'
project(':react-native-immersive').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-immersive/android')
include ':react-native-keep-awake'

View File

@@ -11,6 +11,7 @@ import * as RemoteControlEvents
from './service/remotecontrol/RemoteControlEvents';
import UIEvents from './service/UI/UIEvents';
import UIUtil from './modules/UI/util/UIUtil';
import { createTaskQueue } from './modules/util/helpers';
import * as JitsiMeetConferenceEvents from './ConferenceEvents';
import {
@@ -30,13 +31,16 @@ import EventEmitter from 'events';
import {
AVATAR_ID_COMMAND,
AVATAR_URL_COMMAND,
EMAIL_COMMAND,
authStatusChanged,
commonUserJoinedHandling,
commonUserLeftHandling,
conferenceFailed,
conferenceJoined,
conferenceLeft,
conferenceWillJoin,
conferenceWillLeave,
dataChannelOpened,
EMAIL_COMMAND,
lockStateChanged,
onStartMutedPolicyChanged,
p2pStatusChanged,
@@ -44,6 +48,7 @@ import {
setDesktopSharingEnabled
} from './react/features/base/conference';
import {
getAvailableDevices,
setAudioOutputDeviceId,
updateDeviceList
} from './react/features/base/devices';
@@ -76,8 +81,6 @@ import {
localParticipantRoleChanged,
MAX_DISPLAY_NAME_LENGTH,
participantConnectionStatusChanged,
participantJoined,
participantLeft,
participantPresenceChanged,
participantRoleChanged,
participantUpdated
@@ -94,6 +97,7 @@ import {
getLocationContextRoot,
getJitsiMeetGlobalNS
} from './react/features/base/util';
import { addMessage } from './react/features/chat';
import { showDesktopPicker } from './react/features/desktop-picker';
import { appendSuffix } from './react/features/display-name';
import {
@@ -270,6 +274,27 @@ function redirectToStaticPage(pathname) {
windowLocation.pathname = newPathname;
}
/**
* A queue for the async replaceLocalTrack action so that multiple audio
* replacements cannot happen simultaneously. This solves the issue where
* replaceLocalTrack is called multiple times with an oldTrack of null, causing
* multiple local tracks of the same type to be used.
*
* @private
* @type {Object}
*/
const _replaceLocalAudioTrackQueue = createTaskQueue();
/**
* A task queue for replacement local video tracks. This separate queue exists
* so video replacement is not blocked by audio replacement tasks in the queue
* {@link _replaceLocalAudioTrackQueue}.
*
* @private
* @type {Object}
*/
const _replaceLocalVideoTrackQueue = createTaskQueue();
/**
*
*/
@@ -370,6 +395,8 @@ class ConferenceConnector {
case JitsiConferenceErrors.FOCUS_LEFT:
case JitsiConferenceErrors.VIDEOBRIDGE_NOT_AVAILABLE:
APP.store.dispatch(conferenceWillLeave(room));
// FIXME the conference should be stopped by the library and not by
// the app. Both the errors above are unrecoverable from the library
// perspective.
@@ -398,10 +425,16 @@ class ConferenceConnector {
switch (err) {
case JitsiConferenceErrors.CHAT_ERROR:
logger.error('Chat error.', err);
if (isButtonEnabled('chat')) {
if (isButtonEnabled('chat') && !interfaceConfig.filmStripOnly) {
const [ code, msg ] = params;
APP.UI.showChatError(code, msg);
APP.store.dispatch(addMessage({
hasRead: true,
error: code,
message: msg,
timestamp: Date.now(),
type: 'error'
}));
}
break;
default:
@@ -466,6 +499,7 @@ function _connectionFailedHandler(error) {
JitsiConnectionEvents.CONNECTION_FAILED,
_connectionFailedHandler);
if (room) {
APP.store.dispatch(conferenceWillLeave(room));
room.leave();
}
}
@@ -697,7 +731,7 @@ export default {
track.mute();
}
});
logger.log('initialized with %s local tracks', tracks.length);
logger.log(`initialized with ${tracks.length} local tracks`);
this._localTracksInitialized = true;
con.addEventListener(
JitsiConnectionEvents.CONNECTION_FAILED,
@@ -849,9 +883,6 @@ export default {
return;
}
// FIXME it is possible to queue this task twice, but it's not causing
// any issues. Specifically this can happen when the previous
// get user media call is blocked on "ask user for permissions" dialog.
if (!this.localVideo && !mute) {
const maybeShowErrorDialog = error => {
showUI && APP.UI.showCameraErrorNotification(error);
@@ -1254,16 +1285,23 @@ export default {
* @returns {Promise}
*/
useVideoStream(newStream) {
return APP.store.dispatch(
replaceLocalTrack(this.localVideo, newStream, room))
.then(() => {
this.localVideo = newStream;
this._setSharingScreen(newStream);
if (newStream) {
APP.UI.addLocalStream(newStream);
}
this.setVideoMuteStatus(this.isLocalVideoMuted());
return new Promise((resolve, reject) => {
_replaceLocalVideoTrackQueue.enqueue(onFinish => {
APP.store.dispatch(
replaceLocalTrack(this.localVideo, newStream, room))
.then(() => {
this.localVideo = newStream;
this._setSharingScreen(newStream);
if (newStream) {
APP.UI.addLocalStream(newStream);
}
this.setVideoMuteStatus(this.isLocalVideoMuted());
})
.then(resolve)
.catch(reject)
.then(onFinish);
});
});
},
/**
@@ -1293,15 +1331,22 @@ export default {
* @returns {Promise}
*/
useAudioStream(newStream) {
return APP.store.dispatch(
replaceLocalTrack(this.localAudio, newStream, room))
.then(() => {
this.localAudio = newStream;
if (newStream) {
APP.UI.addLocalStream(newStream);
}
this.setAudioMuteStatus(this.isLocalAudioMuted());
return new Promise((resolve, reject) => {
_replaceLocalAudioTrackQueue.enqueue(onFinish => {
APP.store.dispatch(
replaceLocalTrack(this.localAudio, newStream, room))
.then(() => {
this.localAudio = newStream;
if (newStream) {
APP.UI.addLocalStream(newStream);
}
this.setAudioMuteStatus(this.isLocalAudioMuted());
})
.then(resolve)
.catch(reject)
.then(onFinish);
});
});
},
/**
@@ -1654,21 +1699,16 @@ export default {
room.on(JitsiConferenceEvents.PARTCIPANT_FEATURES_CHANGED,
user => APP.UI.onUserFeaturesChanged(user));
room.on(JitsiConferenceEvents.USER_JOINED, (id, user) => {
// The logic shared between RN and web.
commonUserJoinedHandling(APP.store, room, user);
if (user.isHidden()) {
return;
}
const displayName = user.getDisplayName();
APP.store.dispatch(participantJoined({
botType: user.getBotType(),
conference: room,
id,
name: displayName,
presence: user.getStatus(),
role: user.getRole()
}));
logger.log('USER %s connnected', id, user);
logger.log(`USER ${id} connnected:`, user);
APP.API.notifyUserJoined(id, {
displayName,
formattedDisplayName: appendSuffix(
@@ -1681,11 +1721,14 @@ export default {
});
room.on(JitsiConferenceEvents.USER_LEFT, (id, user) => {
// The logic shared between RN and web.
commonUserLeftHandling(APP.store, room, user);
if (user.isHidden()) {
return;
}
APP.store.dispatch(participantLeft(id, room));
logger.log('USER %s LEFT', id, user);
logger.log(`USER ${id} LEFT:`, user);
APP.API.notifyUserLeft(id);
APP.UI.messageHandler.participantNotification(
user.getDisplayName(),
@@ -1783,35 +1826,6 @@ export default {
JitsiConferenceEvents.DOMINANT_SPEAKER_CHANGED,
id => APP.store.dispatch(dominantSpeakerChanged(id, room)));
if (!interfaceConfig.filmStripOnly) {
if (isButtonEnabled('chat')) {
room.on(
JitsiConferenceEvents.MESSAGE_RECEIVED,
(id, body, ts) => {
let nick = getDisplayName(id);
if (!nick) {
nick = `${
interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME} (${
id})`;
}
APP.API.notifyReceivedChatMessage({
id,
nick,
body,
ts
});
APP.UI.addMessage(id, nick, body, ts);
}
);
APP.UI.addListener(UIEvents.MESSAGE_CREATED, message => {
APP.API.notifySendingChatMessage(message);
room.sendTextMessage(message);
});
}
}
room.on(JitsiConferenceEvents.CONNECTION_INTERRUPTED, () => {
APP.store.dispatch(localParticipantConnectionStatusChanged(
JitsiParticipantConnectionStatus.INTERRUPTED));
@@ -1997,13 +2011,6 @@ export default {
&& APP.UI.notifyInitiallyMuted();
});
room.on(
JitsiConferenceEvents.AVAILABLE_DEVICES_CHANGED,
(id, devices) => {
APP.UI.updateDevicesAvailability(id, devices);
}
);
room.on(
JitsiConferenceEvents.DATA_CHANNEL_OPENED, () => {
APP.store.dispatch(dataChannelOpened());
@@ -2117,20 +2124,6 @@ export default {
}
);
APP.UI.addListener(
UIEvents.AUDIO_OUTPUT_DEVICE_CHANGED,
audioOutputDeviceId => {
sendAnalytics(createDeviceChangedEvent('audio', 'output'));
setAudioOutputDeviceId(audioOutputDeviceId, APP.store.dispatch)
.then(() => logger.log('changed audio output device'))
.catch(err => {
logger.warn('Failed to change audio output device. '
+ 'Default or previously set audio output device '
+ 'will be used instead.', err);
});
}
);
APP.UI.addListener(UIEvents.TOGGLE_AUDIO_ONLY, audioOnly => {
// FIXME On web video track is stored both in redux and in
@@ -2302,39 +2295,43 @@ export default {
/**
* Inits list of current devices and event listener for device change.
* @private
* @returns {Promise}
*/
_initDeviceList() {
const { mediaDevices } = JitsiMeetJS;
if (mediaDevices.isDeviceListAvailable()
&& mediaDevices.isDeviceChangeAvailable()) {
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.
const { dispatch } = APP.store;
if (this.localAudio) {
dispatch(updateSettings({
micDeviceId: this.localAudio.getDeviceId()
}));
}
if (this.localVideo) {
dispatch(updateSettings({
cameraDeviceId: this.localVideo.getDeviceId()
}));
}
APP.store.dispatch(updateDeviceList(devices));
APP.UI.onAvailableDevicesChanged(devices);
});
this.deviceChangeListener = devices =>
window.setTimeout(() => this._onDeviceListChanged(devices), 0);
mediaDevices.addEventListener(
JitsiMediaDevicesEvents.DEVICE_LIST_CHANGED,
this.deviceChangeListener);
const { dispatch } = APP.store;
return dispatch(getAvailableDevices())
.then(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 (this.localAudio) {
dispatch(updateSettings({
micDeviceId: this.localAudio.getDeviceId()
}));
}
if (this.localVideo) {
dispatch(updateSettings({
cameraDeviceId: this.localVideo.getDeviceId()
}));
}
APP.UI.onAvailableDevicesChanged(devices);
});
}
return Promise.resolve();
},
/**
@@ -2372,11 +2369,24 @@ export default {
createLocalTracksF,
newDevices.videoinput,
newDevices.audioinput)
.then(tracks =>
Promise.all(this._setLocalAudioVideoStreams(tracks)))
.then(tracks => {
// If audio or video muted before, or we unplugged current
// device and selected new one, then mute new track.
const muteSyncPromises = tracks.map(track => {
if ((track.isVideoTrack() && videoWasMuted)
|| (track.isAudioTrack() && audioWasMuted)) {
return track.mute();
}
return Promise.resolve();
});
return Promise.all(muteSyncPromises)
.then(() => Promise.all(
this._setLocalAudioVideoStreams(tracks)));
})
.then(() => {
// If audio was muted before, or we unplugged current device
// and selected new one, then mute new audio track.
// Log and sync known mute state.
if (audioWasMuted) {
sendAnalytics(createTrackMutedEvent(
'audio',
@@ -2385,8 +2395,6 @@ export default {
muteLocalAudio(true);
}
// If video was muted before, or we unplugged current device
// and selected new one, then mute new video track.
if (!this.isSharingScreen && videoWasMuted) {
sendAnalytics(createTrackMutedEvent(
'video',
@@ -2485,13 +2493,24 @@ export default {
// before all operations are done.
Promise.all([
requestFeedbackPromise,
room.leave().then(disconnect, disconnect)
this.leaveRoomAndDisconnect()
]).then(values => {
APP.API.notifyReadyToClose();
maybeRedirectToWelcomePage(values[0]);
});
},
/**
* Leaves the room and calls JitsiConnection.disconnect.
*
* @returns {Promise}
*/
leaveRoomAndDisconnect() {
APP.store.dispatch(conferenceWillLeave(room));
return room.leave().then(disconnect, disconnect);
},
/**
* Changes the email for the local user
* @param email {string} the new email

View File

@@ -18,9 +18,6 @@ var config = {
// XMPP domain.
domain: 'jitsi-meet.example.com',
// XMPP MUC domain. FIXME: use XEP-0030 to discover it.
muc: 'conference.jitsi-meet.example.com'
// When using authentication, domain for guest users.
// anonymousdomain: 'guest.example.com',
@@ -35,6 +32,9 @@ var config = {
// Focus component domain. Defaults to focus.<domain>.
// focus: 'focus.jitsi-meet.example.com',
// XMPP MUC domain. FIXME: use XEP-0030 to discover it.
muc: 'conference.jitsi-meet.example.com'
},
// BOSH URL. FIXME: use XEP-0156 to discover it.
@@ -171,10 +171,18 @@ var config = {
// Whether to enable file recording or not.
// fileRecordingsEnabled: false,
// Enable the dropbox integration.
// dropbox: {
// appKey: '<APP_KEY>' // Specify your app key here.
// },
// Whether to enable live streaming or not.
// liveStreamingEnabled: false,
// Transcription (in interface_config,
// subtitles and buttons can be configured)
// transcribingEnabled: false,
// Misc
// Default value for the channel "last N" attribute. -1 for unlimited.
@@ -233,10 +241,6 @@ var config = {
// Disable hiding of remote thumbnails when in a 1-on-1 conference call.
// disable1On1Mode: false,
// The minimum value a video's height (or width, whichever is smaller) needs
// to be in order to be considered high-definition.
minHDHeight: 540,
// Default language for the user interface.
// defaultLanguage: 'en',
@@ -252,6 +256,10 @@ var config = {
// maintenance at 01:00 AM GMT,
// noticeMessage: '',
// Enables calendar integration, depends on googleApiApplicationClientID
// and microsoftApiApplicationClientID
// enableCalendarIntegration: false,
// Stats
//
@@ -343,6 +351,36 @@ var config = {
// userRegion: "asia"
}
// Local Recording
//
// localRecording: {
// Enables local recording.
// Additionally, 'localrecording' (all lowercase) needs to be added to
// TOOLBAR_BUTTONS in interface_config.js for the Local Recording
// button to show up on the toolbar.
//
// enabled: true,
//
// The recording format, can be one of 'ogg', 'flac' or 'wav'.
// format: 'flac'
//
// }
// Options related to end-to-end (participant to participant) ping.
// e2eping: {
// // The interval in milliseconds at which pings will be sent.
// // Defaults to 10000, set to <= 0 to disable.
// pingInterval: 10000,
//
// // The interval in milliseconds at which analytics events
// // with the measured RTT will be sent. Defaults to 60000, set
// // to <= 0 to disable.
// analyticsInterval: 60000,
// }
// List of undocumented settings used in jitsi-meet
/**
_immediateReloadThreshold
@@ -362,8 +400,10 @@ var config = {
externalConnectUrl
firefox_fake_device
googleApiApplicationClientID
googleApiIOSClientID
iAmRecorder
iAmSipGateway
microsoftApiApplicationClientID
peopleSearchQueryTypes
peopleSearchUrl
requireDisplayName
@@ -392,6 +432,7 @@ var config = {
nick
startBitrate
*/
};
/* eslint-enable no-unused-vars, no-var */

View File

@@ -1,19 +0,0 @@
/**
* Project animations
**/
/**
* Slide in animation for extended toolbar (inner) panel.
*/
// FIX: Can't use percentage because of breaking animation when width is changed
// (100% of 0 is also zero) Extracted this to config variable.
@include keyframes(slideInExt) {
from { left: -$sidebarWidth; }
to { left: 0; }
}
@include keyframes(slideOutExt) {
from { left: 0; }
to { left: -$sidebarWidth; }
}

View File

@@ -10,3 +10,48 @@
-ms-transform: translateX(0) translateY(100%) translateY(16px) !important;
-webkit-transform: translateX(0) translateY(100%) translateY(16px) !important;
}
/**
* Welcome page tab color adjustments.
*/
.welcome {
/**
* The text color of the selected tab and hovered tabs.
*/
.bVobOt,
.bVobOt:hover,
.ebveIl:hover {
color: #172B4D;
}
/**
* The color of the inactive tab text.
*/
.ebveIl {
color: #FFFFFF;
}
/**
* The color of the underline of a selected tab.
*/
.kByArU {
background-color: #172B4D;
}
}
.modal-dialog-form {
/**
* Update the dropdown trigger wrapper to make sure it looks click-able.
*/
.gwEjuO {
cursor: pointer;
}
/**
* Override Atlaskit dropdown styling when in a modal because the dropdown
* backgrounds clash with the modal backgrounds.
*/
.gBLqhw[data-role=droplistContent] {
border: 1px solid #455166;
}
}

View File

@@ -108,14 +108,15 @@ form {
}
.leftwatermark {
left: $defaultToolbarSize;
margin-left: 10px;
left: 32px;
top: 32px;
background-image: url($defaultWatermarkLink);
background-position: center left;
}
.rightwatermark {
right: 15;
right: 32px;
top: 32px;
background-position: center right;
}

View File

@@ -1,21 +1,58 @@
#sideToolbarContainer {
background-color: $newToolbarBackgroundColor;
display: flex;
/**
* Make the sidebar flush with the top of the toolbar. Take the size of
* the toolbar and subtract from 100%.
*/
height: calc(100% - #{$newToolbarSizeWithPadding});
left: -$sidebarWidth;
overflow: hidden;
position: absolute;
top: 0;
transition: left 0.5s;
width: $sidebarWidth;
z-index: $sideToolbarContainerZ;
/**
* The sidebar (chat) is off-screen when hidden. Move it flush to the left
* side of the window when it should be visible.
*/
&.slideInExt {
left: 0;
}
.sideToolbarContainer__inner {
box-sizing: border-box;
color: #FFF;
display: flex;
flex-direction: column;
height: 100%;
width: $sidebarWidth;
}
}
#chat_container * {
-webkit-user-select: text;
user-select: text;
}
#chatconversation {
visibility: hidden;
position: relative;
top: 15px;
box-sizing: border-box;
flex: 1;
font-size: 10pt;
line-height: 20px;
margin-top: 15px;
overflow: auto;
padding: 5px;
text-align: left;
line-height: 20px;
font-size: 10pt;
width: 100%;
height: 90%;
overflow: auto;
width: $sidebarWidth;
word-wrap: break-word;
a {
display: block;
}
a:link {
color: rgb(184, 184, 184);
}
@@ -55,41 +92,52 @@
}
}
#chat_container.is-conversation-mode #chatconversation {
visibility: visible;
.chat-close {
background: gray;
border: 3px solid rgba(255, 255, 255, 0.1);
border-radius: 100%;
color: white;
cursor:pointer;
height: 10px;
line-height: 10px;
padding: 4px;
position: absolute;
right: 5px;
text-align: center;
top: 5px;
width: 10px;
z-index: 1;
}
.localuser {
color: #4C9AFF
}
.errorMessage {
color: red;
#chat-input {
background-color: $newToolbarBackgroundColor;
display: flex;
}
.remoteuser {
color: #B8C7E0;
}
.usrmsg-form {
flex: 1;
margin-left: 5px;
}
#usermsg {
background-color: $newToolbarBackgroundColor;
visibility:hidden;
position: absolute;
bottom: 0px;
right: 0px;
width: 83%;
height: 30px;
border: 0px none;
border-radius:0;
box-shadow: none;
color: white;
font-size: 10pt;
line-height: 30px;
padding: 5px 5px 5px 0px;
max-height:150px;
min-height:35px;
border: 0px none;
color: white;
box-shadow: none;
border-radius:0;
font-size: 10pt;
line-height: 30px;
overflow: hidden;
overflow-y: auto;
resize: none;
width: 100%;
word-break: break-word;
}
#usermsg:hover {
@@ -97,10 +145,6 @@
box-shadow: none;
}
#chat_container.is-conversation-mode #usermsg {
visibility: visible;
}
#nickname {
position: absolute;
text-align: center;
@@ -112,20 +156,7 @@
width: 95%;
}
#chat_container.is-conversation-mode #nickname {
visibility: hidden;
}
#nickinput {
margin-top: 20px;
font-size: 14px;
background: #3a3a3a;
box-shadow: inset 0 0 3px 2px #a7a7a7;
border: 1px solid #a7a7a7;
color: #a7a7a7;
}
#chat_container .username {
#chat_container .display-name {
float: left;
padding-left: 5px;
font-weight: bold;
@@ -141,29 +172,45 @@
font-size: 11px;
}
#chat_container .usermessage {
.usermessage {
padding-top: 20px;
padding-left: 5px;
}
.chatArrow {
position: absolute;
height: 15px;
left: 5px;
left: -10px;
position: absolute;
}
.chatmessage {
background-color: $newToolbarBackgroundColor;;
background-color: $newToolbarBackgroundColor;
width: 93%;
margin-left: 9px;
margin-right: auto;
border-radius: 5px;
border-top-left-radius: 0px;
margin-top: 3px;
left: 5px;
color: white;
overflow: hidden;
padding-bottom: 3px;
position: relative;
&.localuser .display-name {
color: #4C9AFF
}
&.error {
.chatArrow,
.timestamp,
.display-name {
display: none;
}
.usermessage {
color: red;
padding: 0;
}
}
}
.smiley {
@@ -171,11 +218,9 @@
}
#smileys {
position: absolute;
bottom: 7px;
right: 5px;
background: white;
border-radius: 50px;
border-radius: 50%;
display: inline-block;
height: 26px;
margin: auto;
cursor: pointer;
@@ -187,33 +232,40 @@
}
#smileysarea {
position: absolute;
bottom: 0px;
left: 0px;
width: 17%;
min-width: 31px;
height: 40px;
padding: 0px;
max-height:150px;
min-height:35px;
background-color: $newToolbarBackgroundColor;
border: 0px none;
background-color: $newToolbarBackgroundColor;
display: flex;
height: 70px;
max-height: 150px;
min-height: 35px;
min-width: 31px;
padding: 0px;
overflow: hidden;
visibility: hidden;
width: 17%;
}
#chat_container.is-conversation-mode #smileysarea {
visibility: visible;
.smiley-input {
position: relative;
}
#smileysContainer {
display: none;
.smileys-panel {
bottom: 100%;
box-sizing: border-box;
height: 0;
overflow: hidden;
position: absolute;
background-color: $newToolbarBackgroundColor;
border-bottom: 1px solid;
border-top: 1px solid;
width: 100%;
bottom: 10%;
transition: height 0.3s;
width: $sidebarWidth;
&.show-smileys {
height: 202px;
}
#smileysContainer {
background-color: $newToolbarBackgroundColor;
border-bottom: 1px solid;
border-top: 1px solid;
}
}
#smileysContainer .smiley {

View File

@@ -24,6 +24,7 @@
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-arrow_back:before {
content: "\e5c4";
}
@@ -210,3 +211,12 @@
.icon-speaker:before {
content: "\e92d";
}
.icon-tiles-many:before {
content: "\e92e";
}
.icon-tiles-one:before {
content: "\e92f";
}
.icon-closed_caption:before {
content: "\e930";
}

117
css/_meetings_list.scss Normal file
View File

@@ -0,0 +1,117 @@
.meetings-list {
font-size: 14px;
color: #253858;
line-height: 20px;
text-align: left;
text-overflow: ellipsis;
display: flex;
flex-direction: column;
position: relative;
width: 100%;
height: 100%;
overflow: auto;
.meetings-list-empty {
text-align: center;
align-items: center;
justify-content: center;
display: flex;
flex-grow: 1;
flex-direction: column;
.description {
font-size: 16px;
padding: 20px;
}
}
.button {
background: #0074E0;
border-radius: 4px;
color: #FFFFFF;
display: flex;
justify-content: center;
align-items: center;
padding: 5px 10px;
cursor: pointer;
}
.item {
background: rgba(255,255,255,0.50);
box-sizing: border-box;
display: inline-flex;
margin-top: 5px;
min-height: 92px;
width: 100%;
word-break: break-word;
display: flex;
flex-direction: row;
text-align: left;
&:first-child {
margin-top: 0px;
}
.left-column {
display: flex;
flex-direction: column;
width: 140px;
flex-grow: 0;
padding-left: 30px;
padding-top: 25px;
.date {
font-weight: bold;
padding-bottom: 5px;
}
}
.right-column {
display: flex;
flex-direction: column;
flex-grow: 1;
padding-left: 30px;
padding-top: 25px;
.title {
font-size: 16px;
font-weight: bold;
padding-bottom: 5px;
}
}
.actions {
display: flex;
align-items: center;
justify-content: center;
flex-grow: 0;
padding-right: 30px;
}
&.with-click-handler {
cursor: pointer;
}
&.with-click-handler:hover {
background-color: #75A7E7;
}
.add-button {
width: 30px;
height: 30px;
padding: 0px;
}
i {
cursor: inherit;
}
.join-button {
display: none;
}
&:hover .join-button {
display: block
}
}
}

View File

@@ -0,0 +1,80 @@
%navigate-section-list-text {
width: 100%;
font-size: 14px;
line-height: 20px;
color: $welcomePageTitleColor;
text-align: left;
font-family: 'open_sanslight', Helvetica, sans-serif;
}
%navigate-section-list-tile-text {
@extend %navigate-section-list-text;
overflow: hidden;
text-overflow: ellipsis;
float: left;
}
.navigate-section-list-tile {
background-color: #1754A9;
border-radius: 4px;
box-sizing: border-box;
display: inline-flex;
margin-bottom: 8px;
margin-right: 8px;
min-height: 100px;
padding: 16px;
width: 100%;
&.with-click-handler {
cursor: pointer;
}
&.with-click-handler:hover {
background-color: #1a5dbb;
}
i {
cursor: inherit;
}
.element-after {
display: flex;
align-items: center;
justify-content: center;
}
.join-button {
display: none;
}
&:hover .join-button {
display: block
}
}
.navigate-section-tile-body {
@extend %navigate-section-list-tile-text;
font-weight: normal;
line-height: 24px;
}
.navigate-section-list-tile-info {
flex: 1;
word-break: break-word;
}
.navigate-section-tile-title {
@extend %navigate-section-list-tile-text;
font-weight: bold;
line-height: 24px;
}
.navigate-section-section-header {
@extend %navigate-section-list-text;
font-weight: bold;
margin-bottom: 16px;
display: block;
}
.navigate-section-list {
position: relative;
margin-top: 36px;
margin-bottom: 36px;
width: 100%;
}
.navigate-section-list-empty {
text-align: center;
}

View File

@@ -10,14 +10,24 @@
right: 0;
width: 100%;
}
.popover-mousemove-padding-right {
%vertical-popover-padding {
height: 100%;
position: absolute;
right: -20;
top: 0;
width: 40px;
}
.popover-mousemove-padding-left {
@extend %vertical-popover-padding;
left: -20px;
}
.popover-mousemove-padding-right {
@extend %vertical-popover-padding;
right: -20px;
}
/**
* An invisible element is added to the top of the popover to ensure the mouse
* stays over the popover when the popover's height is shrunk, which would then

View File

@@ -2,6 +2,57 @@
vertical-align: top;
}
.recording-dialog {
flex: 0;
flex-direction: column;
.recording-header {
display: flex;
flex: 0;
flex-direction: row;
justify-content: space-between;
align-items: center;
.recording-title {
font-size: 16px;
font-weight: bold;
}
}
.authorization-panel {
display: flex;
flex-direction: column;
margin-bottom: 10px;
padding-bottom: 10px;
.dropbox-sign-in {
align-items: center;
border: 1px solid #4285f4;
background-color: white;
border-radius: 2px;
cursor: pointer;
display: inline-flex;
padding: 10px;
font-size: 18px;
font-weight: 600;
margin: 10px 0px;
color: #4285f4;
.dropbox-logo {
background-color: white;
border-radius: 2px;
display: inline-block;
padding-right: 5px;
height: 18px;
}
}
.logged-in-panel {
padding: 10px;
}
}
}
.live-stream-dialog {
/**
* Set font-size to be consistent with Atlaskit FieldText.
@@ -34,39 +85,6 @@
color: $errorColor;
}
/**
* The Google sign in button must follow Google's design guidelines.
* See: https://developers.google.com/identity/branding-guidelines
*/
.google-sign-in {
background-color: #4285f4;
border-radius: 2px;
cursor: pointer;
display: inline-flex;
font-family: Roboto, arial, sans-serif;
font-size: 14px;
padding: 1px;
.google-cta {
color: white;
display: inline-block;
/**
* Hack the line height for vertical centering of text.
*/
line-height: 32px;
margin: 0 15px;
}
.google-logo {
background-color: white;
border-radius: 2px;
display: inline-block;
padding: 8px;
height: 18px;
width: 18px;
}
}
.google-panel {
align-items: center;
border-bottom: 2px solid rgba(0, 0, 0, 0.3);

View File

@@ -1,105 +0,0 @@
/**
* Toolbar side panel main container element.
*/
#sideToolbarContainer {
background-color: $newToolbarBackgroundColor;
/**
* Make the sidebar flush with the top of the toolbar. Take the size of
* the toolbar and subtract from 100%.
*/
height: calc(100% - #{$newToolbarSizeWithPadding});
left: 0;
max-width: $sidebarWidth;
overflow: hidden;
position: absolute;
top: 0;
width: 0;
z-index: $sideToolbarContainerZ;
/**
* Labels inside the side panel.
*/
label {
color: $baseLight;
}
/**
* Form elements and blocks.
*/
input,
a,
.sideToolbarBlock,
.form-control {
display: block;
margin-top: 15px;
margin-left: 10%;
width: 80%;
}
/**
* Specify styling of elements inside a block.
*/
.sideToolbarBlock {
input, a {
margin-left: 0;
margin-top: 5px;
width: 100%;
}
}
/**
* Inner container, for example settings or profile.
*/
.sideToolbarContainer__inner {
display: none;
height: 100%;
width: $sidebarWidth;
position: absolute;
box-sizing: border-box;
color: #FFF;
.input-control {
border: 0;
}
/**
* Titles and subtitles of inner containers.
*/
div.title {
margin: 24px 0 11px;
}
/**
* Main title size.
*/
div.title {
color: $toolbarTitleColor;
text-align: center;
font-size: $toolbarTitleFontSize;
}
/**
* First element after a title.
*/
.first {
margin-top: 0 !important;
}
}
.side-toolbar-close {
background: gray;
border: 3px solid rgba(255, 255, 255, 0.1);
border-radius: 100%;
color: white;
cursor:pointer;
height: 10px;
line-height: 10px;
padding: 4px;
position: absolute;
right: 5px;
text-align: center;
top: 5px;
width: 10px;
z-index: 1;
}
}

View File

@@ -146,7 +146,6 @@
background: #B8C7E0;
border-radius: 2px;
color: $newToolbarBackgroundColor;
font-family: -apple-system, BlinkMacSystemFont, $baseFontFamily;
font-size: 11px;
font-weight: bold;
margin-left: 8px;
@@ -304,27 +303,6 @@
}
}
/**
* START of slide in animation for extended toolbar panel.
*/
@include keyframes(slideInExt) {
from { width: 0px; }
to { width: $sidebarWidth; } // TO FIX: Make this value a percentage.
}
.slideInExt {
@include animation("slideInExt .5s forwards");
}
@include keyframes(slideOutExt) {
from { width: $sidebarWidth; } // TO FIX: Make this value a percentage.
to { width: 0px; }
}
.slideOutExt {
@include animation("slideOutExt .5s forwards");
}
/**
* START of fade in animation for main toolbar
*/

View File

@@ -2,12 +2,19 @@
bottom: 10%;
font-size: 16px;
font-weight: 1000;
left: 50%;
max-width: 50vw;
opacity: 0.80;
pointer-events: none;
position: absolute;
text-shadow: 0px 0px 1px rgba(0,0,0,0.3),
0px 1px 1px rgba(0,0,0,0.3),
1px 0px 1px rgba(0,0,0,0.3),
0px 0px 1px rgba(0,0,0,0.3);
width: 100%;
z-index: $zindex2;
transform: translateX(-50%);
z-index: $filmstripVideosZ + 1;
span {
background: black;
}
}

View File

@@ -3,7 +3,7 @@
/**
* Style variables
*/
$baseFontFamily: 'open_sanslight', 'Helvetica Neue', Helvetica, Arial, sans-serif;
$baseFontFamily: -apple-system, BlinkMacSystemFont, 'open_sanslight', 'Helvetica Neue', Helvetica, Arial, sans-serif;
$hangupColor: #bf2117;
$hangupFontSize: 2em;
@@ -146,5 +146,5 @@ $watermarkHeight: 74px;
*/
$welcomePageDescriptionColor: #fff;
$welcomePageFontFamily: inherit;
$welcomePageHeaderBackground: linear-gradient(#165ecc, #44A5FF);
$welcomePageHeaderBackground: linear-gradient(-90deg, #1251AE 0%, #0074FF 50%, #1251AE 100%);
$welcomePageTitleColor: #fff;

View File

@@ -86,7 +86,7 @@
* wrapper needed before we're able to move all top toolbar indicators
* creation to react.
*/
.ckAJgx {
.sc-ifAKCX {
background: none;
}
}
@@ -557,30 +557,6 @@
object-fit: cover;
}
.noMic {
position: absolute;
border-radius: 8px;
z-index: $zindex1;
width: 100%;
height: 100%;
background-image: url("../images/noMic.png");
background-color: #000;
background-repeat: no-repeat;
background-position: center;
}
.noVideo {
position: absolute;
border-radius: 8px;
z-index: $zindex1;
width: 100%;
height: 100%;
background-image: url("../images/noVideo.png");
background-color: #000;
background-repeat: no-repeat;
background-position: center;
}
.videoMessageFilter {
-webkit-filter: grayscale(.5) opacity(0.8);
filter: grayscale(.5) opacity(0.8);

View File

@@ -4,15 +4,19 @@ body.welcome-page {
}
.welcome {
background-image: $welcomePageHeaderBackground;
display: flex;
flex-direction: column;
font-family: $welcomePageFontFamily;
height: 100%;
justify-content: space-between;
min-height: 100vh;
position: relative;
.header {
align-items: center;
background: $welcomePageHeaderBackground;
display: flex;
flex-direction: column;
min-height: fit-content;
overflow: hidden;
position: relative;
text-align: center;
@@ -20,74 +24,148 @@ body.welcome-page {
.header-text {
display: flex;
flex-direction: column;
justify-content: space-around;
margin-top: 120px;
margin-bottom: 20px;
margin-top: $watermarkHeight + 35;
margin-bottom: 35px;
max-width: calc(100% - 40px);
min-height: 286px;
width: 645px;
width: 650px;
z-index: $zindex2;
}
.header-text-title {
color: $welcomePageTitleColor;
font-size: 48px;
letter-spacing: -1px;
line-height: 58px;
margin-bottom: 20px;
font-size: 2.5rem;
font-weight: 500;
line-height: 1.18;
margin-bottom: 16px;
}
.header-text-description {
color: $welcomePageDescriptionColor;
font-size: 20px;
line-height: 28px;
opacity: 0.8;
}
.header-image {
background-image: url(../images/welcome_page/curves.png);
background-size: contain;
height: 209px;
position: absolute;
width: 1070px;
}
#new_enter_room {
align-items: center;
display: flex;
font-size: 1rem;
font-weight: 400;
line-height: 24px;
margin-bottom: 20px;
max-width: calc(100% - 40px);
position: relative;
z-index: 2;
}
.enter-room-input {
display: inline-block;
margin-right: 15px;
width: 350px;
#enter_room {
display: flex;
align-items: center;
max-width: calc(100% - 40px);
width: 680px;
z-index: $zindex2;
background-color: #fff;
padding: 25px 30px;
.enter-room-input-container {
width: 100%;
padding-right: 8px;
padding-bottom: 5px;
text-align: left;
color: #253858;
height: fit-content;
border-width: 0px 0px 2px 0px;
border-style: solid;
border-image: linear-gradient(to right, #dee1e6, #fff) 1;
.enter-room-title {
font-size: 18px;
font-weight: bold;
padding-bottom: 5px;
}
.enter-room-input {
border: none;
display: inline-block;
width: 100%;
font-size: 14px;
}
::placeholder {
color: #253858;
}
}
}
.tab-container {
font-size: 16px;
position: relative;
text-align: left;
min-height: 354px;
width: 710px;
background: #75A7E7;
display: flex;
flex-direction: column;
.tab-content{
margin: 5px 0px;
overflow: hidden;
flex-grow: 1;
position: relative;
> * {
position: absolute;
}
}
.tab-buttons {
font-size: 18px;
color: #FFFFFF;
display: flex;
flex-grow: 0;
flex-direction: row;
min-height: 54px;
width: 100%;
.tab {
text-align: center;
background: rgba(9,30,66,0.37);
height: 55px;
line-height: 54px;
flex-grow: 1;
cursor: pointer;
&.selected, &:hover {
background: rgba(9,30,66,0.71);
}
&:last-child {
margin-left: 1px;
}
}
}
}
}
.welcome-page-button {
font-size: 16px;
width: 51px;
height: 35px;
font-size: 14px;
background: #0074E0;
border-radius: 4px;
color: #FFFFFF;
text-align: center;
vertical-align: middle;
line-height: 35px;
cursor: pointer;
}
}
.welcome.with-content {
.header {
min-height: 552px;
}
.header-image {
left: -61px;
top: 401px;
}
}
.welcome-page-settings {
color: $welcomePageDescriptionColor;
position: absolute;
top: 32px;
right: 32px;
z-index: $zindex2;
.welcome.without-content {
.header {
* {
cursor: pointer;
font-size: 32px;
}
}
.welcome-watermark {
position: absolute;
width: 100%;
height: 100%;
}
.header-image {
bottom: -20px;
left: 0;
}
}

View File

@@ -14,14 +14,9 @@
* Focused video thumbnail.
*/
&.videoContainerFocused {
transition-duration: 0.5s;
-webkit-transition-duration: 0.5s;
-webkit-animation-name: greyPulse;
-webkit-animation-duration: 2s;
-webkit-animation-iteration-count: 1;
border: $thumbnailVideoBorder solid $videoThumbnailSelected !important;
border: $thumbnailVideoBorder solid $videoThumbnailSelected;
box-shadow: inset 0 0 3px $videoThumbnailSelected,
0 0 3px $videoThumbnailSelected !important;
0 0 3px $videoThumbnailSelected;
}
.remotevideomenu > .icon-menu {
@@ -31,7 +26,7 @@
/**
* Hovered video thumbnail.
*/
&:hover {
&:hover:not(.videoContainerFocused):not(.active-speaker) {
cursor: hand;
border: $thumbnailVideoBorder solid $videoThumbnailHovered;
box-shadow: inset 0 0 3px $videoThumbnailHovered,

View File

@@ -0,0 +1,113 @@
/**
* CSS styles that are specific to the filmstrip that shows the thumbnail tiles.
*/
.tile-view {
/**
* Add a border around the active speaker to make the thumbnail easier to
* see.
*/
.active-speaker {
box-shadow: 0 0 5px 3px $videoThumbnailSelected
}
#filmstripRemoteVideos {
align-items: center;
box-sizing: border-box;
display: flex;
flex-direction: column;
height: 100vh;
width: 100vw;
}
.filmstrip__videos .videocontainer {
&:not(.active-speaker),
&:hover:not(.active-speaker) {
border: none;
box-shadow: none;
}
}
#remoteVideos {
/**
* Height is modified with an inline style in horizontal filmstrip mode
* so !important is used to override that.
*/
height: 100% !important;
width: 100%;
}
.filmstrip {
align-items: center;
display: flex;
height: 100%;
justify-content: center;
left: 0;
position: fixed;
top: 0;
width: 100%;
z-index: $filmstripVideosZ
}
/**
* Regardless of the user setting, do not let the filmstrip be in a hidden
* state.
*/
.filmstrip__videos.hidden {
display: block;
}
#filmstripRemoteVideos {
box-sizing: border-box;
/**
* Allow vertical scrolling of the thumbnails.
*/
overflow-x: hidden;
overflow-y: auto;
}
/**
* The size of the thumbnails should be set with javascript, based on
* desired column count and window width. The rows are created using flex
* and allowing the thumbnails to wrap.
*/
#filmstripRemoteVideosContainer {
align-content: center;
align-items: center;
box-sizing: border-box;
display: flex;
flex-wrap: wrap;
height: 100vh;
justify-content: center;
padding: 100px 0;
.videocontainer {
border: 0;
box-sizing: border-box;
display: block;
margin: 5px;
}
video {
object-fit: contain;
}
}
.has-overflow#filmstripRemoteVideosContainer {
align-content: baseline;
}
.has-overflow .videocontainer {
align-self: baseline;
}
/**
* Firefox flex acts a little differently. To make sure the bottom row of
* thumbnails is not overlapped by the horizontal toolbar, margin is added
* to the local thumbnail to keep it from the bottom of the screen. It is
* assumed the local thumbnail will always be on the bottom row.
*/
.has-overflow #localVideoContainer {
margin-bottom: 100px !important;
}
}

View File

@@ -0,0 +1,47 @@
/**
* Various overrides outside of the filmstrip to style the app to support a
* tiled thumbnail experience.
*/
.tile-view {
/**
* Let the avatar grow with the tile.
*/
.userAvatar {
max-height: initial;
max-width: initial;
}
/**
* Hide various features that should not be displayed while in tile view.
*/
#dominantSpeaker,
#filmstripLocalVideoThumbnail,
#largeVideoElementsContainer,
#sharedVideo,
.filmstrip__toolbar {
display: none;
}
#localConnectionMessage,
#remoteConnectionMessage,
.watermark {
z-index: $filmstripVideosZ + 1;
}
/**
* The follow styling uses !important to override inline styles set with
* javascript.
*
* TODO: These overrides should be more easy to remove and should be removed
* when the components are in react so their rendering done declaratively,
* making conditional styling easier to apply.
*/
#largeVideoElementsContainer,
#remoteConnectionMessage,
#remotePresenceMessage {
display: none !important;
}
#largeVideoContainer {
background-color: $defaultBackground !important;
}
}

View File

@@ -127,7 +127,7 @@
/**
* Override other styles to support vertical filmstrip mode.
*/
.vertical-filmstrip.filmstrip-only {
.filmstrip-only .vertical-filmstrip {
.filmstrip {
flex-direction: row-reverse;
}

View File

@@ -16,10 +16,6 @@
/* Mixins END */
/* Animations BEGIN */
@import "animations";
/* Animations END */
/* Fonts BEGIN */
@@ -45,6 +41,7 @@
@import 'modals/settings/settings';
@import 'modals/speaker_stats/speaker_stats';
@import 'modals/video-quality/video-quality';
@import 'modals/local-recording/local-recording';
@import 'videolayout_default';
@import 'notice';
@import 'popup_menu';
@@ -55,7 +52,6 @@
@import 'welcome_page';
@import 'welcome_page_content';
@import 'toolbars';
@import 'side_toolbar_container';
@import 'jquery.contextMenu';
@import 'keyboard-shortcuts';
@import 'redirect_page';
@@ -72,10 +68,17 @@
@import 'filmstrip/filmstrip_toolbar';
@import 'filmstrip/horizontal_filmstrip';
@import 'filmstrip/small_video';
@import 'filmstrip/tile_view';
@import 'filmstrip/tile_view_overrides';
@import 'filmstrip/vertical_filmstrip';
@import 'filmstrip/vertical_filmstrip_overrides';
@import 'unsupported-browser/main';
@import 'modals/invite/add-people';
@import 'deep-linking/main';
@import 'transcription-subtitles';
@import '_meetings_list.scss';
@import 'navigate_section_list';
@import 'third-party-branding/google';
@import 'third-party-branding/microsoft';
/* Modules END */

View File

@@ -154,14 +154,6 @@
&-error {
margin-bottom: 8px;
}
/**
* Override Atlaskit dropdown styling when in a modal because the dropdown
* backgrounds clash with the modal backgrounds.
*/
.htclLc[data-role=droplistContent] {
border: 1px solid #455166;
}
}
.modal-dialog-footer {
font-size: $modalButtonFontSize;

View File

@@ -0,0 +1,92 @@
.localrec-participant-stats {
list-style: none;
padding: 0;
width: 100%;
font-weight: 500;
.localrec-participant-stats-item__status-dot {
position: relative;
display: block;
width: 9px;
height: 9px;
border-radius: 50%;
margin: 0 auto;
&.status-on {
background: green;
}
&.status-off {
background: gray;
}
&.status-unknown {
background: darkgoldenrod;
}
&.status-error {
background: darkred;
}
}
.localrec-participant-stats-item__status,
.localrec-participant-stats-item__name,
.localrec-participant-stats-item__sessionid {
display: inline-block;
margin: 5px 0;
vertical-align: middle;
}
.localrec-participant-stats-item__status {
width: 5%;
}
.localrec-participant-stats-item__name {
width: 40%;
}
.localrec-participant-stats-item__sessionid {
width: 55%;
}
.localrec-participant-stats-item__name,
.localrec-participant-stats-item__sessionid {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.localrec-control-info-label {
font-weight: bold;
}
.localrec-control-info-label:after {
content: ' ';
}
.localrec-control-action-link {
display: inline-block;
line-height: 1.5em;
a {
cursor: pointer;
vertical-align: middle;
}
}
.localrec-control-action-link:before {
color: $linkFontColor;
content: '\2022';
font-size: 1.5em;
padding: 0 10px;
vertical-align: middle;
}
.localrec-control-action-link:first-child:before {
content: '';
padding: 0;
}
.localrec-control-action-links {
font-weight: bold;
margin-top: 10px;
white-space: nowrap;
}

View File

@@ -10,6 +10,7 @@
margin-bottom: 4px;
}
.calendar-tab,
.device-selection {
margin-top: 20px;
}
@@ -22,6 +23,7 @@
padding: 20px 0px 4px 0px;
}
.calendar-tab,
.more-tab,
.profile-edit {
display: flex;
@@ -40,4 +42,20 @@
.language-settings {
max-width: 50%;
}
.calendar-tab {
align-items: center;
flex-direction: column;
font-size: 14px;
min-height: 100px;
text-align: center;
}
.calendar-tab-sign-in {
margin-top: 20px;
}
.sign-out-cta {
margin-bottom: 20px;
}
}

View File

@@ -155,7 +155,6 @@
.circular-label {
color: white;
font-family: -apple-system, BlinkMacSystemFont, $baseFontFamily;
font-weight: bold;
margin-left: 8px;
opacity: 0.8;
@@ -169,6 +168,10 @@
background: #FF5630;
}
.circular-label.local-rec {
background: #FF5630;
}
.circular-label.stream {
background: #0065FF;
}

View File

@@ -0,0 +1,32 @@
/**
* The Google sign in button must follow Google's design guidelines.
* See: https://developers.google.com/identity/branding-guidelines
*/
.google-sign-in {
background-color: #4285f4;
border-radius: 2px;
cursor: pointer;
display: inline-flex;
font-family: Roboto, arial, sans-serif;
font-size: 14px;
padding: 1px;
.google-cta {
color: white;
display: inline-block;
/**
* Hack the line height for vertical centering of text.
*/
line-height: 32px;
margin: 0 15px;
}
.google-logo {
background-color: white;
border-radius: 2px;
display: inline-block;
padding: 8px;
height: 18px;
width: 18px;
}
}

View File

@@ -0,0 +1,28 @@
/**
* The Microsoft sign in button must follow Microsoft's brand guidelines.
* See: https://docs.microsoft.com/en-us/azure/active-directory/
* develop/active-directory-branding-guidelines
*/
.microsoft-sign-in {
align-items: center;
background: #FFFFFF;
border: 1px solid #8C8C8C;
box-sizing: border-box;
cursor: pointer;
display: inline-flex;
font-family: Segoe UI, Roboto, arial, sans-serif;
height: 41px;
padding: 12px;
.microsoft-cta {
display: inline-block;
color: #5E5E5E;
font-size: 15px;
line-height: 41px;
}
.microsoft-logo {
display: inline-block;
margin-right: 12px;
}
}

View File

@@ -135,7 +135,8 @@ server {
location / {
ssi on;
}
# BOSH
# BOSH, Bidirectional-streams Over Synchronous HTTP
# https://en.wikipedia.org/wiki/BOSH_(protocol)
location /http-bind {
proxy_pass http://localhost:5280/http-bind;
proxy_set_header X-Forwarded-For $remote_addr;

28
doc/mobile-dropbox.md Normal file
View File

@@ -0,0 +1,28 @@
# Setting up Dropbox integration
1. Create a Dropbox app.
2. Add the following to ```ios/app/src/Info.plist``` by replacing `<APP_KEY>`
with your own Dropbox app key (which can be found in the
[App Console](https://www.dropbox.com/developers/apps)):
```
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string></string>
<key>CFBundleURLSchemes</key>
<array>
<string>db-<APP_KEY></string>
</array>
</dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>dbapi-2</string>
<string>dbapi-8-emm</string>
</array>
```
**NOTE:** Both Android and iOS builds of the apps will parse the Dropbox app key
from ```ios/app/src/Info.plist```.
**NOTE:** See [Dropbox developer guide](https://www.dropbox.com/developers/reference/developer-guide) for more information

22
doc/mobile-google-auth.md Normal file
View File

@@ -0,0 +1,22 @@
# Setting up Google Authentication
- Create a Firebase project here: https://firebase.google.com/. You'll need a
signed Android build for that, that can be a debug self-signed build too, just
retrieve the signing hash. The key hash of an already signed ap can be obtained
as follows (on macOS): ```keytool -list -printcert -jarfile the-app.apk```
- Place the generated ```google-services.json``` file in ```android/app```
for Android and the ```GoogleService-Info.plist``` into ```ios/app/src``` for
iOS (you can stop at that step, no need for the driver and the code changes they
suggest in the wizard).
- You may want to exclude these files in YOUR GIT config (do not exclude them in
the ```.gitignore``` of the application itself!).
- Your web client ID is auto generated during the Firebase project
creation. Find them in the Google Developer console
(https://console.developers.google.com/)
- Make sure your config reflects this ID by setting
```googleApiApplicationClientID``` in config.js.
- Add your iOS client ID (the REVERSED_CLIENT_ID in the plist file) as an
application URL schema into ```ios/app/src/Info.plist```
(replacing placeholder).
- Enable YouTube API access on the developer console (see above) to enable live
streaming.

View File

@@ -4,7 +4,13 @@ This document describes the required steps for a quick Jitsi Meet installation o
Debian Wheezy and other older systems may require additional things to be done. Specifically for Wheezy, [libc needs to be updated](http://lists.jitsi.org/pipermail/users/2015-September/010064.html).
N.B.: All commands are supposed to be run by root. If you are logged in as a regular user with sudo rights, please prepend ___sudo___ to each of the commands.
Also note that a recent default Ubuntu installation has only the `main` repository enabled, and Jitsi Meet needs packages from `universe`. Check your `/etc/apt/sources.list` file, and if `universe` is not present refer to [Ubuntu's documentation](https://help.ubuntu.com/community/Repositories/Ubuntu) on how to enable it. (Usually it amounts to copying the `main` lines and changing to `universe`.)
N.B.:
a.) All commands are supposed to be run by root. If you are logged in as a regular user with sudo rights, please prepend ___sudo___ to each of the commands.
b.) You only need to do this if you want to ___host your own Jitsi server___. If you just want to have a video conference with someone, use https://meet.jit.si instead.
## Basic Jitsi Meet install
@@ -59,6 +65,17 @@ org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS=<Public.IP.Address>
See [the documenation of ice4j](https://github.com/jitsi/ice4j/blob/master/doc/configuration.md)
for details.
Default deployments on systems using systemd will have low default values for maximum processes and open files. If the used bridge will expect higher number of participants the default values need to be adjusted (the default values are good for less than 100 participants).
To update the values edit `/etc/systemd/system.conf` and make sure you have the following values:
```
DefaultLimitNOFILE=65000
DefaultLimitNPROC=65000
DefaultTasksMax=65000
```
To load the values and check them look [here](#systemd-details) for details.
By default, anyone who has access to your jitsi instance will be able to start a conferencee: if your server is open to the world, anyone can have a chat with anyone else. If you want to limit the ability to start a conference to registered users, set up a "secure domain". Follow the instructions at https://github.com/jitsi/jicofo#secure-domain.
### Open a conference
Launch a web browser (Chrome, Chromium or latest Opera) and enter in the URL bar the hostname (or IP address) you used in the previous step.
@@ -103,3 +120,12 @@ Sometimes the following packages will fail to uninstall properly:
When this happens, just run the uninstall command a second time and it should be ok.
The reason for failure is that sometimes, the uninstall script is faster than the process that stops the daemons. The second run of the uninstall command fixes this, as by then the jigasi or jvb daemons are already stopped.
#### Systemd details
To reload the systemd changes on a running system execute `systemctl daemon-reload` and `service jitsi-videobridge restart`.
To check the tasks part execute `service jitsi-videobridge status` and you should see `Tasks: XX (limit: 65000)`.
To check the files and process part execute ```cat /proc/`cat /var/run/jitsi-videobridge.pid`/limits``` and you should see:
```
Max processes 65000 65000 processes
Max open files 65000 65000 files
```

Binary file not shown.

View File

@@ -72,4 +72,7 @@
<glyph unicode="&#xe92b;" glyph-name="rec" d="M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512c282.77 0 512-229.23 512-512s-229.23-512-512-512zM581.333 433.782h-110.595v59.233h104.338v40.332h-104.338v56.87h110.595v43.539h-161.665v-243.512h161.665v43.539zM738.771 384c58.849 0 101.802 36.282 106.029 88.933h-49.717c-4.904-26.832-26.888-44.045-56.143-44.045-38.556 0-62.4 31.895-62.4 83.196s23.844 83.027 62.231 83.027c29.086 0 51.239-18.394 56.143-46.407h49.717c-3.72 52.989-48.026 91.296-105.86 91.296-70.855 0-114.485-48.77-114.485-127.916 0-79.314 43.798-128.084 114.485-128.084zM230.27 478.502h41.769l45.489-88.258h57.834l-51.408 96.19c28.072 11.138 44.306 38.138 44.306 69.189 0 48.432-32.976 78.133-86.582 78.133h-102.478v-243.512h51.070v88.258zM230.27 592.58v-74.927h44.813c25.704 0 40.754 13.838 40.754 37.295 0 23.119-15.896 37.632-41.262 37.632h-44.306z" />
<glyph unicode="&#xe92c;" glyph-name="live" d="M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512c282.77 0 512-229.23 512-512s-229.23-512-512-512zM298.225 430.025h-112.35v206.5h-52.85v-252.525h165.2v46.025zM399.025 384v252.525h-52.85v-252.525h52.85zM591.525 384l84.175 252.525h-56.875l-56.35-193.025h-3.15l-57.4 193.025h-59.675l85.4-252.525h63.875zM886.050 429.15h-114.45v61.425h107.975v41.825h-107.975v58.975h114.45v45.15h-167.3v-252.525h167.3v45.15z" />
<glyph unicode="&#xe92d;" glyph-name="speaker" d="M0 512c0-282.795 229.205-512 512-512s512 229.205 512 512c0 282.795-229.205 512-512 512s-512-229.205-512-512zM525.005 759.362c-20.475 24.944-16.326 61.342 9.268 81.297s62.94 15.911 83.416-9.033c16.036-19.536 38.593-52.97 60.894-97.797 81.621-164.065 89.461-340.992-26.857-506.352-8.384-11.919-17.386-23.69-27.012-35.307-20.593-24.851-57.959-28.727-83.458-8.657s-29.476 56.487-8.882 81.338c7.686 9.275 14.833 18.621 21.455 28.035 88.66 126.041 82.71 260.306 17.953 390.475-10.599 21.305-21.94 40.51-33.198 57.196-6.515 9.657-11.322 16.057-13.578 18.805zM353.479 647.46c-19.353 24.679-15.129 60.448 9.434 79.893s60.164 15.2 79.517-9.479c9.635-12.287 22.577-32.644 35.209-60.034 50.35-109.176 50.35-231.689-33.639-349.612-18.198-25.551-53.566-31.441-78.997-13.157s-31.294 53.819-13.096 79.37c57.564 80.822 57.564 160.581 22.983 235.565-8.601 18.65-16.892 31.691-21.412 37.455z" />
<glyph unicode="&#xe92e;" glyph-name="tiles-many" d="M113.778 1024h227.556c62.838 0 113.778-50.94 113.778-113.778v-227.556c0-62.838-50.94-113.778-113.778-113.778h-227.556c-62.838 0-113.778 50.94-113.778 113.778v227.556c0 62.838 50.94 113.778 113.778 113.778zM170.667 910.222c-31.419 0-56.889-25.47-56.889-56.889v-113.778c0-31.419 25.47-56.889 56.889-56.889h113.778c31.419 0 56.889 25.47 56.889 56.889v113.778c0 31.419-25.47 56.889-56.889 56.889h-113.778zM113.778 455.111h227.556c62.838 0 113.778-50.94 113.778-113.778v-227.556c0-62.838-50.94-113.778-113.778-113.778h-227.556c-62.838 0-113.778 50.94-113.778 113.778v227.556c0 62.838 50.94 113.778 113.778 113.778zM170.667 341.333c-31.419 0-56.889-25.47-56.889-56.889v-113.778c0-31.419 25.47-56.889 56.889-56.889h113.778c31.419 0 56.889 25.47 56.889 56.889v113.778c0 31.419-25.47 56.889-56.889 56.889h-113.778zM682.667 1024h227.556c62.838 0 113.778-50.94 113.778-113.778v-227.556c0-62.838-50.94-113.778-113.778-113.778h-227.556c-62.838 0-113.778 50.94-113.778 113.778v227.556c0 62.838 50.94 113.778 113.778 113.778zM739.556 910.222c-31.419 0-56.889-25.47-56.889-56.889v-113.778c0-31.419 25.47-56.889 56.889-56.889h113.778c31.419 0 56.889 25.47 56.889 56.889v113.778c0 31.419-25.47 56.889-56.889 56.889h-113.778zM682.667 455.111h227.556c62.838 0 113.778-50.94 113.778-113.778v-227.556c0-62.838-50.94-113.778-113.778-113.778h-227.556c-62.838 0-113.778 50.94-113.778 113.778v227.556c0 62.838 50.94 113.778 113.778 113.778zM739.556 341.333c-31.419 0-56.889-25.47-56.889-56.889v-113.778c0-31.419 25.47-56.889 56.889-56.889h113.778c31.419 0 56.889 25.47 56.889 56.889v113.778c0 31.419-25.47 56.889-56.889 56.889h-113.778z" />
<glyph unicode="&#xe92f;" glyph-name="tiles-one" d="M170.667 810.667h682.667c47.128 0 85.333-38.205 85.333-85.333v-426.667c0-47.128-38.205-85.333-85.333-85.333h-682.667c-47.128 0-85.333 38.205-85.333 85.333v426.667c0 47.128 38.205 85.333 85.333 85.333zM213.333 725.333c-23.564 0-42.667-19.103-42.667-42.667v-341.333c0-23.564 19.103-42.667 42.667-42.667h597.333c23.564 0 42.667 19.103 42.667 42.667v341.333c0 23.564-19.103 42.667-42.667 42.667h-597.333z" />
<glyph unicode="&#xe930;" glyph-name="closed_caption" d="M768 554v44c0 24-18 42-42 42h-128c-24 0-44-18-44-42v-172c0-24 20-42 44-42h128c24 0 42 18 42 42v44h-64v-22h-86v128h86v-22h64zM470 554v44c0 24-20 42-44 42h-128c-24 0-42-18-42-42v-172c0-24 18-42 42-42h128c24 0 44 18 44 42v44h-64v-22h-86v128h86v-22h64zM810 854c46 0 86-40 86-86v-512c0-46-40-86-86-86h-596c-48 0-86 40-86 86v512c0 46 38 86 86 86h596z" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

42
images/dropboxLogo.svg Normal file
View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="324px" height="63.8px" viewBox="0 0 324 63.8" style="enable-background:new 0 0 324 63.8;" xml:space="preserve">
<style type="text/css">
.st0{fill:#0061FF;}
.st1{display:none;}
.st2{display:inline;}
.st3{fill:none;}
</style>
<path class="st0" d="M37.6,12L18.8,24l18.8,12L18.8,48L0,35.9l18.8-12L0,12L18.8,0L37.6,12z M18.7,51.8l18.8-12l18.8,12l-18.8,12
L18.7,51.8z M37.6,35.9l18.8-12L37.6,12L56.3,0l18.8,12L56.3,24l18.8,12L56.3,48L37.6,35.9z"/>
<path d="M89.8,12H105c9.7,0,17.7,5.6,17.7,18.4v2.7c0,12.9-7.5,18.7-17.4,18.7H89.8V12z M98.3,19.2v25.3h6.5c5.5,0,9.2-3.6,9.2-11.6
v-2.1c0-8-3.9-11.6-9.5-11.6H98.3z M127.2,19.6h6.8l1.1,7.5c1.3-5.1,4.6-7.8,10.6-7.8h2.1v8.6h-3.5c-6.9,0-8.6,2.4-8.6,9.2v14.8
h-8.4V19.6H127.2z M149.5,36.4v-0.9c0-10.8,6.9-16.7,16.3-16.7c9.6,0,16.3,5.9,16.3,16.7v0.9c0,10.6-6.5,16.3-16.3,16.3
C155.4,52.6,149.5,47,149.5,36.4z M173.5,36.3v-0.8c0-6-3-9.6-7.8-9.6c-4.7,0-7.8,3.3-7.8,9.6v0.8c0,5.8,3,9.1,7.8,9.1
C170.5,45.3,173.5,42.1,173.5,36.3z M186.5,19.6h7l0.8,6.1c1.7-4.1,5.3-6.9,10.6-6.9c8.2,0,13.6,5.9,13.6,16.8v0.9
c0,10.6-6,16.2-13.6,16.2c-5.1,0-8.6-2.3-10.3-6V63h-8.2L186.5,19.6L186.5,19.6z M210,36.3v-0.7c0-6.4-3.3-9.6-7.7-9.6
c-4.7,0-7.8,3.6-7.8,9.6v0.6c0,5.7,3,9.3,7.7,9.3C207,45.4,210,42.3,210,36.3z M230.9,45.9l-0.7,5.9H223v-43h8.2v16.5
c1.8-4.2,5.4-6.5,10.5-6.5c7.7,0.1,13.4,5.4,13.4,16.1v1c0,10.7-5.4,16.8-13.6,16.8C236.1,52.6,232.6,50.1,230.9,45.9z M246.5,35.9
v-0.8c0-5.9-3.2-9.2-7.7-9.2c-4.6,0-7.8,3.7-7.8,9.3v0.7c0,6,3.1,9.5,7.7,9.5C243.6,45.4,246.5,42.3,246.5,35.9z M258.7,36.4v-0.9
c0-10.8,6.9-16.7,16.3-16.7c9.6,0,16.3,5.9,16.3,16.7v0.9c0,10.6-6.6,16.3-16.3,16.3C264.6,52.6,258.7,47,258.7,36.4z M282.8,36.3
v-0.8c0-6-3-9.6-7.8-9.6c-4.7,0-7.8,3.3-7.8,9.6v0.8c0,5.8,3,9.1,7.8,9.1C279.8,45.3,282.8,42.1,282.8,36.3z M302.3,35.1L291,19.6
h9.7l6.5,9.7l6.6-9.7h9.6L311.9,35L324,51.8h-9.5l-7.4-10.7l-7.2,10.7H290L302.3,35.1z"/>
<g id="Editble" class="st1">
<g class="st2">
<rect x="-105" y="5" class="st3" width="506" height="71.8"/>
<path d="M0.2,13.6h16.3c10.4,0,19,6.1,19,19.8v2.9c0,13.8-8,20-18.7,20H0.2V13.6z M9.4,21.3v27.2h7c5.9,0,9.9-3.9,9.9-12.5v-2.2
c0-8.6-4.1-12.5-10.2-12.5H9.4z M40.4,21.8h7.3l1.1,8c1.4-5.5,4.9-8.3,11.3-8.3h2.2v9.2h-3.7c-7.4,0-9.2,2.6-9.2,9.9v15.8h-9
C40.4,56.4,40.4,21.8,40.4,21.8z M64.3,39.8v-1c0-11.6,7.4-17.9,17.5-17.9c10.3,0,17.5,6.4,17.5,17.9v1c0,11.4-7,17.5-17.5,17.5
C70.6,57.3,64.3,51.2,64.3,39.8z M90.1,39.7v-0.8c0-6.5-3.2-10.3-8.3-10.3c-5,0-8.4,3.5-8.4,10.3v0.8c0,6.2,3.2,9.7,8.3,9.7
C86.9,49.4,90.1,46,90.1,39.7z M104,21.8h7.6l0.9,6.6c1.9-4.4,5.7-7.4,11.4-7.4c8.8,0,14.6,6.4,14.6,18v1
c0,11.4-6.4,17.3-14.6,17.3c-5.5,0-9.2-2.5-11-6.5v17.5H104V21.8z M129.3,39.8V39c0-6.9-3.5-10.3-8.3-10.3c-5,0-8.4,3.8-8.4,10.3
v0.7c0,6.1,3.2,10,8.2,10C126,49.5,129.3,46.1,129.3,39.8z M151.7,50.1l-0.7,6.3h-7.8V10.2h8.8V28c1.9-4.5,5.8-7,11.2-7
c8.2,0.1,14.3,5.8,14.3,17.3v1c0,11.5-5.8,18-14.6,18C157.3,57.3,153.5,54.5,151.7,50.1z M168.5,39.3v-0.8c0-6.4-3.5-9.8-8.3-9.8
c-5,0-8.4,4-8.4,10v0.7c0,6.5,3.3,10.2,8.3,10.2C165.3,49.5,168.5,46.1,168.5,39.3z M181.6,39.8v-1c0-11.6,7.4-17.9,17.5-17.9
c10.3,0,17.5,6.4,17.5,17.9v1c0,11.4-7.1,17.5-17.5,17.5C187.9,57.3,181.6,51.2,181.6,39.8z M207.4,39.7v-0.8
c0-6.5-3.2-10.3-8.3-10.3c-5,0-8.4,3.5-8.4,10.3v0.8c0,6.2,3.2,9.7,8.3,9.7C204.2,49.4,207.4,46,207.4,39.7z M228.3,38.4
l-12.1-16.7h10.4l7,10.4l7.1-10.4H251l-12.3,16.6l13,18h-10.2l-8-11.5l-7.7,11.5h-10.6L228.3,38.4z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 889 B

1
images/microsoftLogo.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="21" height="21" viewBox="0 0 21 21"><title>MS-SymbolLockup</title><rect x="1" y="1" width="9" height="9" fill="#f25022"/><rect x="1" y="11" width="9" height="9" fill="#00a4ef"/><rect x="11" y="1" width="9" height="9" fill="#7fba00"/><rect x="11" y="11" width="9" height="9" fill="#ffb900"/></svg>

After

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

View File

@@ -1,26 +1,2 @@
// The type field of react-native application loader's React Element is created
// as number and not Symbol, because it's not been defined by the polyfill yet.
// We import the application renderer, before Symbol is defined, in order to use
// number types as well. Otherwise this will result in the invariant exception,
// because fiber thingy will not recognise root react-native component as React
// Element, but as an Object.
//
// See node_modules/react-native/Libraries/polyfills/babelHelpers.js
// :babelHelpers.createRawReactElement - that's where first react-native element
// is created (super early - it's the app loader).
//
// See node_modules/react-native/Libraries/Renderer/ReactNativeFiber-dev.js
// and look for REACT_ELEMENT_TYPE definition - it's defined later when Symbol
// has been defined and type will not match.
//
// As an alternative solution we could stop using/polyfilling Symbols and
// replace with classpath string constants or some kind of a wrapper around
// that.
import 'react-native/Libraries/ReactNative/renderApplication';
// Android doesn't provide Symbol
import 'es6-symbol/implement';
import './react/index.native';

View File

@@ -45,13 +45,14 @@ var interfaceConfig = {
* jwt.
*/
TOOLBAR_BUTTONS: [
'microphone', 'camera', 'desktop', 'fullscreen', 'fodeviceselection', 'hangup',
'profile', 'info', 'chat', 'recording', 'livestreaming', 'etherpad',
'sharedvideo', 'settings', 'raisehand', 'videoquality', 'filmstrip',
'invite', 'feedback', 'stats', 'shortcuts'
'microphone', 'camera', 'closedcaptions', 'desktop', 'fullscreen',
'fodeviceselection', 'hangup', 'profile', 'info', 'chat', 'recording',
'livestreaming', 'etherpad', 'sharedvideo', 'settings', 'raisehand',
'videoquality', 'filmstrip', 'invite', 'feedback', 'stats', 'shortcuts',
'tileview'
],
SETTINGS_SECTIONS: [ 'devices', 'language', 'moderator', 'profile' ],
SETTINGS_SECTIONS: [ 'devices', 'language', 'moderator', 'profile', 'calendar' ],
// 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
@@ -163,7 +164,20 @@ var interfaceConfig = {
*
* @type {boolean}
*/
VIDEO_QUALITY_LABEL_DISABLED: false
VIDEO_QUALITY_LABEL_DISABLED: false,
/**
* If true, will display recent list
*
* @type {boolean}
*/
RECENT_LIST_ENABLED: true
/**
* How many columns the tile view can expand to. The respected range is
* between 1 and 5.
*/
// TILE_VIEW_MAX_COLUMNS: 5,
/**
* Specify custom URL for downloading android mobile app.

View File

@@ -26,17 +26,19 @@ target 'JitsiMeet' do
pod 'Folly',
:podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
pod 'ObjectiveDropboxOfficial'
pod 'react-native-background-timer',
:path => '../node_modules/react-native-background-timer'
pod 'react-native-fetch-blob',
:path => '../node_modules/react-native-fetch-blob'
pod 'react-native-fast-image',
:path => '../node_modules/react-native-fast-image'
pod 'react-native-keep-awake',
:path => '../node_modules/react-native-keep-awake'
pod 'react-native-locale-detector',
:path => '../node_modules/react-native-locale-detector'
pod 'react-native-webrtc', :path => '../node_modules/react-native-webrtc'
pod 'ReactNativePermissions',
:path => '../node_modules/react-native-permissions'
pod 'RNGoogleSignin',
:path => '../node_modules/react-native-google-signin'
pod 'RNSound', :path => '../node_modules/react-native-sound'
pod 'RNVectorIcons', :path => '../node_modules/react-native-vector-icons'
pod 'react-native-calendar-events',

View File

@@ -1,82 +1,113 @@
PODS:
- boost-for-react-native (1.63.0)
- DoubleConversion (1.1.5)
- Folly (2016.09.26.00):
- DoubleConversion (1.1.6)
- FLAnimatedImage (1.0.12)
- Folly (2016.10.31.00):
- boost-for-react-native
- DoubleConversion
- glog
- glog (0.3.4)
- React (0.55.4):
- React/Core (= 0.55.4)
- glog (0.3.5)
- GoogleSignIn (4.3.0):
- "GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)"
- "GoogleToolboxForMac/NSString+URLArguments (~> 2.1)"
- GTMOAuth2 (~> 1.0)
- GTMSessionFetcher/Core (~> 1.1)
- GoogleToolboxForMac/DebugUtils (2.1.4):
- GoogleToolboxForMac/Defines (= 2.1.4)
- GoogleToolboxForMac/Defines (2.1.4)
- "GoogleToolboxForMac/NSDictionary+URLArguments (2.1.4)":
- GoogleToolboxForMac/DebugUtils (= 2.1.4)
- GoogleToolboxForMac/Defines (= 2.1.4)
- "GoogleToolboxForMac/NSString+URLArguments (= 2.1.4)"
- "GoogleToolboxForMac/NSString+URLArguments (2.1.4)"
- GTMOAuth2 (1.1.6):
- GTMSessionFetcher (~> 1.1)
- GTMSessionFetcher (1.2.0):
- GTMSessionFetcher/Full (= 1.2.0)
- GTMSessionFetcher/Core (1.2.0)
- GTMSessionFetcher/Full (1.2.0):
- GTMSessionFetcher/Core (= 1.2.0)
- ObjectiveDropboxOfficial (3.9.2)
- React (0.57.1):
- React/Core (= 0.57.1)
- react-native-background-timer (2.0.0):
- React
- react-native-calendar-events (1.6.0):
- react-native-calendar-events (1.6.2):
- React
- react-native-fetch-blob (0.10.6):
- React/Core
- react-native-fast-image (4.0.14):
- FLAnimatedImage
- React
- SDWebImage/Core
- SDWebImage/GIF
- react-native-keep-awake (2.0.6):
- React
- react-native-locale-detector (1.0.0):
- React
- react-native-webrtc (1.58.2):
- react-native-webrtc (1.67.1):
- React
- React/Core (0.55.4):
- yoga (= 0.55.4.React)
- React/CxxBridge (0.55.4):
- Folly (= 2016.09.26.00)
- React/Core (0.57.1):
- yoga (= 0.57.1.React)
- React/CxxBridge (0.57.1):
- Folly (= 2016.10.31.00)
- React/Core
- React/cxxreact
- React/cxxreact (0.55.4):
- React/cxxreact (0.57.1):
- boost-for-react-native (= 1.63.0)
- Folly (= 2016.09.26.00)
- Folly (= 2016.10.31.00)
- React/jschelpers
- React/jsinspector
- React/DevSupport (0.55.4):
- React/DevSupport (0.57.1):
- React/Core
- React/RCTWebSocket
- React/fishhook (0.55.4)
- React/jschelpers (0.55.4):
- Folly (= 2016.09.26.00)
- React/fishhook (0.57.1)
- React/jschelpers (0.57.1):
- Folly (= 2016.10.31.00)
- React/PrivateDatabase
- React/jsinspector (0.55.4)
- React/PrivateDatabase (0.55.4)
- React/RCTActionSheet (0.55.4):
- React/jsinspector (0.57.1)
- React/PrivateDatabase (0.57.1)
- React/RCTActionSheet (0.57.1):
- React/Core
- React/RCTAnimation (0.55.4):
- React/RCTAnimation (0.57.1):
- React/Core
- React/RCTBlob (0.55.4):
- React/RCTBlob (0.57.1):
- React/Core
- React/RCTImage (0.55.4):
- React/RCTImage (0.57.1):
- React/Core
- React/RCTNetwork
- React/RCTLinkingIOS (0.55.4):
- React/RCTLinkingIOS (0.57.1):
- React/Core
- React/RCTNetwork (0.55.4):
- React/RCTNetwork (0.57.1):
- React/Core
- React/RCTText (0.55.4):
- React/RCTText (0.57.1):
- React/Core
- React/RCTWebSocket (0.55.4):
- React/RCTWebSocket (0.57.1):
- React/Core
- React/fishhook
- React/RCTBlob
- ReactNativePermissions (1.1.1):
- RNGoogleSignin (1.0.0-rc6):
- GoogleSignIn
- React
- RNSound (0.10.9):
- React/Core
- RNSound/Core (= 0.10.9)
- RNSound/Core (0.10.9):
- React/Core
- RNVectorIcons (4.4.2):
- RNVectorIcons (6.0.2):
- React
- yoga (0.55.4.React)
- SDWebImage/Core (4.4.2)
- SDWebImage/GIF (4.4.2):
- FLAnimatedImage (~> 1.0)
- SDWebImage/Core
- yoga (0.57.1.React)
DEPENDENCIES:
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- ObjectiveDropboxOfficial
- react-native-background-timer (from `../node_modules/react-native-background-timer`)
- react-native-calendar-events (from `../node_modules/react-native-calendar-events`)
- react-native-fetch-blob (from `../node_modules/react-native-fetch-blob`)
- react-native-fast-image (from `../node_modules/react-native-fast-image`)
- react-native-keep-awake (from `../node_modules/react-native-keep-awake`)
- react-native-locale-detector (from `../node_modules/react-native-locale-detector`)
- react-native-webrtc (from `../node_modules/react-native-webrtc`)
@@ -90,7 +121,7 @@ DEPENDENCIES:
- React/RCTNetwork (from `../node_modules/react-native`)
- React/RCTText (from `../node_modules/react-native`)
- React/RCTWebSocket (from `../node_modules/react-native`)
- ReactNativePermissions (from `../node_modules/react-native-permissions`)
- RNGoogleSignin (from `../node_modules/react-native-google-signin`)
- RNSound (from `../node_modules/react-native-sound`)
- RNVectorIcons (from `../node_modules/react-native-vector-icons`)
- yoga (from `../node_modules/react-native/ReactCommon/yoga`)
@@ -98,6 +129,13 @@ DEPENDENCIES:
SPEC REPOS:
https://github.com/cocoapods/specs.git:
- boost-for-react-native
- FLAnimatedImage
- GoogleSignIn
- GoogleToolboxForMac
- GTMOAuth2
- GTMSessionFetcher
- ObjectiveDropboxOfficial
- SDWebImage
EXTERNAL SOURCES:
DoubleConversion:
@@ -112,16 +150,16 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-background-timer"
react-native-calendar-events:
:path: "../node_modules/react-native-calendar-events"
react-native-fetch-blob:
:path: "../node_modules/react-native-fetch-blob"
react-native-fast-image:
:path: "../node_modules/react-native-fast-image"
react-native-keep-awake:
:path: "../node_modules/react-native-keep-awake"
react-native-locale-detector:
:path: "../node_modules/react-native-locale-detector"
react-native-webrtc:
:path: "../node_modules/react-native-webrtc"
ReactNativePermissions:
:path: "../node_modules/react-native-permissions"
RNGoogleSignin:
:path: "../node_modules/react-native-google-signin"
RNSound:
:path: "../node_modules/react-native-sound"
RNVectorIcons:
@@ -131,21 +169,28 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
DoubleConversion: e22e0762848812a87afd67ffda3998d9ef29170c
Folly: 211775e49d8da0ca658aebc8eab89d642935755c
glog: 1de0bb937dccdc981596d3b5825ebfb765017ded
React: aa2040dbb6f317b95314968021bd2888816e03d5
DoubleConversion: bb338842f62ab1d708ceb63ec3d999f0f3d98ecd
FLAnimatedImage: 4a0b56255d9b05f18b6dd7ee06871be5d3b89e31
Folly: c89ac2d5c6ab169cd7397ef27485c44f35f742c7
glog: e8acf0ebbf99759d3ff18c86c292a5898282dcde
GoogleSignIn: 11183592dc63e105475c7305a325045ff95e02b7
GoogleToolboxForMac: 91c824d21e85b31c2aae9bb011c5027c9b4e738f
GTMOAuth2: c77fe325e4acd453837e72d91e3b5f13116857b2
GTMSessionFetcher: 0c4baf0a73acd0041bf9f71ea018deedab5ea84e
ObjectiveDropboxOfficial: aa792e0556ceb7b72955fa29a2709072f6e35fd9
React: 1fe0eb13d90b625d94c3b117c274dcfd2e760e11
react-native-background-timer: 63dcbf37dbcf294b5c6c071afcdc661fa06a7594
react-native-calendar-events: fe6fbc8ed337a7423c98f2c9012b25f20444de09
react-native-fetch-blob: 63394b1d7b0781547b3e4463b3195790177b1222
react-native-fast-image: cba3d9bf9c2cf8ddb643d887a686c53a5dd90a2c
react-native-keep-awake: 0de4bd66de0c23178107dce0c2fcc3354b2a8e94
react-native-locale-detector: d1b2c6fe5abb56e3a1efb6c2d6f308c05c4251f1
react-native-webrtc: 31b6d3f1e3e2ce373aa43fd682b04367250f807d
ReactNativePermissions: 9f2d9c45c98800795e6c2ed330e25d11a66a8169
RNGoogleSignin: 44debd8c359a662c0e2d585952e88b985bf78008
RNSound: b360b3862d3118ed1c74bb9825696b5957686ac4
RNVectorIcons: c0dbfbf6068fefa240c37b0f71bd03b45dddac44
yoga: a23273df0088bf7f2bb7e5d7b00044ea57a2a54a
RNVectorIcons: 8c52e1e8da1153613fdef44748e865c25556cb9c
SDWebImage: 624d6e296c69b244bcede364c72ae0430ac14681
yoga: b1ce48b6cf950b98deae82838f5173ea7cf89e85
PODFILE CHECKSUM: e24d0131e937934fbe4d1f0b7ad5947ee0192f58
PODFILE CHECKSUM: cf8276ba4b0933b24c6082a25a5f4eabe0ba4ea6
COCOAPODS: 1.5.3

View File

@@ -125,7 +125,23 @@ continueUserActivity:(NSUserActivity *)userActivity
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}
```
And also one of the following:
```objc
// See https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623073-application?language=objc
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
return [JitsiMeetView application:app
openURL:url
options: options];
}
```
or
```objc
// See https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623112-application?language=objc
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
@@ -138,6 +154,8 @@ continueUserActivity:(NSUserActivity *)userActivity
}
```
NOTE: The latter is deprecated.
### JitsiMeetViewDelegate
This delegate is optional, and can be set on the `JitsiMeetView` instance using
@@ -212,3 +230,39 @@ resize `JitsiMeetView`.
If `pictureInPictureEnabled` is set to `YES` or `delegate` implements
`enterPictureInPicture:`, the in-call toolbar will render a button to afford the
user to request entering Picture-in-Picture.
## Dropbox integration
To setup the Dropbox integration, follow these steps:
1. Add the following to the app's Info.plist and change `<APP_KEY>` to your
Dropbox app key:
```
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string></string>
<key>CFBundleURLSchemes</key>
<array>
<string>db-<APP_KEY></string>
</array>
</dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>dbapi-2</string>
<string>dbapi-8-emm</string>
</array>
```
2. Add the following to the app's `AppDelegate`:
```objc
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
return [JitsiMeetView application:app
openURL:url
options:options];
}
```

View File

@@ -138,7 +138,7 @@
83CBB9F71A601CBA00E9B192 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0920;
LastUpgradeCheck = 1000;
ORGANIZATIONNAME = Facebook;
TargetAttributes = {
13B07F861A680F5B00A75B9A = {
@@ -327,12 +327,14 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -383,12 +385,14 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0920"
LastUpgradeVersion = "1000"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
@@ -40,7 +40,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
@@ -60,7 +59,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"

View File

@@ -36,14 +36,13 @@
restorationHandler:restorationHandler];
}
- (BOOL)application:(UIApplication *)application
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
return [JitsiMeetView application:application
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
return [JitsiMeetView application:app
openURL:url
sourceApplication:sourceApplication
annotation:annotation];
options:options];
}
@end

View File

@@ -32,6 +32,16 @@
<string>org.jitsi.meet</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>com.googleusercontent.apps</string>
<key>CFBundleURLSchemes</key>
<array>
<string>com.googleusercontent.apps.YOUR_ID_HERE</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>1</string>

View File

@@ -3,14 +3,17 @@
# This script is executed from Xcode to start the React packager for Debug
# targets.
export RCT_METRO_PORT="${RCT_METRO_PORT:=8081}"
echo "export RCT_METRO_PORT=${RCT_METRO_PORT}" > "${SRCROOT}/../../node_modules/react-native/scripts/.packager.env"
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"
if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then
if ! curl -s "http://localhost:${RCT_METRO_PORT}/status" | grep -q "packager-status:running" ; then
echo "Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly"
exit 2
fi
else
open -g "$SRCROOT/../../node_modules/react-native/scripts/launchPackager.command" || echo "Can't start packager automatically"
fi
fi

View File

@@ -14,7 +14,6 @@
0B49424520AD8DBD00BD2DE0 /* outgoingStart.wav in Resources */ = {isa = PBXBuildFile; fileRef = 0B49424320AD8DBD00BD2DE0 /* outgoingStart.wav */; };
0B49424620AD8DBD00BD2DE0 /* outgoingRinging.wav in Resources */ = {isa = PBXBuildFile; fileRef = 0B49424420AD8DBD00BD2DE0 /* outgoingRinging.wav */; };
0B7C2CFD200F51D60060D076 /* LaunchOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B7C2CFC200F51D60060D076 /* LaunchOptions.m */; };
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 */; };
@@ -34,6 +33,7 @@
75635B0A20751D6D00F29C9F /* joined.wav in Resources */ = {isa = PBXBuildFile; fileRef = 75635B0820751D6D00F29C9F /* joined.wav */; };
75635B0B20751D6D00F29C9F /* left.wav in Resources */ = {isa = PBXBuildFile; fileRef = 75635B0920751D6D00F29C9F /* left.wav */; };
A4414AE020B37F1A003546E6 /* rejected.wav in Resources */ = {isa = PBXBuildFile; fileRef = A4414ADF20B37F1A003546E6 /* rejected.wav */; };
A4A934E9212F3ADB001E9388 /* Dropbox.m in Sources */ = {isa = PBXBuildFile; fileRef = A4A934E8212F3ADB001E9388 /* Dropbox.m */; };
B386B85720981A75000DEF7A /* InviteController.m in Sources */ = {isa = PBXBuildFile; fileRef = B386B85020981A74000DEF7A /* InviteController.m */; };
B386B85820981A75000DEF7A /* AddPeopleController.m in Sources */ = {isa = PBXBuildFile; fileRef = B386B85120981A74000DEF7A /* AddPeopleController.m */; };
B386B85920981A75000DEF7A /* AddPeopleControllerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = B386B85220981A74000DEF7A /* AddPeopleControllerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -87,6 +87,8 @@
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>"; };
A4414ADF20B37F1A003546E6 /* rejected.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = rejected.wav; path = ../../sounds/rejected.wav; sourceTree = "<group>"; };
A4A934E8212F3ADB001E9388 /* Dropbox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Dropbox.m; sourceTree = "<group>"; };
A4A934EB21349A06001E9388 /* Dropbox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Dropbox.h; sourceTree = "<group>"; };
B386B85020981A74000DEF7A /* InviteController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InviteController.m; sourceTree = "<group>"; };
B386B85120981A74000DEF7A /* AddPeopleController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AddPeopleController.m; sourceTree = "<group>"; };
B386B85220981A74000DEF7A /* AddPeopleControllerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddPeopleControllerDelegate.h; sourceTree = "<group>"; };
@@ -111,7 +113,6 @@
files = (
0BB9AD791F5EC6D7001C08DB /* Intents.framework in Frameworks */,
0BB9AD771F5EC6CE001C08DB /* CallKit.framework in Frameworks */,
0B93EF7B1EC608550030D24D /* CoreText.framework in Frameworks */,
0F65EECE1D95DA94561BB47E /* libPods-JitsiMeet.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -122,9 +123,6 @@
0BCA49681EC4BBE500B793EE /* Resources */ = {
isa = PBXGroup;
children = (
6C31EDC720C06D490089C899 /* recordingOn.mp3 */,
6C31EDC920C06D530089C899 /* recordingOff.mp3 */,
A4414ADF20B37F1A003546E6 /* rejected.wav */,
0BC4B8681F8C01E100CE8B21 /* CallKitIcon.png */,
C6245F5B2053091D0040BE68 /* image-resize@2x.png */,
C6245F5C2053091D0040BE68 /* image-resize@3x.png */,
@@ -133,6 +131,9 @@
75635B0920751D6D00F29C9F /* left.wav */,
0B49424420AD8DBD00BD2DE0 /* outgoingRinging.wav */,
0B49424320AD8DBD00BD2DE0 /* outgoingStart.wav */,
6C31EDC920C06D530089C899 /* recordingOff.mp3 */,
6C31EDC720C06D490089C899 /* recordingOn.mp3 */,
A4414ADF20B37F1A003546E6 /* rejected.wav */,
);
name = Resources;
sourceTree = "<group>";
@@ -162,6 +163,7 @@
0BB9AD7C1F60356D001C08DB /* AppInfo.m */,
0BCA495C1EC4B6C600B793EE /* AudioMode.m */,
C69EFA02209A0EFD0027712B /* callkit */,
A4A934E7212F3AB8001E9388 /* dropbox */,
0BA13D301EE83FF8007BEF7F /* ExternalAPI.m */,
0BD906E91EC0C00300C8C18E /* Info.plist */,
B386B84F20981A11000DEF7A /* invite */,
@@ -193,6 +195,15 @@
name = Frameworks;
sourceTree = "<group>";
};
A4A934E7212F3AB8001E9388 /* dropbox */ = {
isa = PBXGroup;
children = (
A4A934EB21349A06001E9388 /* Dropbox.h */,
A4A934E8212F3ADB001E9388 /* Dropbox.m */,
);
path = dropbox;
sourceTree = "<group>";
};
B386B84F20981A11000DEF7A /* invite */ = {
isa = PBXGroup;
children = (
@@ -272,6 +283,7 @@
0BD906E31EC0C00300C8C18E /* Resources */,
0BCA49651EC4B77500B793EE /* Package React bundle */,
C7BC10B338C94EEB98048E64 /* [CP] Copy Pods Resources */,
0B64F7BE2175DFEA005009CD /* Remove unneeded fonts */,
);
buildRules = (
);
@@ -288,7 +300,7 @@
0BD906DC1EC0C00300C8C18E /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0920;
LastUpgradeCheck = 1000;
ORGANIZATIONNAME = Jitsi;
TargetAttributes = {
0BD906E41EC0C00300C8C18E = {
@@ -337,6 +349,24 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
0B64F7BE2175DFEA005009CD /* Remove unneeded fonts */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "Remove unneeded fonts";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# We need to manually do this because react-native-vecotr-icons lists fonts as resources in the Pod spec file\n# so they are automatically added.\n\nshopt -s extglob\n\nrm -f ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/!(jitsi).ttf\n";
};
0BCA49651EC4B77500B793EE /* Package React bundle */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -376,10 +406,16 @@
);
inputPaths = (
"${SRCROOT}/../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet-resources.sh",
"${PODS_ROOT}/GTMOAuth2/Source/Touch/GTMOAuth2ViewTouch.xib",
"${PODS_ROOT}/GoogleSignIn/Resources/GoogleSignIn.bundle",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Feather.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Regular.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Foundation.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf",
@@ -390,10 +426,16 @@
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GTMOAuth2ViewTouch.nib",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleSignIn.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AntDesign.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Entypo.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EvilIcons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Feather.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Brands.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Regular.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Solid.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Foundation.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Ionicons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialCommunityIcons.ttf",
@@ -429,6 +471,7 @@
0BCA49611EC4B6C600B793EE /* Proximity.m in Sources */,
C69EFA0C209A0F660027712B /* JMCallKitEmitter.swift in Sources */,
C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */,
A4A934E9212F3ADB001E9388 /* Dropbox.m in Sources */,
C69EFA0D209A0F660027712B /* JMCallKitProxy.swift in Sources */,
C69EFA0E209A0F660027712B /* JMCallKitListener.swift in Sources */,
0B412F191EDEC65D00B1A0A6 /* JitsiMeetView.m in Sources */,
@@ -452,6 +495,7 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
@@ -459,6 +503,7 @@
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -511,6 +556,7 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
@@ -518,6 +564,7 @@
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -543,6 +590,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0920"
LastUpgradeVersion = "1000"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
@@ -26,7 +26,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
@@ -37,7 +36,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"

View File

@@ -20,6 +20,9 @@
#import <React/RCTLog.h>
@interface AudioMode : NSObject<RCTBridgeModule>
@property(nonatomic, strong) dispatch_queue_t workerQueue;
@end
@implementation AudioMode {
@@ -52,15 +55,18 @@ typedef enum {
if (self) {
_category = nil;
_mode = nil;
dispatch_queue_attr_t attributes =
dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL,
QOS_CLASS_USER_INITIATED, -1);
_workerQueue = dispatch_queue_create("WebRTCModule.queue", attributes);
}
return self;
}
- (dispatch_queue_t)methodQueue {
// Make sure all our methods run in the main thread. The route change
// notification runs there so this will make sure it will only be fired
// after our changes have been applied (when we cause them, that is).
return dispatch_get_main_queue();
// Use a dedicated queue for audio mode operations.
return _workerQueue;
}
- (void)routeChanged:(NSNotification*)notification {
@@ -70,12 +76,15 @@ typedef enum {
integerValue];
switch (reason) {
case AVAudioSessionRouteChangeReasonCategoryChange:
case AVAudioSessionRouteChangeReasonCategoryChange: {
// The category has changed. Check if it's the one we want and adjust as
// needed.
[self setCategory:_category mode:_mode error:nil];
// needed. This notification is posted on a secondary thread, so make
// sure we switch to our worker thread.
dispatch_async(_workerQueue, ^{
[self setCategory:_category mode:_mode error:nil];
});
break;
}
default:
// Do nothing.
break;

View File

@@ -18,12 +18,12 @@
<string>1.9.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>dbapi-2</string>
<string>dbapi-8-emm</string>
</array>
<key>NSPrincipalClass</key>
<string></string>
<key>JitsiMeetFonts</key>
<array>
<string>FontAwesome.ttf</string>
<string>jitsi.ttf</string>
</array>
</dict>
</plist>

View File

@@ -39,10 +39,14 @@
continueUserActivity:(NSUserActivity * _Nonnull)userActivity
restorationHandler:(void (^ _Nullable)(NSArray * _Nullable))restorationHandler;
+ (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options;
+ (BOOL)application:(UIApplication * _Nonnull)application
openURL:(NSURL * _Nonnull)URL
sourceApplication:(NSString * _Nullable)sourceApplication
annotation:(id _Nullable)annotation;
annotation:(id _Nullable)annotation __deprecated;
- (void)loadURL:(NSURL * _Nullable)url;

View File

@@ -14,7 +14,6 @@
* limitations under the License.
*/
#import <CoreText/CoreText.h>
#import <Intents/Intents.h>
#include <mach/mach_time.h>
@@ -23,6 +22,7 @@
#import <React/RCTLinkingManager.h>
#import <React/RCTRootView.h>
#import "Dropbox.h"
#import "Invite+Private.h"
#import "InviteController+Private.h"
#import "JitsiMeetView+Private.h"
@@ -52,35 +52,6 @@ RCTFatalHandler _RCTFatal = ^(NSError *error) {
}
};
/**
* Helper function to dynamically load custom fonts. The `UIAppFonts` key in the
* plist file doesn't work for frameworks, so fonts have to be manually loaded.
*/
void loadCustomFonts(Class clazz) {
NSBundle *bundle = [NSBundle bundleForClass:clazz];
NSArray *fonts = [bundle objectForInfoDictionaryKey:@"JitsiMeetFonts"];
for (NSString *item in fonts) {
NSString *fontName = [item stringByDeletingPathExtension];
NSString *fontExt = [item pathExtension];
NSString *fontPath = [bundle pathForResource:fontName ofType:fontExt];
NSData *inData = [NSData dataWithContentsOfFile:fontPath];
CFErrorRef error;
CGDataProviderRef provider
= CGDataProviderCreateWithCFData((__bridge CFDataRef)inData);
CGFontRef font = CGFontCreateWithDataProvider(provider);
if (!CTFontManagerRegisterGraphicsFont(font, &error)) {
CFStringRef errorDescription = CFErrorCopyDescription(error);
NSLog(@"Failed to load font: %@", errorDescription);
CFRelease(errorDescription);
}
CFRelease(font);
CFRelease(provider);
}
}
/**
* Helper function to register a fatal error handler for React. Our handler
* won't kill the process, it will swallow JS errors and print stack traces
@@ -137,6 +108,8 @@ static NSMapTable<NSString *, JitsiMeetView *> *views;
// Store launch options, will be used when we create the bridge.
_launchOptions = [launchOptions copy];
[Dropbox setAppKey];
return YES;
}
@@ -192,10 +165,13 @@ static NSMapTable<NSString *, JitsiMeetView *> *views;
restorationHandler:restorationHandler];
}
+ (BOOL)application:(UIApplication *)application
+ (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
if ([Dropbox application:app openURL:url options:options]) {
return YES;
}
// XXX At least twice we received bug reports about malfunctioning loadURL
// in the Jitsi Meet SDK while the Jitsi Meet app seemed to functioning as
// expected in our testing. But that was to be expected because the app does
@@ -205,10 +181,14 @@ static NSMapTable<NSString *, JitsiMeetView *> *views;
return YES;
}
return [RCTLinkingManager application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation];
return [RCTLinkingManager application:app openURL:url options:options];
}
+ (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
return [self application:application openURL:url options:@{}];
}
#pragma mark Initializers
@@ -400,9 +380,6 @@ static NSMapTable<NSString *, JitsiMeetView *> *views;
= [[RCTBridgeWrapper alloc] initWithLaunchOptions:_launchOptions];
views = [NSMapTable strongToWeakObjectsMapTable];
// Dynamically load custom bundled fonts.
loadCustomFonts(self.class);
// Register a fatal error handler for React.
registerFatalErrorHandler();
});

View File

@@ -0,0 +1,27 @@
/*
* Copyright @ 2018-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 <React/RCTBridge.h>
@interface Dropbox : NSObject<RCTBridgeModule>
+ (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options;
+ (void)setAppKey;
@end

View File

@@ -0,0 +1,173 @@
/*
* 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 <React/RCTBridgeModule.h>
#import <ObjectiveDropboxOfficial/ObjectiveDropboxOfficial.h>
#import "Dropbox.h"
RCTPromiseResolveBlock currentResolve = nil;
RCTPromiseRejectBlock currentReject = nil;
@implementation Dropbox
+ (NSString *)getAppKey{
NSArray *urlTypes
= [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleURLTypes"];
for (NSDictionary<NSString *, NSArray *> *urlType in urlTypes) {
NSArray *urlSchemes = urlType[@"CFBundleURLSchemes"];
if (urlSchemes) {
for (NSString *urlScheme in urlSchemes) {
if (urlScheme && [urlScheme hasPrefix:@"db-"]) {
return [urlScheme substringFromIndex:3];
}
}
}
}
return nil;
}
RCT_EXPORT_MODULE();
+ (BOOL)requiresMainQueueSetup {
return NO;
}
- (NSDictionary *)constantsToExport {
BOOL enabled = [Dropbox getAppKey] != nil;
return @{
@"ENABLED": [NSNumber numberWithBool:enabled]
};
};
RCT_EXPORT_METHOD(authorize:(RCTPromiseResolveBlock)resolve
reject:(__unused RCTPromiseRejectBlock)reject) {
currentResolve = resolve;
currentReject = reject;
dispatch_async(dispatch_get_main_queue(), ^{
[DBClientsManager authorizeFromController:[UIApplication sharedApplication]
controller:[[self class] topMostController]
openURL:^(NSURL *url) {
[[UIApplication sharedApplication] openURL:url];
}];
});
}
RCT_EXPORT_METHOD(getDisplayName: (NSString *)token
resolve: (RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {
DBUserClient *client = [[DBUserClient alloc] initWithAccessToken:token];
[[client.usersRoutes getCurrentAccount] setResponseBlock:^(DBUSERSFullAccount *result, DBNilObject *routeError, DBRequestError *networkError) {
if (result) {
resolve(result.name.displayName);
} else {
NSString *msg = @"Failed!";
if (networkError) {
msg = [NSString stringWithFormat:@"Failed! Error: %@", networkError];
}
reject(@"getDisplayName", @"Failed", nil);
}
}];
}
RCT_EXPORT_METHOD(getSpaceUsage: (NSString *)token
resolve: (RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {
DBUserClient *client = [[DBUserClient alloc] initWithAccessToken:token];
[[client.usersRoutes getSpaceUsage] setResponseBlock:^(DBUSERSSpaceUsage *result, DBNilObject *routeError, DBRequestError *networkError) {
if (result) {
DBUSERSSpaceAllocation *allocation = result.allocation;
NSNumber *allocated = 0;
NSNumber *used = 0;
if ([allocation isIndividual]) {
allocated = allocation.individual.allocated;
used = result.used;
} else if ([allocation isTeam]) {
allocated = allocation.team.allocated;
used = allocation.team.used;
}
id objects[] = { used, allocated };
id keys[] = { @"used", @"allocated" };
NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:objects
forKeys:keys
count:2];
resolve(dictionary);
} else {
NSString *msg = @"Failed!";
if (networkError) {
msg = [NSString stringWithFormat:@"Failed! Error: %@", networkError];
}
reject(@"getSpaceUsage", msg, nil);
}
}];
}
+ (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
if (currentReject == nil || currentResolve == nil) {
return NO;
}
DBOAuthResult *authResult = [DBClientsManager handleRedirectURL:url];
if (authResult) {
if ([authResult isSuccess]) {
currentResolve(authResult.accessToken.accessToken);
currentResolve = nil;
currentReject = nil;
} else {
NSString *msg;
if ([authResult isError]) {
msg = [NSString stringWithFormat:@"%@, error type: %ld",[authResult errorDescription], [authResult errorType]];
} else {
msg = @"OAuth canceled!";
}
currentReject(@"authorize", msg, nil);
currentResolve = nil;
currentReject = nil;
}
return YES;
}
return NO;
}
+ (UIViewController *)topMostController
{
UIViewController *topController
= [UIApplication sharedApplication].keyWindow.rootViewController;
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
return topController;
}
+ (void)setAppKey {
NSString *appKey = [self getAppKey];
if (appKey) {
[DBClientsManager setupWithAppKey:appKey];
}
}
@end

View File

@@ -130,18 +130,19 @@ cp "${CERT_DIR}/dev-profile.mobileprovision" ~/Library/MobileDevice/Provisionin
npm install
cd ios
pod update
pod install
cd ..
mkdir -p /tmp/jitsi-meet/
xcodebuild archive -workspace ios/jitsi-meet.xcworkspace -scheme jitsi-meet -configuration Release -archivePath /tmp/jitsi-meet/jitsi-meet.xcarchive
xcodebuild archive -quiet -workspace ios/jitsi-meet.xcworkspace -scheme jitsi-meet -configuration Release -archivePath /tmp/jitsi-meet/jitsi-meet.xcarchive
sed -e "s/YOUR_TEAM_ID/${IOS_TEAM_ID}/g" ios/travis-ci/build-ipa.plist.template > ios/travis-ci/build-ipa.plist
IPA_EXPORT_DIR=/tmp/jitsi-meet/jitsi-meet-ipa
xcodebuild -exportArchive -archivePath /tmp/jitsi-meet/jitsi-meet.xcarchive -exportPath $IPA_EXPORT_DIR -exportOptionsPlist ios/travis-ci/build-ipa.plist
xcodebuild -quiet -exportArchive -archivePath /tmp/jitsi-meet/jitsi-meet.xcarchive -exportPath $IPA_EXPORT_DIR -exportOptionsPlist ios/travis-ci/build-ipa.plist
echo "Will try deploy the .ipa to: ${IPA_DEPLOY_LOCATION}"

View File

@@ -1,11 +1,18 @@
{
"en": "Anglais",
"az": "Azerbaïdjanais",
"bg": "Bulgare",
"cs": "Tchèque",
"de": "Allemand",
"el": "Grec",
"eo": "Espéranto",
"es": "Espagnol",
"fr": "Français",
"hy": "Arménien",
"it": "Italien",
"ja": "Japonais",
"ko": "Coréen",
"nb": "Norvégien Bokmal",
"oc": "Occitan",
"pl": "Polonais",
"ptBR": "Portugais (Brésil)",
@@ -14,7 +21,6 @@
"sl": "Slovène",
"sv": "Suédois",
"tr": "Turc",
"zhCN": "Chinois (Chine)",
"nb": "Norvégien Bokmal",
"eo": "Espéranto"
"vi": "Vietnamien",
"zhCN": "Chinois (Chine)"
}

View File

@@ -1,11 +1,18 @@
{
"en": "Inglês",
"az": "Azerbaijanês",
"bg": "Búlgaro",
"cs": "Checo",
"de": "Alemão",
"el": "Grego",
"eo": "Esperanto",
"es": "Espanhol",
"fr": "Francês",
"hy": "Armênio",
"it": "Italiano",
"ja": "Japonês",
"ko": "Coreano",
"nb": "Bokmal norueguês",
"oc": "Occitano",
"pl": "Polonês",
"ptBR": "Português (Brasil)",
@@ -14,7 +21,6 @@
"sl": "Esloveno",
"sv": "Sueco",
"tr": "Turco",
"zhCN": "Chinês (China)",
"nb": "Bokmal norueguês",
"eo": "Esperanto"
"vi": "Vietnamita",
"zhCN": "Chinês (China)"
}

View File

@@ -15,6 +15,6 @@
"sv": "Шведский",
"tr": "Турецкий",
"zhCN": "Китайский (Китай)",
"nb": "",
"eo": ""
"nb": "Норвежский букмол",
"eo": "Эсперанто"
}

20
lang/languages-zhTW.json Normal file
View File

@@ -0,0 +1,20 @@
{
"en": "English",
"bg": "Bulgarian",
"de": "German",
"es": "Spanish",
"fr": "French",
"hy": "Armenian",
"it": "Italian",
"oc": "Occitan",
"pl": "Polish",
"ptBR": "Portuguese (Brazil)",
"ru": "Russian",
"sk": "Slovak",
"sl": "Slovenian",
"sv": "Swedish",
"tr": "Turkish",
"zhCN": "中文 简体 (中国)",
"nb": "Norwegian Bokmal",
"eo": "Esperanto"
}

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