Ver código fonte

feat(App): refactor App and split it into BaseApp and App

BaseApp does all the heavy-lifting related to creating the redux store,
navigation, and so on.

App currently handles URL props and actually triggering navigation based on
them.
master
Saúl Ibarra Corretgé 7 anos atrás
pai
commit
dc246960df
39 arquivos alterados com 455 adições e 406 exclusões
  1. 0
    44
      react/features/app/actions.js
  2. 40
    256
      react/features/app/components/AbstractApp.js
  3. 38
    31
      react/features/app/components/App.native.js
  4. 4
    9
      react/features/app/components/App.web.js
  5. 2
    26
      react/features/app/functions.any.js
  6. 0
    2
      react/features/app/index.js
  7. 1
    1
      react/features/app/middleware.js
  8. 0
    0
      react/features/base/app/actionTypes.js
  9. 48
    0
      react/features/base/app/actions.js
  10. 255
    0
      react/features/base/app/components/BaseApp.js
  11. 1
    0
      react/features/base/app/components/index.js
  12. 28
    0
      react/features/base/app/functions.js
  13. 6
    0
      react/features/base/app/index.js
  14. 5
    5
      react/features/base/app/reducer.js
  15. 1
    1
      react/features/base/config/middleware.js
  16. 2
    1
      react/features/base/known-domains/middleware.js
  17. 1
    1
      react/features/base/known-domains/reducer.js
  18. 1
    1
      react/features/base/logging/middleware.js
  19. 1
    1
      react/features/base/participants/middleware.js
  20. 1
    2
      react/features/base/settings/reducer.js
  21. 1
    1
      react/features/calendar-sync/middleware.js
  22. 1
    1
      react/features/calendar-sync/reducer.js
  23. 1
    1
      react/features/chat/middleware.js
  24. 1
    1
      react/features/invite/functions.js
  25. 1
    1
      react/features/invite/middleware.any.js
  26. 1
    1
      react/features/invite/middleware.native.js
  27. 1
    1
      react/features/mobile/audio-mode/middleware.js
  28. 1
    1
      react/features/mobile/background/middleware.js
  29. 2
    6
      react/features/mobile/callkit/middleware.js
  30. 1
    1
      react/features/mobile/external-api/middleware.js
  31. 1
    1
      react/features/mobile/full-screen/middleware.js
  32. 1
    1
      react/features/mobile/image-cache/middleware.js
  33. 1
    1
      react/features/mobile/network-activity/middleware.js
  34. 1
    1
      react/features/mobile/picture-in-picture/actions.js
  35. 1
    1
      react/features/mobile/picture-in-picture/components/PictureInPictureButton.js
  36. 1
    1
      react/features/recent-list/middleware.js
  37. 1
    1
      react/features/recent-list/reducer.js
  38. 1
    2
      react/features/recording/middleware.js
  39. 1
    1
      react/features/welcome/functions.js

+ 0
- 44
react/features/app/actions.js Ver arquivo

15
 import { parseURIString, toURLString } from '../base/util';
15
 import { parseURIString, toURLString } from '../base/util';
16
 import { setFatalError } from '../overlay';
16
 import { setFatalError } from '../overlay';
17
 
17
 
18
-import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from './actionTypes';
19
 import { getDefaultURL } from './functions';
18
 import { getDefaultURL } from './functions';
20
 
19
 
21
 const logger = require('jitsi-meet-logger').getLogger(__filename);
20
 const logger = require('jitsi-meet-logger').getLogger(__filename);
138
     return _appNavigateToMandatoryLocation(dispatch, getState, location);
137
     return _appNavigateToMandatoryLocation(dispatch, getState, location);
139
 }
138
 }
140
 
139
 
141
-/**
142
- * Signals that a specific App will mount (in the terms of React).
143
- *
144
- * @param {App} app - The App which will mount.
145
- * @returns {{
146
- *     type: APP_WILL_MOUNT,
147
- *     app: App
148
- * }}
149
- */
150
-export function appWillMount(app: Object) {
151
-    return (dispatch: Dispatch<*>) => {
152
-        dispatch({
153
-            type: APP_WILL_MOUNT,
154
-            app
155
-        });
156
-
157
-        // TODO There was a redux action creator appInit which I did not like
158
-        // because we already had the redux action creator appWillMount and,
159
-        // respectively, the redux action APP_WILL_MOUNT. So I set out to remove
160
-        // appInit and managed to move everything it was doing but the
161
-        // following. Which is not extremely bad because we haven't moved the
162
-        // API module into its own feature yet so we're bound to work on that in
163
-        // the future.
164
-        typeof APP === 'object' && APP.API.init();
165
-    };
166
-}
167
-
168
-/**
169
- * Signals that a specific App will unmount (in the terms of React).
170
- *
171
- * @param {App} app - The App which will unmount.
172
- * @returns {{
173
- *     type: APP_WILL_UNMOUNT,
174
- *     app: App
175
- * }}
176
- */
177
-export function appWillUnmount(app: Object) {
178
-    return {
179
-        type: APP_WILL_UNMOUNT,
180
-        app
181
-    };
182
-}
183
-
184
 /**
140
 /**
185
  * Loads config.js from a specific host.
141
  * Loads config.js from a specific host.
186
  *
142
  *

+ 40
- 256
react/features/app/components/AbstractApp.js Ver arquivo

1
-/* global APP */
1
+// @flow
2
 
2
 
3
-import _ from 'lodash';
4
-import PropTypes from 'prop-types';
5
-import React, { Component, Fragment } from 'react';
6
-import { I18nextProvider } from 'react-i18next';
7
-import { Provider } from 'react-redux';
8
-import { compose, createStore } from 'redux';
9
-import Thunk from 'redux-thunk';
3
+import React, { Fragment } from 'react';
10
 
4
 
11
-import { i18next } from '../../base/i18n';
12
-import {
13
-    MiddlewareRegistry,
14
-    ReducerRegistry,
15
-    StateListenerRegistry
16
-} from '../../base/redux';
17
-import { SoundCollection } from '../../base/sounds';
18
-import { PersistenceRegistry } from '../../base/storage';
5
+import { BaseApp } from '../../base/app';
19
 import { toURLString } from '../../base/util';
6
 import { toURLString } from '../../base/util';
20
 import { OverlayContainer } from '../../overlay';
7
 import { OverlayContainer } from '../../overlay';
21
 
8
 
22
-import { appNavigate, appWillMount, appWillUnmount } from '../actions';
9
+import { appNavigate } from '../actions';
23
 import { getDefaultURL } from '../functions';
10
 import { getDefaultURL } from '../functions';
24
 
11
 
25
 /**
12
 /**
26
- * Base (abstract) class for main App component.
27
- *
28
- * @abstract
13
+ * {@code AbstractApp} component's property types.
29
  */
14
  */
