Explorar el Código

[RN] Dynamically adjust LargeView's Avatar to available size

When in PiP mode the LargeView will not be large enough to hold the avatar (for
those interested in the details, our avatar's size is 200, and in PiP mode the
app is resized to about 150).

In order to solve it, this PR refactors how the avatar style is passed along,
reducing it to a single "size" prop. With this only prop, the Avatar compononent
will compute the width, height and borderRadius, plus deal with some Android
shenanigans.

In addition, the LargeView component now uses DimensionsDetector to check its
own size and adjust the size prop passed to the Avatar component as needed.
master
Saúl Ibarra Corretgé hace 7 años
padre
commit
1419247801

+ 18
- 4
react/features/base/participants/components/Avatar.native.js Ver fichero

@@ -6,6 +6,8 @@ import { CachedImage, ImageCache } from '../../../mobile/image-cache';
6 6
 import { Platform } from '../../react';
7 7
 import { ColorPalette } from '../../styles';
8 8
 
9
+import styles from './styles';
10
+
9 11
 /**
10 12
  * The default image/source to be used in case none is specified or the
11 13
  * specified one fails to load.
@@ -32,10 +34,9 @@ export default class Avatar extends Component {
32 34
      */
33 35
     static propTypes = {
34 36
         /**
35
-         * The optional style to add to the {@link Avatar} in order to customize
36
-         * its base look (and feel).
37
+         * The size for the {@link Avatar}.
37 38
          */
38
-        style: PropTypes.object,
39
+        size: PropTypes.number,
39 40
 
40 41
         /**
41 42
          * The URI of the {@link Avatar}.
@@ -216,7 +217,7 @@ export default class Avatar extends Component {
216 217
 
217 218
             /* eslint-enable no-unused-vars */
218 219
 
219
-            style,
220
+            size,
220 221
             ...props
221 222
         } = this.props;
