瀏覽代碼

[RN] LocalVideoTrackUnderlay

Implement a React Component which displays children as an overlay of
local video. The WelcomePage implemented such a component inside of it
among other WelcomePage-specific logic so I split
LocalVideoTrackUnderlay out of it. The new Component is used on the
BlankPage which may be displayed in the future not only when the
WelcomePage is disabled but also when there are long running network
requests, for example.
master
Lyubo Marinov 7 年之前
父節點
當前提交
a7ee632f43

+ 7
- 29
react/features/welcome/components/AbstractWelcomePage.js 查看文件

1
 import PropTypes from 'prop-types';
1
 import PropTypes from 'prop-types';
2
-import React, { Component } from 'react';
2
+import { Component } from 'react';
3
 
3
 
4
 import { appNavigate } from '../../app';
4
 import { appNavigate } from '../../app';
5
 import { isRoomValid } from '../../base/conference';
5
 import { isRoomValid } from '../../base/conference';
6
-import { VideoTrack } from '../../base/media';
7
-import { getLocalVideoTrack } from '../../base/tracks';
8
 
6
 
9
-import { generateRoomWithoutSeparator } from '../roomnameGenerator';
7
+import { generateRoomWithoutSeparator } from '../functions';
10
 
8
 
11
 /**
9
 /**
12
  * Base (abstract) class for container component rendering the welcome page.
10
  * Base (abstract) class for container component rendering the welcome page.
15
  */
13
  */
16
 export class AbstractWelcomePage extends Component {
14
 export class AbstractWelcomePage extends Component {
17
     /**
15
     /**
18
-     * {@code AbstractWelcomePage} component's property types.
16
+     * {@code AbstractWelcomePage}'s React {@code Component} prop types.
19
      *
17
      *
20
      * @static
18
      * @static
21
      */
19
      */
22
     static propTypes = {
20
     static propTypes = {
23
-        _localVideoTrack: PropTypes.object,
24
         _room: PropTypes.string,
21
         _room: PropTypes.string,
25
         dispatch: PropTypes.func
22
         dispatch: PropTypes.func
26
     };
23
     };
159
         this.setState({ room: value });
156
         this.setState({ room: value });
160
     }
157
     }
161
 
158
 
162
-    /**
163
-     * Renders a local video if any.
164
-     *
165
-     * @protected
166
-     * @returns {(ReactElement|null)}
167
-     */
168
-    _renderLocalVideo() {
169
-        return (
170
-            <VideoTrack videoTrack = { this.props._localVideoTrack } />
171
-        );
172
-    }
173
-
174
     /**
159
     /**
175
      * Triggers the generation of a new room name and initiates an animation of
160
      * Triggers the generation of a new room name and initiates an animation of
176
      * its changing.
161
      * its changing.
195
 }
180
 }
196
 
181
 
197
 /**
182
 /**
198
- * Selects local video track from tracks in state, local participant and room
199
- * and maps them to component props. It seems it's not possible to 'connect'
200
- * base component and then extend from it. So we export this function in order
201
- * to be used in child classes for 'connect'.
183
+ * Maps (parts of) the redux state to the React {@code Component} props of
184
+ * {@code AbstractWelcomePage}.
202
  *
185
  *
203
- * @param {Object} state - Redux state.
186
+ * @param {Object} state - The redux state.
204
  * @protected
187
  * @protected
205
  * @returns {{
188
  * @returns {{
206
- *     _localVideoTrack: (Track|undefined),
207
  *     _room: string
189
  *     _room: string
208
  * }}
190
  * }}
209
  */
191
  */
210
 export function _mapStateToProps(state) {
192
 export function _mapStateToProps(state) {
211
-    const conference = state['features/base/conference'];
212
-    const tracks = state['features/base/tracks'];
213
-
214
     return {
193
     return {
215
-        _localVideoTrack: getLocalVideoTrack(tracks),
216
-        _room: conference.room
194
+        _room: state['features/base/conference'].room
217
     };
195
     };
218
 }
196
 }

+ 4
- 3
react/features/welcome/components/BlankPage.native.js 查看文件

2
 
2
 
3
 import PropTypes from 'prop-types';
3
 import PropTypes from 'prop-types';
4
 import React, { Component } from 'react';
4
 import React, { Component } from 'react';
5
-import { ActivityIndicator, View } from 'react-native';
5
+import { ActivityIndicator } from 'react-native';
6
 import { connect } from 'react-redux';
6
 import { connect } from 'react-redux';
7
 
7
 
