Explorar el Código

rn,responsive-ui: refactor dimensions detection

Use a dimensions detecting root component. The Dimensions module does not
measure the app's view size, but the Window, which may not be the same, for
example on iOS when PiP is used.

Also refactor the aspect ratio wrap component since it can be taken directly
from the store.

Last, remove the use of DimensionsDetector on LargeVideo and TileView since they
occupy the full-screen anyway.

Fixes PiP mode on iOS.
master
Saúl Ibarra Corretgé hace 4 años
padre
commit
d740752522

+ 35
- 1
react/features/app/components/App.native.js Ver fichero

@@ -9,7 +9,7 @@ import { DialogContainer } from '../../base/dialog';
9 9
 import { CALL_INTEGRATION_ENABLED, updateFlags } from '../../base/flags';
10 10
 import '../../base/jwt';
11 11
 import { Platform } from '../../base/react';
12
-import '../../base/responsive-ui';
12
+import { DimensionsDetector, clientResized } from '../../base/responsive-ui';
13 13
 import { updateSettings } from '../../base/settings';
14 14
 import '../../google-api';
15 15
 import '../../mobile/audio-mode';
@@ -78,6 +78,9 @@ export class App extends AbstractApp {
78 78
         // This will effectively kill the app. In accord with the Web, do not
79 79
         // kill the app.
80 80
         this._maybeDisableExceptionsManager();
81
+
82
+        // Bind event handler so it is only bound once per instance.
83
+        this._onDimensionsChanged = this._onDimensionsChanged.bind(this);
81 84
     }
82 85
 
83 86
     /**
@@ -107,6 +110,21 @@ export class App extends AbstractApp {
107 110
         });
108 111
     }
109 112
 
113
+    /**
114
+     * Overrides the parent method to inject {@link DimensionsDetector} as
115
+     * the top most component.
116
+     *
117
+     * @override
118
+     */
119
+    _createMainElement(component, props) {
120
+        return (
121
+            <DimensionsDetector
122
+                onDimensionsChanged = { this._onDimensionsChanged }>
123
+                { super._createMainElement(component, props) }
124
+            </DimensionsDetector>
125
+        );
126
+    }
127
+
110 128
     /**
111 129
      * Attempts to disable the use of React Native
112 130
      * {@link ExceptionsManager#handleException} on platforms and in
@@ -144,6 +162,22 @@ export class App extends AbstractApp {
144 162
         }
145 163
     }
146 164
 
165
+    _onDimensionsChanged: (width: number, height: number) => void;
166
+
167
+    /**
168
+     * Updates the known available size for the app to occupy.
169
+     *
170
+     * @param {number} width - The component's current width.
171
+     * @param {number} height - The component's current height.
172
+     * @private
173
+     * @returns {void}
174
+     */
175
+    _onDimensionsChanged(width: number, height: number) {
176
+        const { dispatch } = this.state.store;
177
+
178
+        dispatch(clientResized(width, height));
179
+    }
180
+
147 181
     /**
148 182
      * Renders the platform specific dialog container.
149 183
      *

+ 0
- 70
react/features/base/responsive-ui/components/AspectRatioAware.js Ver fichero

@@ -1,70 +0,0 @@
1
-// @flow
2
-
3
-import React, { Component } from 'react';
4
-
5
-import { connect } from '../../redux';
6
-import { ASPECT_RATIO_NARROW, ASPECT_RATIO_WIDE } from '../constants';
7
-
8
-/**
9
- * The type of the React {@code Component} props of {@link AspectRatioAware}.
10
- */
11
-type Props = {
12
-    aspectRatio: ASPECT_RATIO_NARROW | ASPECT_RATIO_WIDE
13
-};
14
-
15
-/**
16
- * Determines whether a specific React {@code Component} decorated into an
17
- * {@link AspectRatioAware} has {@link ASPECT_RATIO_NARROW} as the value of its
18
- * {@code aspectRatio} React prop.
19
- *
20
- * @param {AspectRatioAware} component - An {@link AspectRatioAware} which may
21
- * have an {@code aspectRatio} React prop.
22
- * @returns {boolean}
23
- */
24
-export function isNarrowAspectRatio(component: React$Component<*>) {
25
-    return component.props.aspectRatio === ASPECT_RATIO_NARROW;
26
-}
27
-
28
-/**
29
- * Decorates a specific React {@code Component} class into an
30
- * {@link AspectRatioAware} which provides the React prop {@code aspectRatio}
31
- * updated on each redux state change.
32
- *
33
- * @param {Class<React$Component>} WrappedComponent - A React {@code Component}
34
- * class to be wrapped.
35
- * @returns {AspectRatioAwareWrapper}
36
- */
37
-export function makeAspectRatioAware(
38
-        WrappedComponent: Class<React$Component<*>>
39
-): Class<React$Component<*>> {
40
-    /**
41
-     * Renders {@code WrappedComponent} with the React prop {@code aspectRatio}.
42
-     */
43
-    class AspectRatioAware extends Component<Props> {
44
-        /**
45
-         * Implement's React render method to wrap the nested component.
46
-         *
47
-         * @returns {React$Element}
48
-         */
49
-        render(): React$Element<*> {
50
-            return <WrappedComponent { ...this.props } />;
51
-        }
52
-    }
53
-
54
-    return connect(_mapStateToProps)(AspectRatioAware);
55
-}
56
-
57
-/**
58
- * Maps (parts of) the redux state to {@link AspectRatioAware} props.
59
- *
60
- * @param {Object} state - The whole redux state.
61
- * @private
62
- * @returns {{
63
- *     aspectRatio: Symbol
64
- * }}
65
- */
66
-function _mapStateToProps(state) {
67
-    return {
68
-        aspectRatio: state['features/base/responsive-ui'].aspectRatio
69
-    };
70
-}