222 223
         const {
@@ -224,6 +225,19 @@ export default class Avatar extends Component {
224 225
             source
225 226
         } = this.state;
226 227
 
228
+        // Compute the base style
229
+        const style = {
230
+            ...styles.avatar,
231
+
232
+            // XXX Workaround for Android: for radii < 80 the border radius
233
+            // doesn't work properly, but applying a radius twice as big
234
+            // seems to do the trick.
235
+            borderRadius: size / 2 < 80
236
+                ? Platform.OS === 'android' ? size * 2 : size / 2 : size / 2,
237
+            height: size,
238
+            width: size
239
+        };
240
+
227 241
         // If we're rendering the _DEFAULT_SOURCE, then we want to do some
228 242
         // additional fu like having automagical colors generated per
229 243
         // participant, transparency to make the intermediate state while

+ 5
- 5
react/features/base/participants/components/ParticipantView.native.js Ver fichero

@@ -73,9 +73,9 @@ class ParticipantView extends Component {
73 73
         _videoTrack: PropTypes.object,
74 74
 
75 75
         /**
76
-         * The style, if any, of the avatar in addition to the default style.
76
+         * The avatar size.
77 77
          */
78
-        avatarStyle: PropTypes.object,
78
+        avatarSize: PropTypes.number,
79 79
 
80 80
         /**
81 81
          * The ID of the participant (to be) depicted by ParticipantView.
@@ -145,7 +145,7 @@ class ParticipantView extends Component {
145 145
         }
146 146
 
147 147
         const {
148
-            avatarStyle,
148
+            avatarSize,
149 149
             _participantName: displayName,
150 150
             t
151 151
         } = this.props;
@@ -154,7 +154,7 @@ class ParticipantView extends Component {
154 154
         // view and one for the thumbnail. Some of these don't apply to both.
155 155
         const containerStyle = {
156 156
             ...styles.connectionInfoContainer,
157
-            width: avatarStyle.width * 1.5
157
+            width: avatarSize * 1.5
158 158
         };
159 159
 
160 160
         return (
@@ -230,7 +230,7 @@ class ParticipantView extends Component {
230 230
                     // rendered.
231 231
                     && _toBoolean(this.props.showAvatar, true)
232 232
                     && <Avatar
233
-                        style = { this.props.avatarStyle }
233
+                        size = { this.props.avatarSize }
234 234
                         uri = { avatar } /> }
235 235
 
236 236
                 { useTint

+ 8
- 0
react/features/base/participants/components/styles.js Ver fichero

@@ -4,6 +4,14 @@ import { BoxModel, ColorPalette, createStyleSheet } from '../../styles';
4 4
  * The styles of the feature base/participants.
5 5
  */
6 6
 export default createStyleSheet({
7
+    /**
8
+     * The style of the avatar of the participant.
9
+     */
10
+    avatar: {
11
+        alignSelf: 'center',
12
+        flex: 0
13
+    },
14
+
7 15
     /**
8 16
      * Style for the text rendered when there is a connectivity problem.
9 17
      */

+ 3
- 1
react/features/filmstrip/components/Thumbnail.js Ver fichero

@@ -19,6 +19,8 @@ import {
19 19
     VideoMutedIndicator
20 20
 } from './_';
21 21
 
22
+import { AVATAR_SIZE } from './styles';
23
+
22 24
 /**
23 25
  * React component for video thumbnail.
24 26
  * @extends Component
@@ -94,7 +96,7 @@ class Thumbnail extends Component {
94 96
                             = { audioTrack.jitsiTrack.getOriginalStream() } /> }
95 97
 
96 98
                 <ParticipantView
97
-                    avatarStyle = { styles.avatar }
99
+                    avatarSize = { AVATAR_SIZE }
98 100
                     participantId = { participantId }
99 101
                     showAvatar = { participantNotInLargeVideo }
100 102
                     showVideo = { participantNotInLargeVideo }

+ 5
- 15
react/features/filmstrip/components/styles.js Ver fichero

@@ -1,6 +1,10 @@
1
-import { Platform } from '../../base/react';
2 1
 import { ColorPalette } from '../../base/styles';
3 2
 
3
+/**
4
+ * Size for the Avatar.
5
+ */
6
+export const AVATAR_SIZE = 50;
7
+
4 8
 /**
5 9
  * The base style of {@link Filmstrip} shared between narrow and wide versions.
6 10
  */
@@ -13,20 +17,6 @@ const filmstrip = {
13 17
  * The styles of the feature filmstrip common to both Web and native.
14 18
  */
15 19
 export default {
16
-    /**
17
-     * Avatar style.
18
-     */
19
-    avatar: {
20
-        alignSelf: 'center',
21
-
22
-        // XXX Workaround for Android: for images < 80 the border radius doesn't
23
-        // work properly, but applying a radius twice as big does the trick.
24
-        borderRadius: Platform.OS === 'android' ? 100 : 25,
25
-        flex: 0,
26
-        height: 50,
27
-        width: 50
28
-    },
29
-
30 20
     /**
31 21
      * Dominant speaker indicator style.
32 22
      */

+ 89
- 20
react/features/large-video/components/LargeVideo.native.js Ver fichero

@@ -1,12 +1,42 @@
1
-/* @flow */
1
+// @flow
2 2
 
3
-import PropTypes from 'prop-types';
4 3
 import React, { Component } from 'react';
5 4
 import { connect } from 'react-redux';
6 5
 
7 6
 import { ParticipantView } from '../../base/participants';
7
+import { DimensionsDetector } from '../../base/responsive-ui';
8 8
 
9
-import styles from './styles';
9
+import styles, { AVATAR_SIZE } from './styles';
10
+
11
+type Props = {
12
+
13
+    /**
14
+     * The ID of the participant (to be) depicted by LargeVideo.
15
+     *
16
+     * @private
17
+     */
18
+    _participantId: string
19
+};
20
+
21
+type State = {
22
+
23
+    /**
24
+     * Size for the Avatar. It will be dynamically adjusted based on the
25
+     * available size.
26
+     */
27
+    avatarSize: number,
28
+
29
+    /**
30
+     * Whether the connectivity indicator will be shown or not. It will be true
31
+     * by default, but it may be turned off if there is not enough space.
32
+     */
33
+    useConnectivityInfoLabel: boolean
34
+};
35
+
36
+const DEFAULT_STATE = {
37
+    avatarSize: AVATAR_SIZE,
38
+    useConnectivityInfoLabel: true
39
+};
10 40
 
11 41
 /**
12 42
  * Implements a React {@link Component} which represents the large video (a.k.a.
@@ -14,20 +44,51 @@ import styles from './styles';
14 44
  *
15 45
  * @extends Component
16 46
  */
17
-class LargeVideo extends Component<*> {
47
+class LargeVideo extends Component<Props, State> {
48
+    state = {
49
+        ...DEFAULT_STATE
50
+    };
51
+
52
+    /** Initializes a new {@code LargeVideo} instance.
53
+     *
54
+     * @param {Object} props - The read-only properties with which the new
55
+     * instance is to be initialized.
56
+     */
57
+    constructor(props) {
58
+        super(props);
59
+
60
+        this._onDimensionsChanged = this._onDimensionsChanged.bind(this);
61
+    }
62
+
63
+    _onDimensionsChanged: (width: number, height: number) => void;
64
+
18 65
     /**
19
-     * LargeVideo component's property types.
66
+     * Handle this component's dimension changes. In case we deem it's too
67
+     * small, the connectivity indicator won't be rendered and the avatar
68
+     * will occupy the entirety of the available screen state.
20 69
      *
21
-     * @static
70
+     * @param {number} width - The component's current width.
71
+     * @param {number} height - The component's current height.
72
+     * @private
73
+     * @returns {void}
22 74
      */
23
-    static propTypes = {
24
-        /**
25
-         * The ID of the participant (to be) depicted by LargeVideo.
26
-         *
27
-         * @private
28
-         */
29
-        _participantId: PropTypes.string
30
-    };
75
+    _onDimensionsChanged(width: number, height: number) {
76
+        // Get the size, rounded to the nearest even number.
77
+        const size = 2 * Math.round(Math.min(height, width) / 2);
78
+
79
+        let newState;
80
+
81
+        if (size < AVATAR_SIZE * 1.5) {
82
+            newState = {
83
+                avatarSize: size - 15, // Leave some margin.
84
+                useConnectivityInfoLabel: false
85
+            };
86
+        } else {
87
+            newState = DEFAULT_STATE;
88
+        }
89
+
90
+        this.setState(newState);
91
+    }
31 92
 
32 93
     /**
33 94
      * Implements React's {@link Component#render()}.
@@ -36,13 +97,21 @@ class LargeVideo extends Component<*> {
36 97
      * @returns {ReactElement}
37 98
      */
38 99
     render() {
100
+        const {
101
+            avatarSize,
102
+            useConnectivityInfoLabel
103
+        } = this.state;
104
+
39 105
         return (
40
-            <ParticipantView
41
-                avatarStyle = { styles.avatar }
42
-                participantId = { this.props._participantId }
43
-                style = { styles.largeVideo }
44
-                useConnectivityInfoLabel = { true }
45
-                zOrder = { 0 } />
106
+            <DimensionsDetector
107
+                onDimensionsChanged = { this._onDimensionsChanged } >
108
+                <ParticipantView
109
+                    avatarSize = { avatarSize }
110
+                    participantId = { this.props._participantId }
111
+                    style = { styles.largeVideo }
112
+                    useConnectivityInfoLabel = { useConnectivityInfoLabel }
113
+                    zOrder = { 0 } />
114
+            </DimensionsDetector>
46 115
         );
47 116
     }
48 117
 }

+ 5
- 12
react/features/large-video/components/styles.js Ver fichero

@@ -1,18 +1,11 @@
1 1
 import { ColorPalette, createStyleSheet } from '../../base/styles';
2 2
 
3
-export default createStyleSheet({
4
-    /**
5
-     * The style of the avatar of the participant displayed in largeVideo. It's
6
-     * an addition to the default style of Avatar.
7
-     */
8
-    avatar: {
9
-        alignSelf: 'center',
10
-        borderRadius: 100,
11
-        flex: 0,
12
-        height: 200,
13
-        width: 200
14
-    },
3
+/**
4
+ * Size for the Avatar.
5
+ */
6
+export const AVATAR_SIZE = 200;
15 7
 
8
+export default createStyleSheet({
16 9
     /**
17 10
      * Large video container style.
18 11
      */

Loading…
Cancelar
Guardar