8
 import { destroyLocalTracks } from '../../base/tracks';
8
 import { destroyLocalTracks } from '../../base/tracks';
9
 
9
 
10
 import { isWelcomePageAppEnabled } from '../functions';
10
 import { isWelcomePageAppEnabled } from '../functions';
11
+import LocalVideoTrackUnderlay from './LocalVideoTrackUnderlay';
11
 import styles from './styles';
12
 import styles from './styles';
12
 
13
 
13
 /**
14
 /**
62
      */
63
      */
63
     render() {
64
     render() {
64
         return (
65
         return (
65
-            <View style = { styles.blankPage }>
66
+            <LocalVideoTrackUnderlay style = { styles.blankPage }>
66
                 <ActivityIndicator
67
                 <ActivityIndicator
67
                     animating = { this.props._networkActivity }
68
                     animating = { this.props._networkActivity }
68
                     size = { 'large' } />
69
                     size = { 'large' } />
69
-            </View>
70
+            </LocalVideoTrackUnderlay>
70
         );
71
         );
71
     }
72
     }
72
 }
73
 }

+ 117
- 0
react/features/welcome/components/LocalVideoTrackUnderlay.native.js 查看文件

1
+/* @flow */
2
+
3
+import PropTypes from 'prop-types';
4
+import React, { Component } from 'react';
5
+import { View } from 'react-native';
6
+import { connect } from 'react-redux';
7
+
8
+import { VideoTrack } from '../../base/media';
9
+import { getLocalVideoTrack } from '../../base/tracks';
10
+
11
+import styles from './styles';
12
+
13
+/**
14
+ * Implements a React {@code Component} which underlays the local video track,
15
+ * if any, underneath its children.
16
+ */
17
+class LocalVideoTrackUnderlay extends Component {
18
+    state: {
19
+
20
+        /**
21
+         * The style of <tt>LocalVideoTrackUnderlay</tt> which is a combination
22
+         * of its default style and the consumer-specified style.
23
+         */
24
+        style: Object
25
+    };
26
+
27
+    /**
28
+     * {@code LocalVideoTrackUnderlay}'s React {@code Component} prop types.
29
+     *
30
+     * @static
31
+     */
32
+    static propTypes = {
33
+        _localVideoTrack: PropTypes.object,
34
+        children: PropTypes.node,
35
+        style: PropTypes.object
36
+    };
37
+
38
+    /**
39
+     * Initializes a new {@code LocalVideoTrackUnderlay} instance.
40
+     *
41
+     * @param {Object} props - The read-only React {@code Component} props with
42
+     * which the new instance is to be initialized.
43
+     */
44
+    constructor(props) {
45
+        super(props);
46
+
47
+        this.componentWillReceiveProps(props);
48
+    }
49
+
50
+    /**
51
+     * Notifies this mounted React {@code Component} that it will receive new
52
+     * props. Forks (in Facebook/React speak) the prop {@code style} because its
53
+     * value is to be combined with the default style.
54
+     *
55
+     * @inheritdoc
56
+     * @param {Object} nextProps - The read-only React {@code Component} props
57
+     * that this instance will receive.
58
+     * @returns {void}
59
+     */
60
+    componentWillReceiveProps(nextProps) {
61
+        // style
62
+        const prevStyle = this.props && this.props.style;
63
+        const nextStyle = nextProps && nextProps.style;
64
+        const assignState = !this.state;
65
+
66
+        if (prevStyle !== nextStyle || assignState) {
67
+            const nextState = {
68
+                style: {
69
+                    ...styles.localVideoTrackUnderlay,
70
+                    ...nextStyle
71
+                }
72
+            };
73
+
74
+            if (assignState) {
75
+                this.state = nextState;
76
+            } else {
77
+                this.setState(nextState);
78
+            }
79
+        }
80
+    }
81
+
82
+    /**
83
+     * Implements React's {@link Component#render()}.
84
+     *
85
+     * @inheritdoc
86
+     * @override
87
+     * @returns {ReactElement}
88
+     */
89
+    render() {
90
+        return (
91
+            <View style = { this.state.style }>
92
+                <VideoTrack videoTrack = { this.props._localVideoTrack } />
93
+                <View style = { styles.localVideoTrackOverlay }>
94
+                    { this.props.children }
95
+                </View>
96
+            </View>
97
+        );
98
+    }
99
+}
100
+
101
+/**
102
+ * Maps (parts of) the redux state to the React {@code Component} props of
103
+ * {@code LocalVideoTrackUnderlay}.
104
+ *
105
+ * @param {Object} state - The redux state.
106
+ * @private
107
+ * @returns {{
108
+ *     _localVideoTrack: (Track|undefined)
109
+ * }}
110
+ */
111
+function _mapStateToProps(state) {
112
+    return {
113
+        _localVideoTrack: getLocalVideoTrack(state['features/base/tracks'])
114
+    };
115
+}
116
+
117
+export default connect(_mapStateToProps)(LocalVideoTrackUnderlay);