+ 2
- 6
react/features/base/responsive-ui/components/DimensionsDetector.native.js Ver fichero

@@ -1,13 +1,9 @@
1 1
 // @flow
2 2
 
3 3
 import React, { PureComponent } from 'react';
4
-import { View } from 'react-native';
4
+import { StyleSheet, View } from 'react-native';
5 5
 
6
-import styles from './styles';
7 6
 
8
-/**
9
- * AspectRatioDetector component's property types.
10
- */
11 7
 type Props = {
12 8
 
13 9
     /**
@@ -64,7 +60,7 @@ export default class DimensionsDetector extends PureComponent<Props> {
64 60
         return (
65 61
             <View
66 62
                 onLayout = { this._onLayout }
67
-                style = { styles.dimensionsDetector } >
63
+                style = { StyleSheet.absoluteFillObject } >
68 64
                 { this.props.children }
69 65
             </View>
70 66
         );

+ 0
- 1
react/features/base/responsive-ui/components/index.js Ver fichero

@@ -1,2 +1 @@
1
-export * from './AspectRatioAware';
2 1
 export { default as DimensionsDetector } from './DimensionsDetector';

+ 0
- 14
react/features/base/responsive-ui/components/styles.js Ver fichero

@@ -1,14 +0,0 @@
1
-import { createStyleSheet } from '../../styles';
2
-
3
-/**
4
- * The styles of the feature base/responsive-ui.
5
- */
6
-export default createStyleSheet({
7
-    /**
8
-     * The style of {@link DimensionsDetector} used on react-native.
9
-     */
10
-    dimensionsDetector: {
11
-        alignSelf: 'stretch',
12
-        flex: 1
13
-    }
14
-});

+ 7
- 59
react/features/base/responsive-ui/middleware.native.js Ver fichero

@@ -1,16 +1,10 @@
1 1
 // @flow
2 2
 
3
-import { Dimensions } from 'react-native';
4
-
5
-import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../base/app';
6 3
 import { MiddlewareRegistry } from '../../base/redux';
7 4
 
5
+import { CLIENT_RESIZED } from './actionTypes';
8 6
 import { setAspectRatio, setReducedUI } from './actions';
9 7
 
10
-/**
11
- * Dimensions change handler.
12
- */
13
-let handler;
14 8
 
15 9
 /**
16 10
  * Middleware that handles widnow dimension changes and updates the aspect ratio and
@@ -19,65 +13,19 @@ let handler;
19 13
  * @param {Store} store - The redux store.
20 14
  * @returns {Function}
21 15
  */
22
-MiddlewareRegistry.register(store => next => action => {
16
+MiddlewareRegistry.register(({ dispatch }) => next => action => {
23 17
     const result = next(action);
24 18
 
25 19
     switch (action.type) {
26
-    case APP_WILL_UNMOUNT: {
27
-        _appWillUnmount();
20
+    case CLIENT_RESIZED: {
21
+        const { clientWidth: width, clientHeight: height } = action;
22
+
23
+        dispatch(setAspectRatio(width, height));
24
+        dispatch(setReducedUI(width, height));
28 25
         break;
29 26
     }
30
-    case APP_WILL_MOUNT:
31
-        _appWillMount(store);
32
-        break;
33 27
 
34 28
     }
35 29
 
36 30
     return result;
37 31
 });
38
-
39
-/**
40
- * Notifies this feature that the action {@link APP_WILL_MOUNT} is being
41
- * dispatched within a specific redux {@code store}.
42
- *
43
- * @param {Store} store - The redux store in which the specified {@code action}
44
- * is being dispatched.
45
- * @private
46
- * @returns {void}
47
- */
48
-function _appWillMount(store) {
49
-    handler = dim => {
50
-        _onDimensionsChange(dim, store);
51
-    };
52
-
53
-    Dimensions.addEventListener('change', handler);
54
-}
55
-
56
-/**
57
- * Notifies this feature that the action {@link APP_WILL_UNMOUNT} is being
58
- * dispatched within a specific redux {@code store}.
59
- *
60
- * @private
61
- * @returns {void}
62
- */
63
-function _appWillUnmount() {
64
-    Dimensions.removeEventListener('change', handler);
65
-
66
-    handler = undefined;
67
-}
68
-
69
-/**
70
- * Handles window dimension changes.
71
- *
72
- * @param {Object} dimensions - The new dimensions.
73
- * @param {Store} store - The redux store.
74
- * @private
75
- * @returns {void}
76
- */
77
-function _onDimensionsChange(dimensions, store) {
78
-    const { width, height } = dimensions.window;
79
-    const { dispatch } = store;
80
-
81
-    dispatch(setAspectRatio(width, height));
82
-    dispatch(setReducedUI(width, height));
83
-}

+ 0
- 1
react/features/base/responsive-ui/reducer.js Ver fichero

@@ -23,7 +23,6 @@ const DEFAULT_STATE = {
23 23
 ReducerRegistry.register('features/base/responsive-ui', (state = DEFAULT_STATE, action) => {
24 24
     switch (action.type) {
25 25
     case CLIENT_RESIZED: {
26
-
27 26
         return {
28 27
             ...state,
29 28
             clientWidth: action.clientWidth,

+ 15
- 78
react/features/conference/components/native/Conference.js Ver fichero

@@ -8,10 +8,7 @@ import { appNavigate } from '../../../app';
8 8
 import { PIP_ENABLED, getFeatureFlag } from '../../../base/flags';
9 9
 import { Container, LoadingIndicator, TintedView } from '../../../base/react';
10 10
 import { connect } from '../../../base/redux';
11
-import {
12
-    isNarrowAspectRatio,
13
-    makeAspectRatioAware
14
-} from '../../../base/responsive-ui';
11
+import { ASPECT_RATIO_NARROW } from '../../../base/responsive-ui/constants';
15 12
 import { TestConnectionInfo } from '../../../base/testing';
16 13
 import { ConferenceNotification, isCalendarEnabled } from '../../../calendar-sync';
17 14
 import { Chat } from '../../../chat';
@@ -45,10 +42,13 @@ import styles, { NAVBAR_GRADIENT_COLORS } from './styles';
45 42
  */
46 43
 type Props = AbstractProps & {
47 44
 
45
+    /**
46
+     * Application's aspect ratio.
47
+     */
48
+    _aspectRatio: Symbol,
49
+
48 50
     /**
49 51
      * Wherther the calendar feature is enabled or not.
50
-     *
51
-     * @private
52 52
      */
53 53
     _calendarEnabled: boolean,
54 54
 
@@ -57,15 +57,11 @@ type Props = AbstractProps & {
57 57
      * conference which includes establishing the XMPP connection and then
58 58
      * joining the room. If truthy, then an activity/loading indicator will be
59 59
      * rendered.
60
-     *
61
-     * @private
62 60
      */
63 61
     _connecting: boolean,
64 62
 
65 63
     /**
66 64
      * Set to {@code true} when the filmstrip is currently visible.
67
-     *
68
-     * @private
69 65
      */
70 66
     _filmstripVisible: boolean,
71 67
 
@@ -76,34 +72,17 @@ type Props = AbstractProps & {
76 72
 
77 73
     /**
78 74
      * Whether Picture-in-Picture is enabled.
79
-     *
80
-     * @private
81 75
      */
82 76
     _pictureInPictureEnabled: boolean,
83 77
 
84 78
     /**
85 79
      * The indicator which determines whether the UI is reduced (to accommodate
86 80
      * smaller display areas).
87
-     *
88
-     * @private
89 81
      */
90 82
     _reducedUI: boolean,
91 83
 
92
-    /**
93
-     * The handler which dispatches the (redux) action {@link setToolboxVisible}
94
-     * to show/hide the {@link Toolbox}.
95
-     *
96
-     * @param {boolean} visible - {@code true} to show the {@code Toolbox} or
97
-     * {@code false} to hide it.
98
-     * @private
99
-     * @returns {void}
100
-     */
101
-    _setToolboxVisible: Function,
102
-
103 84
     /**
104 85
      * The indicator which determines whether the Toolbox is visible.
105
-     *
106
-     * @private
107 86
      */
108 87
     _toolboxVisible: boolean,
109 88
 
@@ -249,6 +228,7 @@ class Conference extends AbstractConference<Props, *> {
249 228
      */
250 229
     _renderContent() {
251 230
         const {
231
+            _aspectRatio,
252 232
             _connecting,
253 233
             _filmstripVisible,
254 234
             _largeVideoParticipantId,
@@ -257,7 +237,8 @@ class Conference extends AbstractConference<Props, *> {
257 237
             _toolboxVisible
258 238
         } = this.props;
259 239
         const showGradient = _toolboxVisible;
260
-        const applyGradientStretching = _filmstripVisible && isNarrowAspectRatio(this) && !_shouldDisplayTileView;
240
+        const applyGradientStretching
241
+            = _filmstripVisible && _aspectRatio === ASPECT_RATIO_NARROW && !_shouldDisplayTileView;
261 242
 
262 243
         if (_reducedUI) {
263 244
             return this._renderContentForReducedUi();
@@ -393,7 +374,9 @@ class Conference extends AbstractConference<Props, *> {
393 374
         // flex layout. The only option that seemed to limit the notification's
394 375
         // size was explicit 'width' value which is not better than the margin
395 376
         // added here.
396
-        if (this.props._filmstripVisible && !isNarrowAspectRatio(this)) {
377
+        const { _aspectRatio, _filmstripVisible } = this.props;
378
+
379
+        if (_filmstripVisible && _aspectRatio !== ASPECT_RATIO_NARROW) {
397 380
             notificationsStyle.marginRight = FILMSTRIP_SIZE;
398 381
         }
399 382
 
@@ -433,7 +416,7 @@ function _mapStateToProps(state) {
433 416
         joining,
434 417
         leaving
435 418
     } = state['features/base/conference'];
436
-    const { reducedUI } = state['features/base/responsive-ui'];
419
+    const { aspectRatio, reducedUI } = state['features/base/responsive-ui'];
437 420
 
438 421
     // XXX There is a window of time between the successful establishment of the
439 422
     // XMPP connection and the subsequent commencement of joining the MUC during
@@ -449,61 +432,15 @@ function _mapStateToProps(state) {
449 432
 
450 433
     return {
451 434
         ...abstractMapStateToProps(state),
452
-
453
-        /**
454
-         * Wherther the calendar feature is enabled or not.
455
-         *
456
-         * @private
457
-         * @type {boolean}
458
-         */
435
+        _aspectRatio: aspectRatio,
459 436
         _calendarEnabled: isCalendarEnabled(state),
460
-
461
-        /**
462
-         * The indicator which determines that we are still connecting to the
463
-         * conference which includes establishing the XMPP connection and then
464
-         * joining the room. If truthy, then an activity/loading indicator will
465
-         * be rendered.
466
-         *
467
-         * @private
468
-         * @type {boolean}
469
-         */
470 437
         _connecting: Boolean(connecting_),
471
-
472
-        /**
473
-         * Is {@code true} when the filmstrip is currently visible.
474
-         */
475 438
         _filmstripVisible: isFilmstripVisible(state),
476
-
477
-        /**
478
-         * The ID of the participant currently on stage.
479
-         */
480 439
         _largeVideoParticipantId: state['features/large-video'].participantId,
481
-
482
-        /**
483
-         * Whether Picture-in-Picture is enabled.
484
-         *
485
-         * @private
486
-         * @type {boolean}
487
-         */
488 440
         _pictureInPictureEnabled: getFeatureFlag(state, PIP_ENABLED),
489
-
490
-        /**
491
-         * The indicator which determines whether the UI is reduced (to
492
-         * accommodate smaller display areas).
493
-         *
494
-         * @private
495
-         * @type {boolean}
496
-         */
497 441
         _reducedUI: reducedUI,
498
-
499
-        /**
500
-         * The indicator which determines whether the Toolbox is visible.
501
-         *
502
-         * @private
503
-         * @type {boolean}
504
-         */
505 442
         _toolboxVisible: isToolboxVisible(state)
506 443
     };
507 444
 }
508 445
 
509
-export default connect(_mapStateToProps)(makeAspectRatioAware(Conference));
446
+export default connect(_mapStateToProps)(Conference);

+ 15
- 11
react/features/conference/components/native/Labels.js Ver fichero

@@ -5,10 +5,7 @@ import { TouchableOpacity, View } from 'react-native';
5 5
 
6 6
 import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
7 7
 import { connect } from '../../../base/redux';
8
-import {
9
-    isNarrowAspectRatio,
10
-    makeAspectRatioAware
11
-} from '../../../base/responsive-ui';
8
+import { ASPECT_RATIO_WIDE } from '../../../base/responsive-ui/constants';
12 9
 import {
13 10
     RecordingExpandedLabel
14 11
 } from '../../../recording';
@@ -29,14 +26,19 @@ import styles from './styles';
29 26
 type Props = AbstractLabelsProps & {
30 27
 
31 28
     /**
32
-     * Function to translate i18n labels.
29
+     * Application's aspect ratio.
33 30
      */
34
-    t: Function,
31
+    _aspectRatio: Symbol,
35 32
 
36 33
     /**
37 34
      * True if the labels should be visible, false otherwise.
38 35
      */
39
-    _visible: boolean
36
+    _visible: boolean,
37
+
38
+    /**
39
+     * Function to translate i18n labels.
40
+     */
41
+    t: Function
40 42
 };
41 43
 
42 44
 type State = {
@@ -149,12 +151,13 @@ class Labels extends AbstractLabels<Props, State> {
149 151
      * @inheritdoc
150 152
      */
151 153
     render() {
152
-        if (!this.props._visible) {
154
+        const { _aspectRatio, _filmstripVisible, _visible } = this.props;
155
+
156
+        if (!_visible) {
153 157
             return null;
154 158
         }
155 159
 
156
-        const wide = !isNarrowAspectRatio(this);
157
-        const { _filmstripVisible } = this.props;
160
+        const wide = _aspectRatio === ASPECT_RATIO_WIDE;
158 161
 
159 162
         return (
160 163
             <View
@@ -354,8 +357,9 @@ class Labels extends AbstractLabels<Props, State> {
354 357
 function _mapStateToProps(state) {
355 358
     return {
356 359
         ..._abstractMapStateToProps(state),
360
+        _aspectRatio: state['features/base/responsive-ui'].aspectRatio,
357 361
         _visible: !shouldDisplayNotifications(state)
358 362
     };
359 363
 }
360 364
 
361
-export default connect(_mapStateToProps)(makeAspectRatioAware(Labels));
365
+export default connect(_mapStateToProps)(Labels);

+ 1
- 2
react/features/conference/components/web/Labels.js Ver fichero

@@ -41,8 +41,7 @@ class Labels extends AbstractLabels<Props, State> {
41 41
      */
42 42
     static getDerivedStateFromProps(props: Props, prevState: State) {
43 43
         return {
44
-            filmstripBecomingVisible: !prevState.filmstripBecomingVisible
45
-                && props._filmstripVisible
44
+            filmstripBecomingVisible: !prevState.filmstripBecomingVisible && props._filmstripVisible
46 45
         };
47 46
     }
48 47
 

+ 24
- 58
react/features/filmstrip/components/native/Filmstrip.js Ver fichero

@@ -5,10 +5,7 @@ import { ScrollView } from 'react-native';
5 5
 
6 6
 import { Container, Platform } from '../../../base/react';
7 7
 import { connect } from '../../../base/redux';
8
-import {
9
-    isNarrowAspectRatio,
10
-    makeAspectRatioAware
11
-} from '../../../base/responsive-ui';
8
+import { ASPECT_RATIO_NARROW } from '../../../base/responsive-ui/constants';
12 9
 import { isFilmstripVisible } from '../../functions';
13 10
 
14 11
 import LocalThumbnail from './LocalThumbnail';
@@ -20,24 +17,23 @@ import styles from './styles';
20 17
  */
21 18
 type Props = {
22 19
 
20
+    /**
21
+     * Application's aspect ratio.
22
+     */
23
+    _aspectRatio: Symbol,
24
+
23 25
     /**
24 26
      * The indicator which determines whether the filmstrip is enabled.
25
-     *
26
-     * @private
27 27
      */
28 28
     _enabled: boolean,
29 29
 
30 30
     /**
31 31
      * The participants in the conference.
32
-     *
33
-     * @private
34 32
      */
35 33
     _participants: Array<any>,
36 34
 
37 35
     /**
38 36
      * The indicator which determines whether the filmstrip is visible.
39
-     *
40
-     * @private
41 37
      */
42 38
     _visible: boolean
43 39
 };
@@ -90,40 +86,36 @@ class Filmstrip extends Component<Props> {
90 86
      * @returns {ReactElement}
91 87
      */
92 88
     render() {
93
-        if (!this.props._enabled) {
89
+        const { _aspectRatio, _enabled, _participants, _visible } = this.props;
90
+
91
+        if (!_enabled) {
94 92
             return null;
95 93
         }
96 94
 
97
-        const isNarrowAspectRatio_ = isNarrowAspectRatio(this);
98
-        const filmstripStyle
99
-            = isNarrowAspectRatio_
100
-                ? styles.filmstripNarrow
101
-                : styles.filmstripWide;
95
+        const isNarrowAspectRatio = _aspectRatio === ASPECT_RATIO_NARROW;
96
+        const filmstripStyle = isNarrowAspectRatio ? styles.filmstripNarrow : styles.filmstripWide;
102 97
 
103 98
         return (
104 99
             <Container
105 100
                 style = { filmstripStyle }
106
-                visible = { this.props._visible }>
101
+                visible = { _visible }>
107 102
                 {
108 103
                     this._separateLocalThumbnail
109
-                        && !isNarrowAspectRatio_
104
+                        && !isNarrowAspectRatio
110 105
                         && <LocalThumbnail />
111 106
                 }
112 107
                 <ScrollView
113
-                    horizontal = { isNarrowAspectRatio_ }
108
+                    horizontal = { isNarrowAspectRatio }
114 109
                     showsHorizontalScrollIndicator = { false }
115 110
                     showsVerticalScrollIndicator = { false }
116 111
                     style = { styles.scrollView } >
117 112
                     {
118
-                        !this._separateLocalThumbnail
119
-                            && !isNarrowAspectRatio_
113
+                        !this._separateLocalThumbnail && !isNarrowAspectRatio
120 114
                             && <LocalThumbnail />
121 115
                     }
122 116
                     {
123 117
 
124
-                        this._sort(
125
-                                this.props._participants,
126
-                                isNarrowAspectRatio_)
118
+                        this._sort(_participants, isNarrowAspectRatio)
127 119
                             .map(p => (
128 120
                                 <Thumbnail
129 121
                                     key = { p.id }
@@ -131,14 +123,12 @@ class Filmstrip extends Component<Props> {
131 123
 
132 124
                     }
133 125
                     {
134
-                        !this._separateLocalThumbnail
135
-                            && isNarrowAspectRatio_
126
+                        !this._separateLocalThumbnail && isNarrowAspectRatio
136 127
                             && <LocalThumbnail />
137 128
                     }
138 129
                 </ScrollView>
139 130
                 {
140
-                    this._separateLocalThumbnail
141
-                        && isNarrowAspectRatio_
131
+                    this._separateLocalThumbnail && isNarrowAspectRatio
142 132
                         && <LocalThumbnail />
143 133
                 }
144 134
             </Container>
@@ -150,13 +140,13 @@ class Filmstrip extends Component<Props> {
150 140
      *
151 141
      * @param {Participant[]} participants - The array of {@code Participant}s
152 142
      * to sort in display order.
153
-     * @param {boolean} isNarrowAspectRatio_ - Indicates if the aspect ratio is
143
+     * @param {boolean} isNarrowAspectRatio - Indicates if the aspect ratio is
154 144
      * wide or narrow.
155 145
      * @private
156 146
      * @returns {Participant[]} A new array containing the elements of the
157 147
      * specified {@code participants} array sorted in display order.
158 148
      */
159
-    _sort(participants, isNarrowAspectRatio_) {
149
+    _sort(participants, isNarrowAspectRatio) {
160 150
         // XXX Array.prototype.sort() is not appropriate because (1) it operates
161 151
         // in place and (2) it is not necessarily stable.
162 152
 
@@ -164,7 +154,7 @@ class Filmstrip extends Component<Props> {
164 154
             ...participants
165 155
         ];
166 156
 
167
-        if (isNarrowAspectRatio_) {
157
+        if (isNarrowAspectRatio) {
168 158
             // When the narrow aspect ratio is used, we want to have the remote
169 159
             // participants from right to left with the newest added/joined to
170 160
             // the leftmost side. The local participant is the leftmost item.
@@ -180,42 +170,18 @@ class Filmstrip extends Component<Props> {
180 170
  *
181 171
  * @param {Object} state - The redux state.
182 172
  * @private
183
- * @returns {{
184
- *     _participants: Participant[],
185
- *     _visible: boolean
186
- * }}
173
+ * @returns {Props}
187 174
  */
188 175
 function _mapStateToProps(state) {
189 176
     const participants = state['features/base/participants'];
190 177
     const { enabled } = state['features/filmstrip'];
191 178
 
192 179
     return {
193
-        /**
194
-         * The indicator which determines whether the filmstrip is enabled.
195
-         *
196
-         * @private
197
-         * @type {boolean}
198
-         */
180
+        _aspectRatio: state['features/base/responsive-ui'].aspectRatio,
199 181
         _enabled: enabled,
200
-
201
-        /**
202
-         * The remote participants in the conference.
203
-         *
204
-         * @private
205
-         * @type {Participant[]}
206
-         */
207 182
         _participants: participants.filter(p => !p.local),
208
-
209
-        /**
210
-         * The indicator which determines whether the filmstrip is visible. The
211
-         * mobile/react-native Filmstrip is visible when there are at least 2
212
-         * participants in the conference (including the local one).
213
-         *
214
-         * @private
215
-         * @type {boolean}
216
-         */
217 183
         _visible: isFilmstripVisible(state)
218 184
     };
219 185
 }
220 186
 
221
-export default connect(_mapStateToProps)(makeAspectRatioAware(Filmstrip));
187
+export default connect(_mapStateToProps)(Filmstrip);

+ 49
- 94
react/features/filmstrip/components/native/TileView.js Ver fichero

@@ -13,11 +13,7 @@ import {
13 13
     setMaxReceiverVideoQuality
14 14
 } from '../../../base/conference';
15 15
 import { connect } from '../../../base/redux';
16
-import {
17
-    DimensionsDetector,
18
-    isNarrowAspectRatio,
19
-    makeAspectRatioAware
20
-} from '../../../base/responsive-ui';
16
+import { ASPECT_RATIO_NARROW } from '../../../base/responsive-ui/constants';
21 17
 
22 18
 import Thumbnail from './Thumbnail';
23 19
 import styles from './styles';
@@ -28,35 +24,34 @@ import styles from './styles';
28 24
 type Props = {
29 25
 
30 26
     /**
31
-     * The participants in the conference.
27
+     * Application's aspect ratio.
32 28
      */
33
-    _participants: Array<Object>,
29
+    _aspectRatio: Symbol,
34 30
 
35 31
     /**
36
-     * Invoked to update the receiver video quality.
32
+     * Application's viewport height.
37 33
      */
38
-    dispatch: Dispatch<any>,
34
+    _height: number,
39 35
 
40 36
     /**
41
-     * Callback to invoke when tile view is tapped.
37
+     * The participants in the conference.
42 38
      */
43
-    onClick: Function
44
-};
39
+    _participants: Array<Object>,
45 40
 
46
-/**
47
- * The type of the React {@link Component} state of {@link TileView}.
48
- */
49
-type State = {
41
+    /**
42
+     * Application's viewport height.
43
+     */
44
+    _width: number,
50 45
 
51 46
     /**
52
-     * The available width for {@link TileView} to occupy.
47
+     * Invoked to update the receiver video quality.
53 48
      */
54
-    height: number,
49
+    dispatch: Dispatch<any>,
55 50
 
56 51
     /**
57
-     * The available height for {@link TileView} to occupy.
52
+     * Callback to invoke when tile view is tapped.
58 53
      */
59
-    width: number
54
+    onClick: Function
60 55
 };
61 56
 
62 57
 /**
@@ -82,25 +77,7 @@ const TILE_ASPECT_RATIO = 1;
82 77
  *
83 78
  * @extends Component
84 79
  */
85
-class TileView extends Component<Props, State> {
86
-    state = {
87
-        height: 0,
88
-        width: 0
89
-    };
90
-
91
-    /**
92
-     * Initializes a new {@code TileView} instance.
93
-     *
94
-     * @param {Object} props - The read-only properties with which the new
95
-     * instance is to be initialized.
96
-     */
97
-    constructor(props: Props) {
98
-        super(props);
99
-
100
-        // Bind event handler so it is only bound once per instance.
101
-        this._onDimensionsChanged = this._onDimensionsChanged.bind(this);
102
-    }
103
-
80
+class TileView extends Component<Props> {
104 81
     /**
105 82
      * Implements React's {@link Component#componentDidMount}.
106 83
      *
@@ -126,32 +103,27 @@ class TileView extends Component<Props, State> {
126 103
      * @returns {ReactElement}
127 104
      */
128 105
     render() {
129
-        const { onClick } = this.props;
130
-        const { height, width } = this.state;
131
-        const rowElements = this._groupIntoRows(
132
-            this._renderThumbnails(), this._getColumnCount());
106
+        const { _height, _width, onClick } = this.props;
107
+        const rowElements = this._groupIntoRows(this._renderThumbnails(), this._getColumnCount());
133 108
 
134 109
         return (
135
-            <DimensionsDetector
136
-                onDimensionsChanged = { this._onDimensionsChanged }>
137
-                <ScrollView
138
-                    style = {{
139
-                        ...styles.tileView,
140
-                        height,
141
-                        width
142
-                    }}>
143
-                    <TouchableWithoutFeedback onPress = { onClick }>
144
-                        <View
145
-                            style = {{
146
-                                ...styles.tileViewRows,
147
-                                minHeight: height,
148
-                                minWidth: width
149
-                            }}>
150
-                            { rowElements }
151
-                        </View>
152
-                    </TouchableWithoutFeedback>
153
-                </ScrollView>
154
-            </DimensionsDetector>
110
+            <ScrollView
111
+                style = {{
112
+                    ...styles.tileView,
113
+                    height: _height,
114
+                    width: _width
115
+                }}>
116
+                <TouchableWithoutFeedback onPress = { onClick }>
117
+                    <View
118
+                        style = {{
119
+                            ...styles.tileViewRows,
120
+                            minHeight: _height,
121
+                            minWidth: _width
122
+                        }}>
123
+                        { rowElements }
124
+                    </View>
125
+                </TouchableWithoutFeedback>
126
+            </ScrollView>
155 127
         );
156 128
     }
157 129
 
@@ -167,7 +139,7 @@ class TileView extends Component<Props, State> {
167 139
         // For narrow view, tiles should stack on top of each other for a lonely
168 140
         // call and a 1:1 call. Otherwise tiles should be grouped into rows of
169 141
         // two.
170
-        if (isNarrowAspectRatio(this)) {
142
+        if (this.props._aspectRatio === ASPECT_RATIO_NARROW) {
171 143
             return participantCount >= 3 ? 2 : 1;
172 144
         }
173 145
 
@@ -209,19 +181,17 @@ class TileView extends Component<Props, State> {
209 181
      * @returns {Object}
210 182
      */
211 183
     _getTileDimensions() {
212
-        const { _participants } = this.props;
213
-        const { height, width } = this.state;
184
+        const { _height, _participants, _width } = this.props;
214 185
         const columns = this._getColumnCount();
215 186
         const participantCount = _participants.length;
216
-        const heightToUse = height - (MARGIN * 2);
217
-        const widthToUse = width - (MARGIN * 2);
187
+        const heightToUse = _height - (MARGIN * 2);
188
+        const widthToUse = _width - (MARGIN * 2);
218 189
         let tileWidth;
219 190
 
220 191
         // If there is going to be at least two rows, ensure that at least two
221 192
         // rows display fully on screen.
222 193
         if (participantCount / columns > 1) {
223
-            tileWidth
224
-                = Math.min(widthToUse / columns, heightToUse / 2);
194
+            tileWidth = Math.min(widthToUse / columns, heightToUse / 2);
225 195
         } else {
226 196
             tileWidth = Math.min(widthToUse / columns, heightToUse);
227 197
         }
@@ -247,8 +217,7 @@ class TileView extends Component<Props, State> {
247 217
 
248 218
         for (let i = 0; i < thumbnails.length; i++) {
249 219
             if (i % rowLength === 0) {
250
-                const thumbnailsInRow
251
-                    = thumbnails.slice(i, i + rowLength);
220
+                const thumbnailsInRow = thumbnails.slice(i, i + rowLength);
252 221
 
253 222
                 rowElements.push(
254 223
                     <View
@@ -263,23 +232,6 @@ class TileView extends Component<Props, State> {
263 232
         return rowElements;
264 233
     }
265 234
 
266
-    _onDimensionsChanged: (width: number, height: number) => void;
267
-
268
-    /**
269
-     * Updates the known available state for {@link TileView} to occupy.
270
-     *
271
-     * @param {number} width - The component's current width.
272
-     * @param {number} height - The component's current height.
273
-     * @private
274
-     * @returns {void}
275
-     */
276
-    _onDimensionsChanged(width: number, height: number) {
277
-        this.setState({
278
-            height,
279
-            width
280
-        });
281
-    }
282
-
283 235
     /**
284 236
      * Creates React Elements to display each participant in a thumbnail. Each
285 237
      * tile will be.
@@ -326,14 +278,17 @@ class TileView extends Component<Props, State> {
326 278
  *
327 279
  * @param {Object} state - The redux state.
328 280
  * @private
329
- * @returns {{
330
- *     _participants: Participant[]
331
- * }}
281
+ * @returns {Props}
332 282
  */
333 283
 function _mapStateToProps(state) {
284
+    const responsiveUi = state['features/base/responsive-ui'];
285
+
334 286
     return {
335
-        _participants: state['features/base/participants']
287
+        _aspectRatio: responsiveUi.aspectRatio,
288
+        _height: responsiveUi.clientHeight,
289
+        _participants: state['features/base/participants'],
290
+        _width: responsiveUi.clientWidth
336 291
     };
337 292
 }
338 293
 
339
-export default connect(_mapStateToProps)(makeAspectRatioAware(TileView));
294
+export default connect(_mapStateToProps)(TileView);

+ 36
- 46
react/features/large-video/components/LargeVideo.native.js Ver fichero

@@ -1,11 +1,10 @@
1 1
 // @flow
2 2
 
3
-import React, { Component } from 'react';
3
+import React, { PureComponent } from 'react';
4 4
 
5 5
 import { ColorSchemeRegistry } from '../../base/color-scheme';
6 6
 import { ParticipantView } from '../../base/participants';
7 7
 import { connect } from '../../base/redux';
8
-import { DimensionsDetector } from '../../base/responsive-ui';
9 8
 import { StyleType } from '../../base/styles';
10 9
 
11 10
 import { AVATAR_SIZE } from './styles';
@@ -15,6 +14,11 @@ import { AVATAR_SIZE } from './styles';
15 14
  */
16 15
 type Props = {
17 16
 
17
+    /**
18
+     * Application's viewport height.
19
+     */
20
+    _height: number,
21
+
18 22
     /**
19 23
      * The ID of the participant (to be) depicted by LargeVideo.
20 24
      *
@@ -27,6 +31,11 @@ type Props = {
27 31
      */
28 32
     _styles: StyleType,
29 33
 
34
+    /**
35
+     * Application's viewport height.
36
+     */
37
+    _width: number,
38
+
30 39
     /**
31 40
      * Callback to invoke when the {@code LargeVideo} is clicked/pressed.
32 41
      */
@@ -62,50 +71,33 @@ const DEFAULT_STATE = {
62 71
  *
63 72
  * @extends Component
64 73
  */
65
-class LargeVideo extends Component<Props, State> {
74
+class LargeVideo extends PureComponent<Props, State> {
66 75
     state = {
67 76
         ...DEFAULT_STATE
68 77
     };
69 78
 
70
-    /** Initializes a new {@code LargeVideo} instance.
71
-     *
72
-     * @param {Object} props - The read-only properties with which the new
73
-     * instance is to be initialized.
74
-     */
75
-    constructor(props: Props) {
76
-        super(props);
77
-
78
-        // Bind event handlers so they are only bound once per instance.
79
-        this._onDimensionsChanged = this._onDimensionsChanged.bind(this);
80
-    }
81
-
82
-    _onDimensionsChanged: (width: number, height: number) => void;
83
-
84 79
     /**
85
-     * Handle this component's dimension changes. In case we deem it's too
80
+     * Handles dimension changes. In case we deem it's too
86 81
      * small, the connectivity indicator won't be rendered and the avatar
87 82
      * will occupy the entirety of the available screen state.
88 83
      *
89
-     * @param {number} width - The component's current width.
90
-     * @param {number} height - The component's current height.
91
-     * @private
92
-     * @returns {void}
84
+     * @inheritdoc
93 85
      */
94
-    _onDimensionsChanged(width: number, height: number) {
86
+    static getDerivedStateFromProps(props: Props) {
87
+        const { _height, _width } = props;
88
+
95 89
         // Get the size, rounded to the nearest even number.
96
-        const size = 2 * Math.round(Math.min(height, width) / 2);
97
-        let nextState;
90
+        const size = 2 * Math.round(Math.min(_height, _width) / 2);
98 91
 
99 92
         if (size < AVATAR_SIZE * 1.5) {
100
-            nextState = {
93
+            return {
101 94
                 avatarSize: size - 15, // Leave some margin.
102 95
                 useConnectivityInfoLabel: false
103 96
             };
104
-        } else {
105
-            nextState = DEFAULT_STATE;
106 97
         }
107 98
 
108
-        this.setState(nextState);
99
+        return DEFAULT_STATE;
100
+
109 101
     }
110 102
 
111 103
     /**
@@ -126,18 +118,15 @@ class LargeVideo extends Component<Props, State> {
126 118
         } = this.props;
127 119
 
128 120
         return (
129
-            <DimensionsDetector
130
-                onDimensionsChanged = { this._onDimensionsChanged }>
131
-                <ParticipantView
132
-                    avatarSize = { avatarSize }
133
-                    onPress = { onClick }
134
-                    participantId = { _participantId }
135
-                    style = { _styles.largeVideo }
136
-                    testHintId = 'org.jitsi.meet.LargeVideo'
137
-                    useConnectivityInfoLabel = { useConnectivityInfoLabel }
138
-                    zOrder = { 0 }
139
-                    zoomEnabled = { true } />
140
-            </DimensionsDetector>
121
+            <ParticipantView
122
+                avatarSize = { avatarSize }
123
+                onPress = { onClick }
124
+                participantId = { _participantId }
125
+                style = { _styles.largeVideo }
126
+                testHintId = 'org.jitsi.meet.LargeVideo'
127
+                useConnectivityInfoLabel = { useConnectivityInfoLabel }
128
+                zOrder = { 0 }
129
+                zoomEnabled = { true } />
141 130
         );
142 131
     }
143 132
 }
@@ -147,15 +136,16 @@ class LargeVideo extends Component<Props, State> {
147 136
  *
148 137
  * @param {Object} state - Redux state.
149 138
  * @private
150
- * @returns {{
151
- *     _participantId: string,
152
- *     _styles: StyleType
153
- * }}
139
+ * @returns {Props}
154 140
  */
155 141
 function _mapStateToProps(state) {
142
+    const { clientHeight: height, clientWidth: width } = state['features/base/responsive-ui'];
143
+
156 144
     return {
145
+        _height: height,
157 146
         _participantId: state['features/large-video'].participantId,
158
-        _styles: ColorSchemeRegistry.get(state, 'LargeVideo')
147
+        _styles: ColorSchemeRegistry.get(state, 'LargeVideo'),
148
+        _width: width
159 149
     };
160 150
 }
161 151
 

Loading…
Cancelar
Guardar