content: import React from 'react';
  import { Provider } from 'react-redux';
  import {
      browserHistory,
      Route,
      Router
  } from 'react-router';
  import { push, syncHistoryWithStore } from 'react-router-redux';
  
  import { getDomain } from '../../base/connection';
  import { RouteRegistry } from '../../base/navigator';
  
  import { AbstractApp } from './AbstractApp';
  
  /**
   * Root application component.
   *
   * @extends AbstractApp
   */
  export class App extends AbstractApp {
      /**
       * Initializes a new App instance.
       *
       * @param {Object} props - The read-only React Component props with which
       * the new instance is to be initialized.
       */
      constructor(props) {
          super(props);
  
          /**
           * Create an enhanced history that syncs navigation events with the
           * store.
           * @link https://github.com/reactjs/react-router-redux#how-it-works
           */
          this.history = syncHistoryWithStore(browserHistory, props.store);
  
          // Bind event handlers so they are only bound once for every instance.
          this._onRouteEnter = this._onRouteEnter.bind(this);
          this._routerCreateElement = this._routerCreateElement.bind(this);
      }
  
      /**
       * Implements React's {@link Component#render()}.
       *
       * @inheritdoc
       * @returns {ReactElement}
       */
      render() {
          const routes = RouteRegistry.getRoutes();
  
          /* eslint-disable no-extra-parens */
          return (
              <Provider store = { this.props.store }>
                  <Router
                      createElement = { this._routerCreateElement }
                      history = { this.history }>
                      { routes.map(r => (
                          <Route
                              component = { r.component }
                              key = { r.component }
                              onEnter = { this._onRouteEnter }
                              path = { r.path } />
                      )) }
                  </Router>
              </Provider>
          );
  
          /* eslint-enable no-extra-parens */
      }
  
      /**
       * Navigates to a specific Route (via platform-specific means).
       *
       * @param {Route} route - The Route to which to navigate.
       * @returns {void}
       */
      _navigate(route) {
          let path = route.path;
          const store = this.props.store;
  
          // The syntax :room bellow is defined by react-router. It "matches a URL
          // segment up to the next /, ?, or #. The matched string is called a
          // param."
          path
              = path.replace(
                  /:room/g,
                  store.getState()['features/base/conference'].room);
  
          return store.dispatch(push(path));
      }
  
      /**
       * Invoked by react-router to notify this App that a Route is about to be
       * rendered.
       *
       * @private
       * @returns {void}
       */
      _onRouteEnter() {
          // XXX The following is mandatory. Otherwise, moving back & forward
          // through the browser's history could leave this App on the Conference
          // page without a room name.
  
          // Our Router configuration (at the time of this writing) is such that
          // each Route corresponds to a single URL. Hence, entering into a Route
          // is like opening a URL.
  
          // XXX In order to unify work with URLs in web and native environments,
          // we will construct URL here with correct domain from config.
          const currentDomain = getDomain(this.props.store.getState);
          const url
              = new URL(window.location.pathname, `https://${currentDomain}`)
                  .toString();
  
          this._openURL(url);
      }
  
      /**
       * Create a ReactElement from the specified component and props on behalf of
       * the associated Router.
       *
       * @param {Component} component - The component from which the ReactElement
       * is to be created.
       * @param {Object} props - The read-only React Component props with which
       * the ReactElement is to be initialized.
       * @private
       * @returns {ReactElement}
       */
      _routerCreateElement(component, props) {
          return this._createElement(component, props);
      }
  }
  
  /**
   * App component's property types.
   *
   * @static
   */
  App.propTypes = AbstractApp.propTypes;
  