+ 0
- 0
react/features/welcome/components/LocalVideoTrackUnderlay.web.js 查看文件


+ 32
- 53
react/features/welcome/components/WelcomePage.native.js 查看文件

9
 import { createDesiredLocalTracks } from '../../base/tracks';
9
 import { createDesiredLocalTracks } from '../../base/tracks';
10
 
10
 
11
 import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage';
11
 import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage';
12
+import LocalVideoTrackUnderlay from './LocalVideoTrackUnderlay';
12
 import styles from './styles';
13
 import styles from './styles';
13
 
14
 
14
 /**
15
 /**
55
      * @returns {ReactElement}
56
      * @returns {ReactElement}
56
      */
57
      */
57
     render() {
58
     render() {
59
+        const { t } = this.props;
60
+
58
         return (
61
         return (
59
-            <View style = { styles.container }>
60
-                {
61
-                    this._renderLocalVideo()
62
-                }
62
+            <LocalVideoTrackUnderlay style = { styles.welcomePage }>
63
+                <View style = { styles.roomContainer }>
64
+                    <Text style = { styles.title }>
65
+                        { t('welcomepage.roomname') }
66
+                    </Text>
67
+                    <TextInput
68
+                        accessibilityLabel = { 'Input room name.' }
69
+                        autoCapitalize = 'none'
70
+                        autoComplete = { false }
71
+                        autoCorrect = { false }
72
+                        autoFocus = { false }
73
+                        onChangeText = { this._onRoomChange }
74
+                        placeholder = { t('welcomepage.roomnamePlaceHolder') }
75
+                        style = { styles.textInput }
76
+                        underlineColorAndroid = 'transparent'
77
+                        value = { this.state.room } />
78
+                    <TouchableHighlight
79
+                        accessibilityLabel = { 'Tap to Join.' }
80
+                        disabled = { this._isJoinDisabled() }
81
+                        onPress = { this._onJoin }
82
+                        style = { styles.button }
83
+                        underlayColor = { ColorPalette.white }>
84
+                        <Text style = { styles.buttonText }>
85
+                            { t('welcomepage.join') }
86
+                        </Text>
87
+                    </TouchableHighlight>
88
+                </View>
63
                 {
89
                 {
64
-                    this._renderLocalVideoOverlay()
90
+                    this._renderLegalese()
65
                 }
91
                 }
66
-            </View>
92
+            </LocalVideoTrackUnderlay>
67
         );
93
         );
68
     }
94
     }
69
 
95
 
97
             </View>
123
             </View>
98
         );
124
         );
99
     }
125
     }
100
-
101
-    /**
102
-     * Renders a View over the local video. The latter is thought of as the
103
-     * background (content) of this WelcomePage. The former is thought of as the
104
-     * foreground (content) of this WelcomePage such as the room name input, the
105
-     * button to initiate joining the specified room, etc.
106
-     *
107
-     * @private
108
-     * @returns {ReactElement}
109
-     */
110
-    _renderLocalVideoOverlay() {
111
-        const { t } = this.props;
112
-
113
-        return (
114
-            <View style = { styles.localVideoOverlay }>
115
-                <View style = { styles.roomContainer }>
116
-                    <Text style = { styles.title }>
117
-                        { t('welcomepage.roomname') }
118
-                    </Text>
119
-                    <TextInput
120
-                        accessibilityLabel = { 'Input room name.' }
121
-                        autoCapitalize = 'none'
122
-                        autoComplete = { false }
123
-                        autoCorrect = { false }
124
-                        autoFocus = { false }
125
-                        onChangeText = { this._onRoomChange }
126
-                        placeholder = { t('welcomepage.roomnamePlaceHolder') }
127
-                        style = { styles.textInput }
128
-                        underlineColorAndroid = 'transparent'
129
-                        value = { this.state.room } />
130
-                    <TouchableHighlight
131
-                        accessibilityLabel = { 'Tap to Join.' }
132
-                        disabled = { this._isJoinDisabled() }
133
-                        onPress = { this._onJoin }
134
-                        style = { styles.button }
135
-                        underlayColor = { ColorPalette.white }>
136
-                        <Text style = { styles.buttonText }>
137
-                            { t('welcomepage.join') }
138
-                        </Text>
139
-                    </TouchableHighlight>
140
-                </View>
141
-                {
142
-                    this._renderLegalese()
143
-                }
144
-            </View>
145
-        );
146
-    }
147
 }