30
-export class AbstractApp extends Component {
15
+export type Props = {
16
+
31
     /**
17
     /**
32
-     * {@code AbstractApp} component's property types.
33
-     *
34
-     * @static
18
+     * The default URL {@code AbstractApp} is to open when not in any
19
+     * conference/room.
35
      */
20
      */
36
-    static propTypes = {
37
-        /**
38
-         * The default URL {@code AbstractApp} is to open when not in any
39
-         * conference/room.
40
-         */
41
-        defaultURL: PropTypes.string,
42
-
43
-        // XXX Refer to the implementation of loadURLObject: in
44
-        // ios/sdk/src/JitsiMeetView.m for further information.
45
-        timestamp: PropTypes.any,
46
-
47
-        /**
48
-         * The URL, if any, with which the app was launched.
49
-         */
50
-        url: PropTypes.oneOfType([
51
-            PropTypes.object,
52
-            PropTypes.string
53
-        ])
54
-    };
21
+    defaultURL: string,
55
 
22
 
56
     /**
23
     /**
57
-     * Initializes a new {@code AbstractApp} instance.
58
-     *
59
-     * @param {Object} props - The read-only React {@code Component} props with
60
-     * which the new instance is to be initialized.
24
+     * XXX Refer to the implementation of loadURLObject: in
25
+     * ios/sdk/src/JitsiMeetView.m for further information.
61
      */
26
      */
62
-    constructor(props) {
63
-        super(props);
64
-
65
-        this.state = {
27
+    timestamp: any,
66
 
28
 
67
-            /**
68
-             * The state of the »possible« async initialization of the
69
-             * {@code AbstractApp}.
70
-             */
71
-            appAsyncInitialized: false,
72
-
73
-            /**
74
-             * The Route rendered by this {@code AbstractApp}.
75
-             *
76
-             * @type {Route}
77
-             */
78
-            route: {},
79
-
80
-            /**
81
-             * The redux store used by this {@code AbstractApp}.
82
-             *
83
-             * @type {Store}
84
-             */
85
-            store: undefined
86
-        };
29
+    /**
30
+     * The URL, if any, with which the app was launched.
31
+     */
32
+    url: Object | string
33
+};
87
 
34
 
88
-        /**
89
-         * Make the mobile {@code AbstractApp} wait until the
90
-         * {@code AsyncStorage} implementation of {@code Storage} initializes
91
-         * fully.
92
-         *
93
-         * @private
94
-         * @see {@link #_initStorage}
95
-         * @type {Promise}
96
-         */
97
-        this._init
98
-            = this._initStorage()
99
-                .catch(() => { /* AbstractApp should always initialize! */ })
100
-                .then(() =>
101
-                    this.setState({
102
-                        store: this._createStore()
103
-                    }));
104
-    }
35
+/**
36
+ * Base (abstract) class for main App component.
37
+ *
38
+ * @abstract
39
+ */
40
+export class AbstractApp extends BaseApp<Props, *> {
41
+    _init: Promise<*>;
105
 
42
 
106
     /**
43
     /**
107
      * Initializes the app.
44
      * Initializes the app.
109
      * @inheritdoc
46
      * @inheritdoc
110
      */
47
      */
111
     componentWillMount() {
48
     componentWillMount() {
112
-        this._init.then(() => {
113
-            const { dispatch } = this.state.store;
114
-
115
-            dispatch(appWillMount(this));
49
+        super.componentWillMount();
116
 
50
 
117
-            // We set the initialized state here and not in the constructor to
118
-            // make sure that {@code componentWillMount} gets invoked before the
119
-            // app tries to render the actual app content.
120
-            this.setState({
121
-                appAsyncInitialized: true
122
-            });
123
-
124
-            // If a URL was explicitly specified to this React Component, then
125
-            // open it; otherwise, use a default.
51
+        this._init.then(() => {
52
+            // If a URL was explicitly specified to this React Component,
53
+            // then open it; otherwise, use a default.
126
             this._openURL(toURLString(this.props.url) || this._getDefaultURL());
54
             this._openURL(toURLString(this.props.url) || this._getDefaultURL());
127
         });
55
         });
128
     }
56
     }
136
      * that this instance will receive.
64
      * that this instance will receive.
137
      * @returns {void}
65
      * @returns {void}
138
      */
66
      */
139
-    componentWillReceiveProps(nextProps) {
67
+    componentWillReceiveProps(nextProps: Props) {
140
         const { props } = this;
68
         const { props } = this;
141
 
69
 
142
         this._init.then(() => {
70
         this._init.then(() => {
154
         });
82
         });
155
     }
83
     }
156
 
84
 
157
-    /**
158
-     * De-initializes the app.
159
-     *
160
-     * @inheritdoc
161
-     */
162
-    componentWillUnmount() {
163
-        this.state.store.dispatch(appWillUnmount(this));
164
-    }
165
-
166
     /**
85
     /**
167
      * Gets a {@code Location} object from the window with information about the
86
      * Gets a {@code Location} object from the window with information about the
168
      * current location of the document. Explicitly defined to allow extenders
87
      * current location of the document. Explicitly defined to allow extenders
180
     }
99
     }
181
 
100
 
182
     /**
101
     /**
183
-     * Delays this {@code AbstractApp}'s startup until the {@code Storage}
184
-     * implementation of {@code localStorage} initializes. While the
185
-     * initialization is instantaneous on Web (with Web Storage API), it is
186
-     * asynchronous on mobile/react-native.
187
-     *
188
-     * @private
189
-     * @returns {Promise}
190
-     */
191
-    _initStorage() {
192
-        const localStorageInitializing = window.localStorage._initializing;
193
-
194
-        return (
195
-            typeof localStorageInitializing === 'undefined'
196
-                ? Promise.resolve()
197
-                : localStorageInitializing);
198
-    }
199
-
200
-    /**
201
-     * Implements React's {@link Component#render()}.
202
-     *
203
-     * @inheritdoc
204
-     * @returns {ReactElement}
205
-     */
206
-    render() {
207
-        const { appAsyncInitialized, route, store } = this.state;
208
-        const { component } = route;
209
-
210
-        if (appAsyncInitialized && component) {
211
-            return (
212
-                <I18nextProvider i18n = { i18next }>
213
-                    <Provider store = { store }>
214
-                        <Fragment>
215
-                            { this._createElement(component) }
216
-                            <SoundCollection />
217
-                            <OverlayContainer />
218
-                        </Fragment>
219
-                    </Provider>
220
-                </I18nextProvider>
221
-            );
222
-        }
223
-
224
-        return null;
225
-    }
226
-
227
-    /**
228
-     * Creates a {@link ReactElement} from the specified component, the
229
-     * specified props and the props of this {@code AbstractApp} which are
230
-     * suitable for propagation to the children of this {@code Component}.
102
+     * Creates an extra {@link ReactElement}s to be added (unconditionaly)
103
+     * alongside the main element.
231
      *
104
      *
232
-     * @param {Component} component - The component from which the
233
-     * {@code ReactElement} is to be created.
234
-     * @param {Object} props - The read-only React {@code Component} props with
235
-     * which the {@code ReactElement} is to be initialized.
236
      * @returns {ReactElement}
105
      * @returns {ReactElement}
106
+     * @abstract
237
      * @protected
107
      * @protected
238
      */
108
      */
239
-    _createElement(component, props) {
240
-        /* eslint-disable no-unused-vars */
241
-
242
-        const {
243
-            // The following props were introduced to be consumed entirely by
244
-            // AbstractApp:
245
-            defaultURL,
246
-            timestamp,
247
-            url,
248
-
249
-            // The remaining props, if any, are considered suitable for
250
-            // propagation to the children of this Component.
251
-            ...thisProps
252
-        } = this.props;
253
-
254
-        /* eslint-enable no-unused-vars */
255
-
256
-        return React.createElement(component, {
257
-            ...thisProps,
258
-            ...props
259
-        });
109
+    _createExtraElement() {
110
+        return (
111
+            <Fragment>
112
+                <OverlayContainer />
113
+            </Fragment>
114
+        );
260
     }
115
     }
261
 
116
 
262
-    /**
263
-     * Initializes a new redux store instance suitable for use by this
264
-     * {@code AbstractApp}.
265
-     *
266
-     * @private
267
-     * @returns {Store} - A new redux store instance suitable for use by this
268
-     * {@code AbstractApp}.
269
-     */
270
-    _createStore() {
271
-        // Create combined reducer from all reducers in ReducerRegistry.
272
-        const reducer = ReducerRegistry.combineReducers();
273
-
274
-        // Apply all registered middleware from the MiddlewareRegistry and
275
-        // additional 3rd party middleware:
276
-        // - Thunk - allows us to dispatch async actions easily. For more info
277
-        // @see https://github.com/gaearon/redux-thunk.
278
-        let middleware = MiddlewareRegistry.applyMiddleware(Thunk);
279
-
280
-        // Try to enable Redux DevTools Chrome extension in order to make it
281
-        // available for the purposes of facilitating development.
282
-        let devToolsExtension;
283
-
284
-        if (typeof window === 'object'
285
-                && (devToolsExtension = window.devToolsExtension)) {
286
-            middleware = compose(middleware, devToolsExtension());
287
-        }
288
-
289
-        const store
290
-            = createStore(
291
-                reducer,
292
-                PersistenceRegistry.getPersistedState(),
293
-                middleware);
294
-
295
-        // StateListenerRegistry
296
-        StateListenerRegistry.subscribe(store);
297
-
298
-        // This is temporary workaround to be able to dispatch actions from
299
-        // non-reactified parts of the code (conference.js for example).
300
-        // Don't use in the react code!!!
301
-        // FIXME: remove when the reactification is finished!
302
-        if (typeof APP !== 'undefined') {
303
-            APP.store = store;
304
-        }
305
-
306
-        return store;
307
-    }
117
+    _createMainElement: (React$Element<*>, Object) => ?React$Element<*>;
308
 
118
 
309
     /**
119
     /**
310
      * Gets the default URL to be opened when this {@code App} mounts.
120
      * Gets the default URL to be opened when this {@code App} mounts.
317
         return getDefaultURL(this.state.store);
127
         return getDefaultURL(this.state.store);
318
     }
128
     }
319
 
129
 
320
-    /**
321
-     * Navigates to a specific Route.
322
-     *
323
-     * @param {Route} route - The Route to which to navigate.
324
-     * @returns {Promise}
325
-     */
326
-    _navigate(route) {
327
-        if (_.isEqual(route, this.state.route)) {
328
-            return Promise.resolve();
329
-        }
330
-
331
-        if (route.href) {
332
-            // This navigation requires loading a new URL in the browser.
333
-            window.location.href = route.href;
334
-
335
-            return Promise.resolve();
336
-        }
337
-
338
-        // XXX React's setState is asynchronous which means that the value of
339
-        // this.state.route above may not even be correct. If the check is
340
-        // performed before setState completes, the app may not navigate to the
341
-        // expected route. In order to mitigate the problem, _navigate was
342
-        // changed to return a Promise.
343
-        return new Promise(resolve => this.setState({ route }, resolve));
344
-    }
345
-
346
     /**
130
     /**
347
      * Navigates this {@code AbstractApp} to (i.e. opens) a specific URL.
131
      * Navigates this {@code AbstractApp} to (i.e. opens) a specific URL.
348
      *
132
      *

+ 38
- 31
react/features/app/components/App.native.js Ver arquivo

1
-/* global __DEV__ */
1
+// @flow
2
 
2
 
3
-import PropTypes from 'prop-types';
4
 import React from 'react';
3
 import React from 'react';
5
 import { Linking } from 'react-native';
4
 import { Linking } from 'react-native';
6
 
5
 
23
 import '../../mobile/wake-lock';
22
 import '../../mobile/wake-lock';
24
 
23
 
25
 import { AbstractApp } from './AbstractApp';
24
 import { AbstractApp } from './AbstractApp';
25
+import type { Props as AbstractAppProps } from './AbstractApp';
26
+
27
+declare var __DEV__;
26
 
28
 
27
 /**
29
 /**
28
- * Root application component.
29
- *
30
- * @extends AbstractApp
30
+ * App component's property types.
31
  */
31
  */
32
-export class App extends AbstractApp {
32
+type Props = AbstractAppProps & {
33
+
33
     /**
34
     /**
34
-     * App component's property types.
35
-     *
36
-     * @static
35
+     * Whether the add people feature is enabled or not.
37
      */
36
      */
38
-    static propTypes = {
39
-        ...AbstractApp.propTypes,
40
-
41
-        addPeopleEnabled: PropTypes.bool,
37
+    addPeopleEnabled: boolean,
42
 
38
 
43
-        dialOutEnabled: PropTypes.bool,
39
+    /**
40
+     * Whether the dial-out feature is enabled or not.
41
+     */
42
+    dialOutEnabled: boolean,
44
 
43
 
45
-        /**
46
-         * Whether Picture-in-Picture is enabled. If {@code true}, a toolbar
47
-         * button is rendered in the {@link Conference} view to afford entering
48
-         * Picture-in-Picture.
49
-         */
50
-        pictureInPictureEnabled: PropTypes.bool,
44
+    /**
45
+     * Whether Picture-in-Picture is enabled. If {@code true}, a toolbar
46
+     * button is rendered in the {@link Conference} view to afford entering
47
+     * Picture-in-Picture.
48
+     */
49
+    pictureInPictureEnabled: boolean,
51
 
50
 
52
-        /**
53
-         * Whether the Welcome page is enabled. If {@code true}, the Welcome
54
-         * page is rendered when the {@link App} is not at a location (URL)
55
-         * identifying a Jitsi Meet conference/room.
56
-         */
57
-        welcomePageEnabled: PropTypes.bool
58
-    };
51
+    /**
52
+     * Whether the Welcome page is enabled. If {@code true}, the Welcome
53
+     * page is rendered when the {@link App} is not at a location (URL)
54
+     * identifying a Jitsi Meet conference/room.
55
+     */
56
+    welcomePageEnabled: boolean
57
+};
59
 
58
 
59
+/**
60
+ * Root application component.
61
+ *
62
+ * @extends AbstractApp
63
+ */
64
+export class App extends AbstractApp {
60
     /**
65
     /**
61
      * Initializes a new App instance.
66
      * Initializes a new App instance.
62
      *
67
      *
63
      * @param {Object} props - The read-only React Component props with which
68
      * @param {Object} props - The read-only React Component props with which
64
      * the new instance is to be initialized.
69
      * the new instance is to be initialized.
65
      */
70
      */
66
-    constructor(props) {
71
+    constructor(props: Props) {
67
         super(props);
72
         super(props);
68
 
73
 
69
         // Bind event handlers so they are only bound once for every instance.
74
         // Bind event handlers so they are only bound once for every instance.
110
      *
115
      *
111
      * @override
116
      * @override
112
      */
117
      */
113
-    _createElement(component, props) {
118
+    _createMainElement(component, props) {
114
         return (
119
         return (
115
             <AspectRatioDetector>
120
             <AspectRatioDetector>
116
                 <ReducedUIDetector>
121
                 <ReducedUIDetector>
117
-                    { super._createElement(component, props) }
122
+                    { super._createMainElement(component, props) }
118
                 </ReducedUIDetector>
123
                 </ReducedUIDetector>
119
             </AspectRatioDetector>
124
             </AspectRatioDetector>
120
         );
125
         );
158
         }
163
         }
159
     }
164
     }
160
 
165
 
166
+    _onLinkingURL: (*) => void;
167
+
161
     /**
168
     /**
162
      * Notified by React's Linking API that a specific URL registered to be
169
      * Notified by React's Linking API that a specific URL registered to be
163
      * handled by this App was activated.
170
      * handled by this App was activated.
169
      * @returns {void}
176
      * @returns {void}
170
      */
177
      */
171
     _onLinkingURL({ url }) {
178
     _onLinkingURL({ url }) {
172
-        this._openURL(url);
179
+        super._openURL(url);
173
     }
180
     }
174
 }
181
 }
175
 
182
 

+ 4
- 9
react/features/app/components/App.web.js Ver arquivo

1
+// @flow
2
+
1
 import { AtlasKitThemeProvider } from '@atlaskit/theme';
3
 import { AtlasKitThemeProvider } from '@atlaskit/theme';
2
 import React from 'react';
4
 import React from 'react';
3
 
5
 
14
  * @extends AbstractApp
16
  * @extends AbstractApp
15
  */
17
  */
16
 export class App extends AbstractApp {
18
 export class App extends AbstractApp {
17
-    /**
18
-     * App component's property types.
19
-     *
20
-     * @static
21
-     */
22
-    static propTypes = AbstractApp.propTypes;
23
-
24
     /**
19
     /**
25
      * Overrides the parent method to inject {@link AtlasKitThemeProvider} as
20
      * Overrides the parent method to inject {@link AtlasKitThemeProvider} as
26
      * the top most component.
21
      * the top most component.
27
      *
22
      *
28
      * @override
23
      * @override
29
      */
24
      */
30
-    _createElement(component, props) {
25
+    _createMainElement(component, props) {
31
         return (
26
         return (
32
             <AtlasKitThemeProvider mode = 'dark'>
27
             <AtlasKitThemeProvider mode = 'dark'>
33
-                { super._createElement(component, props) }
28
+                { super._createMainElement(component, props) }
34
             </AtlasKitThemeProvider>
29
             </AtlasKitThemeProvider>
35
         );
30
         );
36
     }
31
     }

+ 2
- 26
react/features/app/functions.any.js Ver arquivo

1
 // @flow
1
 // @flow
2
 
2
 
3
+import { getAppProp } from '../base/app';
3
 import { toState } from '../base/redux';
4
 import { toState } from '../base/redux';
4
 import { getServerURL } from '../base/settings';
5
 import { getServerURL } from '../base/settings';
5
 
6
 
6
-/**
7
- * Gets the value of a specific React {@code Component} prop of the currently
8
- * mounted {@link App}.
9
- *
10
- * @param {Function|Object} stateful - The redux store or {@code getState}
11
- * function.
12
- * @param {string} propName - The name of the React {@code Component} prop of
13
- * the currently mounted {@code App} to get.
14
- * @returns {*} The value of the specified React {@code Compoennt} prop of the
15
- * currently mounted {@code App}.
16
- */
17
-export function getAppProp(stateful: Function | Object, propName: string) {
18
-    const state = toState(stateful)['features/app'];
19
-
20
-    if (state) {
21
-        const { app } = state;
22
-
23
-        if (app) {
24
-            return app.props[propName];
25
-        }
26
-    }
27
-
28
-    return undefined;
29
-}
30
-
31
 /**
7
 /**
32
  * Retrieves the default URL for the app. This can either come from a prop to
8
  * Retrieves the default URL for the app. This can either come from a prop to
33
  * the root App component or be configured in the settings.
9
  * the root App component or be configured in the settings.
38
  */
14
  */
39
 export function getDefaultURL(stateful: Function | Object) {
15
 export function getDefaultURL(stateful: Function | Object) {
40
     const state = toState(stateful);
16
     const state = toState(stateful);
41
-    const { app } = state['features/app'];
17
+    const { app } = state['features/base/app'];
42
 
18
 
43
     // If the execution environment provides a Location abstraction (e.g. a Web
19
     // If the execution environment provides a Location abstraction (e.g. a Web
44
     // browser), then we'll presume it's the one and only base URL it can be on.
20
     // browser), then we'll presume it's the one and only base URL it can be on.

+ 0
- 2
react/features/app/index.js Ver arquivo

1
 export * from './actions';
1
 export * from './actions';
2
-export * from './actionTypes';
3
 export * from './components';
2
 export * from './components';
4
 export * from './functions';
3
 export * from './functions';
5
 
4
 
6
 import './middleware';
5
 import './middleware';
7
-import './reducer';

+ 1
- 1
react/features/app/middleware.js Ver arquivo

72
  */
72
  */
73
 function _navigate({ getState }) {
73
 function _navigate({ getState }) {
74
     const state = getState();
74
     const state = getState();
75
-    const { app } = state['features/app'];
75
+    const { app } = state['features/base/app'];
76
 
76
 
77
     _getRouteToRender(state).then(route => app._navigate(route));
77
     _getRouteToRender(state).then(route => app._navigate(route));
78
 }
78
 }

react/features/app/actionTypes.js → react/features/base/app/actionTypes.js Ver arquivo


+ 48
- 0
react/features/base/app/actions.js Ver arquivo

1
+// @flow
2
+
3
+import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from './actionTypes';
4
+
5
+declare var APP;
6
+
7
+/**
8
+ * Signals that a specific App will mount (in the terms of React).
9
+ *
10
+ * @param {App} app - The App which will mount.
11
+ * @returns {{
12
+ *     type: APP_WILL_MOUNT,
13
+ *     app: App
14
+ * }}
15
+ */
16
+export function appWillMount(app: Object) {
17
+    return (dispatch: Dispatch<*>) => {
18
+        dispatch({
19
+            type: APP_WILL_MOUNT,
20
+            app
21
+        });
22
+
23
+        // TODO There was a redux action creator appInit which I did not like
24
+        // because we already had the redux action creator appWillMount and,
25
+        // respectively, the redux action APP_WILL_MOUNT. So I set out to remove
26
+        // appInit and managed to move everything it was doing but the
27
+        // following. Which is not extremely bad because we haven't moved the
28
+        // API module into its own feature yet so we're bound to work on that in
29
+        // the future.
30
+        typeof APP === 'object' && APP.API.init();
31
+    };
32
+}
33
+
34
+/**
35
+ * Signals that a specific App will unmount (in the terms of React).
36
+ *
37
+ * @param {App} app - The App which will unmount.
38
+ * @returns {{
39
+ *     type: APP_WILL_UNMOUNT,
40
+ *     app: App
41
+ * }}
42
+ */
43
+export function appWillUnmount(app: Object) {
44
+    return {
45
+        type: APP_WILL_UNMOUNT,
46
+        app
47
+    };
48
+}

+ 255
- 0
react/features/base/app/components/BaseApp.js Ver arquivo

1
+// @flow
2
+
3
+import _ from 'lodash';
4
+import React, { Component, Fragment } from 'react';
5
+import { I18nextProvider } from 'react-i18next';
6
+import { Provider } from 'react-redux';
7
+import { compose, createStore } from 'redux';
8
+import Thunk from 'redux-thunk';
9
+
10
+import { i18next } from '../../i18n';
11
+import {
12
+    MiddlewareRegistry,
13
+    ReducerRegistry,
14
+    StateListenerRegistry
15
+} from '../../redux';
16
+import { SoundCollection } from '../../sounds';
17
+import { PersistenceRegistry } from '../../storage';
18
+
19
+import { appWillMount, appWillUnmount } from '../actions';
20
+
21
+declare var APP: Object;
22
+
23
+type State = {
24
+
25
+    /**
26
+     * The state of the »possible« async initialization of
27
+     * the {@code BaseApp}.
28
+     */
29
+    initialized: boolean,
30
+
31
+    /**
32
+     * The Route rendered by this {@code BaseApp}.
33
+     */
34
+    route: Object,
35
+
36
+    /**
37
+     * The redux store used by this {@code BaseApp}.
38
+     */
39
+    store: Object
40
+};
41
+
42
+/**
43
+ * Base (abstract) class for main App component.
44
+ *
45
+ * @abstract
46
+ */
47
+export default class BaseApp extends Component<*, State> {
48
+    _init: Promise<*>;
49
+
50
+    /**
51
+     * Initializes a new {@code BaseApp} instance.
52
+     *
53
+     * @param {Object} props - The read-only React {@code Component} props with
54
+     * which the new instance is to be initialized.
55
+     */
56
+    constructor(props: Object) {
57
+        super(props);
58
+
59
+        this.state = {
60
+            initialized: false,
61
+            route: {},
62
+
63
+            // $FlowFixMe
64
+            store: undefined
65
+        };
66
+
67
+        /**
68
+         * Make the mobile {@code BaseApp} wait until the
69
+         * {@code AsyncStorage} implementation of {@code Storage} initializes
70
+         * fully.
71
+         *
72
+         * @private
73
+         * @see {@link #_initStorage}
74
+         * @type {Promise}
75
+         */
76
+        this._init
77
+            = this._initStorage()
78
+                .catch(() => { /* AbstractApp should always initialize! */ })
79
+                .then(() =>
80
+                    this.setState({
81
+                        store: this._createStore()
82
+                    }));
83
+    }
84
+
85
+    /**
86
+     * Initialize the application.
87
+     *
88
+     * @inheritdoc
89
+     */
90
+    componentWillMount() {
91
+        this._init.then(() => {
92
+            const { dispatch } = this.state.store;
93
+
94
+            dispatch(appWillMount(this));
95
+
96
+            // We set the initialized state here and not in the constructor to
97
+            // make sure that {@code componentWillMount} gets invoked before
98
+            // the app tries to render the actual app content.
99
+            this.setState({ initialized: true });
100
+        });
101
+    }
102
+
103
+    /**
104
+     * De-initialize the application.
105
+     *
106
+     * @inheritdoc
107
+     */
108
+    componentWillUnmount() {
109
+        const { dispatch } = this.state.store;
110
+
111
+        dispatch(appWillUnmount(this));
112
+    }
113
+
114
+    /**
115
+     * Delays this {@code BaseApp}'s startup until the {@code Storage}
116
+     * implementation of {@code localStorage} initializes. While the
117
+     * initialization is instantaneous on Web (with Web Storage API), it is
118
+     * asynchronous on mobile/react-native.
119
+     *
120
+     * @private
121
+     * @returns {Promise}
122
+     */
123
+    _initStorage(): Promise<*> {
124
+        const { _initializing } = window.localStorage;
125
+
126
+        return _initializing || Promise.resolve();
127
+    }
128
+
129
+    /**
130
+     * Implements React's {@link Component#render()}.
131
+     *
132
+     * @inheritdoc
133
+     * @returns {ReactElement}
134
+     */
135
+    render() {
136
+        const { initialized, route, store } = this.state;
137
+        const { component } = route;
138
+
139
+        if (initialized && component) {
140
+            return (
141
+                <I18nextProvider i18n = { i18next }>
142
+                    <Provider store = { store }>
143
+                        <Fragment>
144
+                            { this._createMainElement(component) }
145
+                            <SoundCollection />
146
+                            { this._createExtraElement() }
147
+                        </Fragment>
148
+                    </Provider>
149
+                </I18nextProvider>
150
+            );
151
+        }
152
+
153
+        return null;
154
+    }
155
+
156
+    /**
157
+     * Creates an extra {@link ReactElement}s to be added (unconditionaly)
158
+     * alongside the main element.
159
+     *
160
+     * @returns {ReactElement}
161
+     * @abstract
162
+     * @protected
163
+     */
164
+    _createExtraElement() {
165
+        return null;
166
+    }
167
+
168
+    /**
169
+     * Creates a {@link ReactElement} from the specified component, the
170
+     * specified props and the props of this {@code AbstractApp} which are
171
+     * suitable for propagation to the children of this {@code Component}.
172
+     *
173
+     * @param {Component} component - The component from which the
174
+     * {@code ReactElement} is to be created.
175
+     * @param {Object} props - The read-only React {@code Component} props with
176
+     * which the {@code ReactElement} is to be initialized.
177
+     * @returns {ReactElement}
178
+     * @protected
179
+     */
180
+    _createMainElement(component, props) {
181
+        return React.createElement(component, props || {});
182
+    }
183
+
184
+    /**
185
+     * Initializes a new redux store instance suitable for use by this
186
+     * {@code AbstractApp}.
187
+     *
188
+     * @private
189
+     * @returns {Store} - A new redux store instance suitable for use by
190
+     * this {@code AbstractApp}.
191
+     */
192
+    _createStore() {
193
+        // Create combined reducer from all reducers in ReducerRegistry.
194
+        const reducer = ReducerRegistry.combineReducers();
195
+
196
+        // Apply all registered middleware from the MiddlewareRegistry and
197
+        // additional 3rd party middleware:
198
+        // - Thunk - allows us to dispatch async actions easily. For more info
199
+        // @see https://github.com/gaearon/redux-thunk.
200
+        let middleware = MiddlewareRegistry.applyMiddleware(Thunk);
201
+
202
+        // Try to enable Redux DevTools Chrome extension in order to make it
203
+        // available for the purposes of facilitating development.
204
+        let devToolsExtension;
205
+
206
+        if (typeof window === 'object'
207
+                && (devToolsExtension = window.devToolsExtension)) {
208
+            middleware = compose(middleware, devToolsExtension());
209
+        }
210
+
211
+        const store = createStore(
212
+            reducer, PersistenceRegistry.getPersistedState(), middleware);
213
+
214
+        // StateListenerRegistry
215
+        StateListenerRegistry.subscribe(store);
216
+
217
+        // This is temporary workaround to be able to dispatch actions from
218
+        // non-reactified parts of the code (conference.js for example).
219
+        // Don't use in the react code!!!
220
+        // FIXME: remove when the reactification is finished!
221
+        if (typeof APP !== 'undefined') {
222
+            APP.store = store;
223
+        }
224
+
225
+        return store;
226
+    }
227
+
228
+    /**
229
+     * Navigates to a specific Route.
230
+     *
231
+     * @param {Route} route - The Route to which to navigate.
232
+     * @returns {Promise}
233
+     */
234
+    _navigate(route): Promise<*> {
235
+        if (_.isEqual(route, this.state.route)) {
236
+            return Promise.resolve();
237
+        }
238
+
239
+        if (route.href) {
240
+            // This navigation requires loading a new URL in the browser.
241
+            window.location.href = route.href;
242
+
243
+            return Promise.resolve();
244
+        }
245
+
246
+        // XXX React's setState is asynchronous which means that the value of
247
+        // this.state.route above may not even be correct. If the check is
248
+        // performed before setState completes, the app may not navigate to the
249
+        // expected route. In order to mitigate the problem, _navigate was
250
+        // changed to return a Promise.
251
+        return new Promise(resolve => {
252
+            this.setState({ route }, resolve);
253
+        });
254
+    }
255
+}

+ 1
- 0
react/features/base/app/components/index.js Ver arquivo

1
+export { default as BaseApp } from './BaseApp';

+ 28
- 0
react/features/base/app/functions.js Ver arquivo

1
+// @flow
2
+
3
+import { toState } from '../redux';
4
+
5
+/**
6
+ * Gets the value of a specific React {@code Component} prop of the currently
7
+ * mounted {@link App}.
8
+ *
9
+ * @param {Function|Object} stateful - The redux store or {@code getState}
10
+ * function.
11
+ * @param {string} propName - The name of the React {@code Component} prop of
12
+ * the currently mounted {@code App} to get.
13
+ * @returns {*} The value of the specified React {@code Compoennt} prop of the
14
+ * currently mounted {@code App}.
15
+ */
16
+export function getAppProp(stateful: Function | Object, propName: string) {
17
+    const state = toState(stateful)['features/base/app'];
18
+
19
+    if (state) {
20
+        const { app } = state;
21
+
22
+        if (app) {
23
+            return app.props[propName];
24
+        }
25
+    }
26
+
27
+    return undefined;
28
+}

+ 6
- 0
react/features/base/app/index.js Ver arquivo

1
+export * from './actions';
2
+export * from './actionTypes';
3
+export * from './components';
4
+export * from './functions';
5
+
6
+import './reducer';

react/features/app/reducer.js → react/features/base/app/reducer.js Ver arquivo

1
 // @flow
1
 // @flow
2
 
2
 
3
-import { ReducerRegistry } from '../base/redux';
3
+import { ReducerRegistry } from '../redux';
4
 
4
 
5
 import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from './actionTypes';
5
 import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from './actionTypes';
6
 
6
 
7
-ReducerRegistry.register('features/app', (state = {}, action) => {
7
+ReducerRegistry.register('features/base/app', (state = {}, action) => {
8
     switch (action.type) {
8
     switch (action.type) {
9
     case APP_WILL_MOUNT: {
9
     case APP_WILL_MOUNT: {
10
         const { app } = action;
10
         const { app } = action;
14
                 ...state,
14
                 ...state,
15
 
15
 
16
                 /**
16
                 /**
17
-                 * The one and only (i.e. singleton) {@link App} instance which
18
-                 * is currently mounted.
17
+                 * The one and only (i.e. singleton) {@link BaseApp} instance
18
+                 * which is currently mounted.
19
                  *
19
                  *
20
-                 * @type {App}
20
+                 * @type {BaseApp}
21
                  */
21
                  */
22
                 app
22
                 app
23
             };
23
             };

+ 1
- 1
react/features/base/config/middleware.js Ver arquivo

1
 // @flow
1
 // @flow
2
 
2
 
3
-import { APP_WILL_MOUNT } from '../../app';
3
+import { APP_WILL_MOUNT } from '../app';
4
 import { addKnownDomains } from '../known-domains';
4
 import { addKnownDomains } from '../known-domains';
5
 import { MiddlewareRegistry } from '../redux';
5
 import { MiddlewareRegistry } from '../redux';
6
 import { parseURIString } from '../util';
6
 import { parseURIString } from '../util';

+ 2
- 1
react/features/base/known-domains/middleware.js Ver arquivo

1
 // @flow
1
 // @flow
2
 
2
 
3
-import { APP_WILL_MOUNT, getDefaultURL } from '../../app';
3
+import { getDefaultURL } from '../../app';
4
 
4
 
5
+import { APP_WILL_MOUNT } from '../app';
5
 import { SET_ROOM } from '../conference';
6
 import { SET_ROOM } from '../conference';
6
 import { MiddlewareRegistry } from '../redux';
7
 import { MiddlewareRegistry } from '../redux';
7
 import { parseURIString } from '../util';
8
 import { parseURIString } from '../util';

+ 1
- 1
react/features/base/known-domains/reducer.js Ver arquivo

1
 // @flow
1
 // @flow
2
 
2
 
3
-import { APP_WILL_MOUNT } from '../../app';
3
+import { APP_WILL_MOUNT } from '../app';
4
 import { ReducerRegistry } from '../redux';
4
 import { ReducerRegistry } from '../redux';
5
 import { PersistenceRegistry } from '../storage';
5
 import { PersistenceRegistry } from '../storage';
6
 
6
 

+ 1
- 1
react/features/base/logging/middleware.js Ver arquivo

2
 
2
 
3
 import Logger from 'jitsi-meet-logger';
3
 import Logger from 'jitsi-meet-logger';
4
 
4
 
5
-import { APP_WILL_MOUNT } from '../../app';
5
+import { APP_WILL_MOUNT } from '../app';
6
 import JitsiMeetJS, { LIB_WILL_INIT } from '../lib-jitsi-meet';
6
 import JitsiMeetJS, { LIB_WILL_INIT } from '../lib-jitsi-meet';
7
 import { MiddlewareRegistry } from '../redux';
7
 import { MiddlewareRegistry } from '../redux';
8
 
8
 

+ 1
- 1
react/features/base/participants/middleware.js Ver arquivo

1
 // @flow
1
 // @flow
2
 
2
 
3
-import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../app';
3
+import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app';
4
 import {
4
 import {
5
     CONFERENCE_WILL_JOIN,
5
     CONFERENCE_WILL_JOIN,
6
     forEachConference,
6
     forEachConference,

+ 1
- 2
react/features/base/settings/reducer.js Ver arquivo

1
 // @flow
1
 // @flow
2
 import _ from 'lodash';
2
 import _ from 'lodash';
3
 
3
 
4
-import { APP_WILL_MOUNT } from '../../app';
5
-
4
+import { APP_WILL_MOUNT } from '../app';
6
 import JitsiMeetJS, { browser } from '../lib-jitsi-meet';
5
 import JitsiMeetJS, { browser } from '../lib-jitsi-meet';
7
 import { ReducerRegistry } from '../redux';
6
 import { ReducerRegistry } from '../redux';
8
 import { PersistenceRegistry } from '../storage';
7
 import { PersistenceRegistry } from '../storage';

+ 1
- 1
react/features/calendar-sync/middleware.js Ver arquivo

3
 import md5 from 'js-md5';
3
 import md5 from 'js-md5';
4
 import RNCalendarEvents from 'react-native-calendar-events';
4
 import RNCalendarEvents from 'react-native-calendar-events';
5
 
5
 
6
-import { APP_WILL_MOUNT } from '../app';
6
+import { APP_WILL_MOUNT } from '../base/app';
7
 import { ADD_KNOWN_DOMAINS, addKnownDomains } from '../base/known-domains';
7
 import { ADD_KNOWN_DOMAINS, addKnownDomains } from '../base/known-domains';
8
 import { MiddlewareRegistry } from '../base/redux';
8
 import { MiddlewareRegistry } from '../base/redux';
9
 import { APP_LINK_SCHEME, parseURIString } from '../base/util';
9
 import { APP_LINK_SCHEME, parseURIString } from '../base/util';

+ 1
- 1
react/features/calendar-sync/reducer.js Ver arquivo

1
 // @flow
1
 // @flow
2
 
2
 
3
-import { APP_WILL_MOUNT } from '../app';
3
+import { APP_WILL_MOUNT } from '../base/app';
4
 import { ReducerRegistry, set } from '../base/redux';
4
 import { ReducerRegistry, set } from '../base/redux';
5
 import { PersistenceRegistry } from '../base/storage';
5
 import { PersistenceRegistry } from '../base/storage';
6
 
6
 

+ 1
- 1
react/features/chat/middleware.js Ver arquivo

1
 // @flow
1
 // @flow
2
 
2
 
3
-import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app';
3
+import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
4
 import { CONFERENCE_JOINED } from '../base/conference';
4
 import { CONFERENCE_JOINED } from '../base/conference';
5
 import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
5
 import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
6
 import { MiddlewareRegistry } from '../base/redux';
6
 import { MiddlewareRegistry } from '../base/redux';

+ 1
- 1
react/features/invite/functions.js Ver arquivo

1
 // @flow
1
 // @flow
2
 
2
 
3
-import { getAppProp } from '../app';
3
+import { getAppProp } from '../base/app';
4
 import { isLocalParticipantModerator } from '../base/participants';
4
 import { isLocalParticipantModerator } from '../base/participants';
5
 import { doGetJSON } from '../base/util';
5
 import { doGetJSON } from '../base/util';
6
 
6
 

+ 1
- 1
react/features/invite/middleware.any.js Ver arquivo

1
 // @flow
1
 // @flow
2
 
2
 
3
-import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app';
3
+import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
4
 import {
4
 import {
5
     CONFERENCE_JOINED
5
     CONFERENCE_JOINED
6
 } from '../base/conference';
6
 } from '../base/conference';

+ 1
- 1
react/features/invite/middleware.native.js Ver arquivo

3
 import i18next from 'i18next';
3
 import i18next from 'i18next';
4
 import { NativeEventEmitter, NativeModules } from 'react-native';
4
 import { NativeEventEmitter, NativeModules } from 'react-native';
5
 
5
 
6
+import { APP_WILL_MOUNT, APP_WILL_UNMOUNT, getAppProp } from '../base/app';
6
 import { MiddlewareRegistry } from '../base/redux';
7
 import { MiddlewareRegistry } from '../base/redux';
7
-import { APP_WILL_MOUNT, APP_WILL_UNMOUNT, getAppProp } from '../app';
8
 
8
 
9
 import { invite } from './actions';
9
 import { invite } from './actions';
10
 import {
10
 import {

+ 1
- 1
react/features/mobile/audio-mode/middleware.js Ver arquivo

2
 
2
 
3
 import { NativeModules } from 'react-native';
3
 import { NativeModules } from 'react-native';
4
 
4
 
5
-import { APP_WILL_MOUNT } from '../../app';
5
+import { APP_WILL_MOUNT } from '../../base/app';
6
 import {
6
 import {
7
     CONFERENCE_FAILED,
7
     CONFERENCE_FAILED,
8
     CONFERENCE_LEFT,
8
     CONFERENCE_LEFT,

+ 1
- 1
react/features/mobile/background/middleware.js Ver arquivo

3
 import { AppState } from 'react-native';
3
 import { AppState } from 'react-native';
4
 import type { Dispatch } from 'redux';
4
 import type { Dispatch } from 'redux';
5
 
5
 
6
-import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../app';
6
+import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../base/app';
7
 import { MiddlewareRegistry } from '../../base/redux';
7
 import { MiddlewareRegistry } from '../../base/redux';
8
 
8
 
9
 import {
9
 import {

+ 2
- 6
react/features/mobile/callkit/middleware.js Ver arquivo

3
 import uuid from 'uuid';
3
 import uuid from 'uuid';
4
 
4
 
5
 import { createTrackMutedEvent, sendAnalytics } from '../../analytics';
5
 import { createTrackMutedEvent, sendAnalytics } from '../../analytics';
6
-import {
7
-    APP_WILL_MOUNT,
8
-    APP_WILL_UNMOUNT,
9
-    appNavigate,
10
-    getName
11
-} from '../../app';
6
+import { appNavigate, getName } from '../../app';
7
+import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../base/app';
12
 import {
8
 import {
13
     CONFERENCE_FAILED,
9
     CONFERENCE_FAILED,
14
     CONFERENCE_LEFT,
10
     CONFERENCE_LEFT,

+ 1
- 1
react/features/mobile/external-api/middleware.js Ver arquivo

2
 
2
 
3
 import { NativeModules } from 'react-native';
3
 import { NativeModules } from 'react-native';
4
 
4
 
5
-import { getAppProp } from '../../app';
5
+import { getAppProp } from '../../base/app';
6
 import {
6
 import {
7
     CONFERENCE_FAILED,
7
     CONFERENCE_FAILED,
8
     CONFERENCE_JOINED,
8
     CONFERENCE_JOINED,

+ 1
- 1
react/features/mobile/full-screen/middleware.js Ver arquivo

3
 import { StatusBar } from 'react-native';
3
 import { StatusBar } from 'react-native';
4
 import { Immersive } from 'react-native-immersive';
4
 import { Immersive } from 'react-native-immersive';
5
 
5
 
6
-import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../app';
6
+import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../base/app';
7
 import { getCurrentConference } from '../../base/conference';
7
 import { getCurrentConference } from '../../base/conference';
8
 import { Platform } from '../../base/react';
8
 import { Platform } from '../../base/react';
9
 import { MiddlewareRegistry, StateListenerRegistry } from '../../base/redux';
9
 import { MiddlewareRegistry, StateListenerRegistry } from '../../base/redux';

+ 1
- 1
react/features/mobile/image-cache/middleware.js Ver arquivo

1
 /* @flow */
1
 /* @flow */
2
 
2
 
3
-import { APP_WILL_MOUNT } from '../../app';
3
+import { APP_WILL_MOUNT } from '../../base/app';
4
 import {
4
 import {
5
     getAvatarURL,
5
     getAvatarURL,
6
     getLocalParticipant,
6
     getLocalParticipant,

+ 1
- 1
react/features/mobile/network-activity/middleware.js Ver arquivo

2
 
2
 
3
 import XHRInterceptor from 'react-native/Libraries/Network/XHRInterceptor';
3
 import XHRInterceptor from 'react-native/Libraries/Network/XHRInterceptor';
4
 
4
 
5
-import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../app';
5
+import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../base/app';
6
 import { MiddlewareRegistry } from '../../base/redux';
6
 import { MiddlewareRegistry } from '../../base/redux';
7
 
7
 
8
 import {
8
 import {

+ 1
- 1
react/features/mobile/picture-in-picture/actions.js Ver arquivo

2
 
2
 
3
 import { NativeModules } from 'react-native';
3
 import { NativeModules } from 'react-native';
4
 
4
 
5
-import { getAppProp } from '../../app';
5
+import { getAppProp } from '../../base/app';
6
 import { Platform } from '../../base/react';
6
 import { Platform } from '../../base/react';
7
 
7
 
8
 import { ENTER_PICTURE_IN_PICTURE } from './actionTypes';
8
 import { ENTER_PICTURE_IN_PICTURE } from './actionTypes';

+ 1
- 1
react/features/mobile/picture-in-picture/components/PictureInPictureButton.js Ver arquivo

2
 
2
 
3
 import { connect } from 'react-redux';
3
 import { connect } from 'react-redux';
4
 
4
 
5
-import { getAppProp } from '../../../app';
5
+import { getAppProp } from '../../../base/app';
6
 import { translate } from '../../../base/i18n';
6
 import { translate } from '../../../base/i18n';
7
 import { AbstractButton } from '../../../base/toolbox';
7
 import { AbstractButton } from '../../../base/toolbox';
8
 import type { AbstractButtonProps } from '../../../base/toolbox';
8
 import type { AbstractButtonProps } from '../../../base/toolbox';

+ 1
- 1
react/features/recent-list/middleware.js Ver arquivo

1
 // @flow
1
 // @flow
2
 
2
 
3
-import { APP_WILL_MOUNT } from '../app';
3
+import { APP_WILL_MOUNT } from '../base/app';
4
 import { CONFERENCE_WILL_LEAVE, SET_ROOM } from '../base/conference';
4
 import { CONFERENCE_WILL_LEAVE, SET_ROOM } from '../base/conference';
5
 import { addKnownDomains } from '../base/known-domains';
5
 import { addKnownDomains } from '../base/known-domains';
6
 import { MiddlewareRegistry } from '../base/redux';
6
 import { MiddlewareRegistry } from '../base/redux';

+ 1
- 1
react/features/recent-list/reducer.js Ver arquivo

1
 // @flow
1
 // @flow
2
 
2
 
3
-import { APP_WILL_MOUNT } from '../app';
3
+import { APP_WILL_MOUNT } from '../base/app';
4
 import { getURLWithoutParamsNormalized } from '../base/connection';
4
 import { getURLWithoutParamsNormalized } from '../base/connection';
5
 import { ReducerRegistry } from '../base/redux';
5
 import { ReducerRegistry } from '../base/redux';
6
 import { PersistenceRegistry } from '../base/storage';
6
 import { PersistenceRegistry } from '../base/storage';

+ 1
- 2
react/features/recording/middleware.js Ver arquivo

1
 /* @flow */
1
 /* @flow */
2
 
2
 
3
+import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
3
 import { CONFERENCE_WILL_JOIN, getCurrentConference } from '../base/conference';
4
 import { CONFERENCE_WILL_JOIN, getCurrentConference } from '../base/conference';
4
 import JitsiMeetJS, {
5
 import JitsiMeetJS, {
5
     JitsiConferenceEvents,
6
     JitsiConferenceEvents,
13
     unregisterSound
14
     unregisterSound
14
 } from '../base/sounds';
15
 } from '../base/sounds';
15
 
16
 
16
-import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app';
17
-
18
 import {
17
 import {
19
     clearRecordingSessions,
18
     clearRecordingSessions,
20
     hidePendingRecordingNotification,
19
     hidePendingRecordingNotification,

+ 1
- 1
react/features/welcome/functions.js Ver arquivo

1
 // @flow
1
 // @flow
2
 
2
 
3
-import { getAppProp } from '../app';
3
+import { getAppProp } from '../base/app';
4
 import { toState } from '../base/redux';
4
 import { toState } from '../base/redux';
5
 
5
 
6
 declare var APP: Object;
6
 declare var APP: Object;

Carregando…
Cancelar
Salvar