You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.native.js 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // @flow
  2. // FIXME The bundler-related (and the browser-related) polyfills were born at
  3. // the very early days of prototyping the execution of lib-jitsi-meet on
  4. // react-native. Today, the feature base/lib-jitsi-meet should not be
  5. // responsible for such polyfills because it is not the only feature relying on
  6. // them. Additionally, the polyfills are usually necessary earlier than the
  7. // execution of base/lib-jitsi-meet (which is understandable given that the
  8. // polyfills are globals). The remaining problem to be solved here is where to
  9. // collect the polyfills' files.
  10. import './features/base/lib-jitsi-meet/native/polyfills-bundler';
  11. // FIXME: Remove once react-native-webrtc and react-native-prompt import
  12. // PropTypes from 'prop-types' instead of 'react'.
  13. import './features/base/react/prop-types-polyfill';
  14. import React, { Component } from 'react';
  15. import { AppRegistry, Linking, NativeModules } from 'react-native';
  16. import { App } from './features/app';
  17. import { equals } from './features/base/redux';
  18. import { IncomingCallApp } from './features/mobile/incoming-call';
  19. const logger = require('jitsi-meet-logger').getLogger(__filename);
  20. /**
  21. * The type of the React {@code Component} props of {@link Root}.
  22. */
  23. type Props = {
  24. /**
  25. * The URL, if any, with which the app was launched.
  26. */
  27. url: Object | string
  28. };
  29. /**
  30. * The type of the React {@code Component} state of {@link Root}.
  31. */
  32. type State = {
  33. /**
  34. * The URL, if any, with which the app was launched.
  35. */
  36. url: ?Object | string
  37. };
  38. /**
  39. * React Native doesn't support specifying props to the main/root component (in
  40. * the JS/JSX source code). So create a wrapper React Component (class) around
  41. * features/app's App instead.
  42. *
  43. * @extends Component
  44. */
  45. class Root extends Component<Props, State> {
  46. /**
  47. * Initializes a new {@code Root} instance.
  48. *
  49. * @param {Props} props - The read-only properties with which the new
  50. * instance is to be initialized.
  51. */
  52. constructor(props) {
  53. super(props);
  54. this.state = {
  55. url: this.props.url
  56. };
  57. // Handle the URL, if any, with which the app was launched. But props
  58. // have precedence.
  59. if (typeof this.props.url === 'undefined') {
  60. this._getInitialURL()
  61. .then(url => {
  62. if (typeof this.state.url === 'undefined') {
  63. this.setState({ url });
  64. }
  65. })
  66. .catch(err => {
  67. logger.error('Failed to get initial URL', err);
  68. if (typeof this.state.url === 'undefined') {
  69. // Start with an empty URL if getting the initial URL
  70. // fails; otherwise, nothing will be rendered.
  71. this.setState({ url: null });
  72. }
  73. });
  74. }
  75. }
  76. /**
  77. * Gets the initial URL the app was launched with. This can be a universal
  78. * (or deep) link, or a CallKit intent in iOS. Since the native
  79. * {@code Linking} module doesn't provide a way to access intents in iOS,
  80. * those are handled with the {@code LaunchOptions} module, which
  81. * essentially provides a replacement which takes that into consideration.
  82. *
  83. * @private
  84. * @returns {Promise} - A promise which will be fulfilled with the URL that
  85. * the app was launched with.
  86. */
  87. _getInitialURL() {
  88. if (NativeModules.LaunchOptions) {
  89. return NativeModules.LaunchOptions.getInitialURL();
  90. }
  91. return Linking.getInitialURL();
  92. }
  93. /**
  94. * Implements React's {@link Component#componentWillReceiveProps()}.
  95. *
  96. * New props can be set from the native side by setting the appProperties
  97. * property (on iOS) or calling setAppProperties (on Android).
  98. *
  99. * @inheritdoc
  100. */
  101. componentWillReceiveProps({ url }) {
  102. equals(this.props.url, url) || this.setState({ url: url || null });
  103. }
  104. /**
  105. * Implements React's {@link Component#render()}.
  106. *
  107. * @inheritdoc
  108. * @returns {ReactElement}
  109. */
  110. render() {
  111. const { url } = this.state;
  112. // XXX We don't render the App component until we get the initial URL.
  113. // Either it's null or some other non-null defined value.
  114. if (typeof url === 'undefined') {
  115. return null;
  116. }
  117. const {
  118. // The following props are forked in state:
  119. url: _, // eslint-disable-line no-unused-vars
  120. // The remaining props are passed through to App.
  121. ...props
  122. } = this.props;
  123. return (
  124. <App
  125. { ...props }
  126. url = { url } />
  127. );
  128. }
  129. }
  130. // Register the main/root Component of JitsiMeetView.
  131. AppRegistry.registerComponent('App', () => Root);
  132. // Register the main/root Component of IncomingCallView.
  133. AppRegistry.registerComponent('IncomingCallApp', () => IncomingCallApp);