126
 }
148
 
127
 
149
 export default translate(connect(_mapStateToProps)(WelcomePage));
128
 export default translate(connect(_mapStateToProps)(WelcomePage));

+ 26
- 25
react/features/welcome/components/styles.js 查看文件

16
  */
16
  */
17
 export default createStyleSheet({
17
 export default createStyleSheet({
18
     /**
18
     /**
19
-     * The style of <tt>BlankPage</tt>.
19
+     * The style of the top-level container of <tt>BlankPage</tt>.
20
      */
20
      */
21
     blankPage: {
21
     blankPage: {
22
-        alignItems: 'center',
23
-        backgroundColor: 'transparent',
24
-        flex: 1,
25
-        flexDirection: 'column',
26
-        justifyContent: 'center'
27
     },
22
     },
28
 
23
 
29
     /**
24
     /**
49
         fontSize: 18
44
         fontSize: 18
50
     },
45
     },
51
 
46
 
52
-    /**
53
-     * The style of the top-level container of WelcomePage.
54
-     */
55
-    container: fixAndroidViewClipping({
56
-        alignSelf: 'stretch',
57
-        backgroundColor: ColorPalette.blue,
58
-        flex: 1
59
-    }),
60
-
61
     /**
47
     /**
62
      * The style of the legal-related content such as (hyper)links to Privacy
48
      * The style of the legal-related content such as (hyper)links to Privacy
63
      * Policy and Terms of Service displayed on the WelcomePage.
49
      * Policy and Terms of Service displayed on the WelcomePage.
80
     },
66
     },
81
 
67
 
82
     /**
68
     /**
83
-     * The style of the View displayed over the local video. The latter is
84
-     * thought of as the background (content) of WelcomePage. The former is
85
-     * thought of as the foreground (content) of WelcomePage.
69
+     * The style of the <tt>View</tt> displayed over the local video by
70
+     * <tt>LocalVideoTrackUnderlay</tt>. The latter is thought of as the
71
+     * background (content). The former is thought of as the foreground
72
+     * (content).
86
      */
73
      */
87
-    localVideoOverlay: {
88
-        // Since (1) the top-level container of WelcomePage is not transparent
89
-        // and, more importantly, (2) this View is displayed over the local
90
-        // video, this View would better not have a background color.
91
-        // Otherwise, Views within this View will inherit its background color
92
-        // and Text, for example, will display non-transparent rectangles over
93
-        // the local video.
74
+    localVideoTrackOverlay: {
94
         backgroundColor: 'transparent',
75
         backgroundColor: 'transparent',
95
         bottom: 0,
76
         bottom: 0,
96
         flex: 1,
77
         flex: 1,
97
         flexDirection: 'column',
78
         flexDirection: 'column',
79
+        justifyContent: 'center',
98
         left: 0,
80
         left: 0,
99
         position: 'absolute',
81
         position: 'absolute',
100
         right: 0,
82
         right: 0,
101
         top: 0
83
         top: 0
102
     },
84
     },
103
 
85
 
86
+    /**
87
+     * The style of the top-level container/<tt>View</tt> of
88
+     * <tt>LocalVideoTrackUnderlay</tt>.
89
+     */
90
+    localVideoTrackUnderlay: fixAndroidViewClipping({
91
+        alignItems: 'center',
92
+        alignSelf: 'stretch',
93
+        backgroundColor: 'transparent',
94
+        flex: 1,
95
+        justifyContent: 'center'
96
+    }),
97
+
104
     /**
98
     /**
105
      * Container for room name input box and 'join' button.
99
      * Container for room name input box and 'join' button.
106
      */
100
      */
134
         fontSize: 25,
128
         fontSize: 25,
135
         marginBottom: 2 * BoxModel.margin,
129
         marginBottom: 2 * BoxModel.margin,
136
         textAlign: 'center'
130
         textAlign: 'center'
131
+    },
132
+
133
+    /**
134
+     * The style of the top-level container of <tt>WelcomePage</tt>.
135
+     */
136
+    welcomePage: {
137
+        backgroundColor: ColorPalette.blue
137
     }
138
     }
138
 });
139
 });

Loading…
取消
儲存