Explorar el Código

fix(device-selection): use non-connect video preview

Filmstrip only mode displays a device selection dialog that
does not have access to the redux/connect. However, the current
VideoTrack extends from AbstractVideoTrack, which assumes a
redux connection. The fix is to move video display logic into
a separate component and have device selection use that, while
the existing VideoTrack remains connected to redux but
uses the new video display component.
master
Leonard Kim hace 8 años
padre
commit
1e84f993b4

+ 218
- 0
react/features/base/media/components/web/Video.js Ver fichero

@@ -0,0 +1,218 @@
1
+import React, { Component } from 'react';
2
+
3
+/**
4
+ * Component that renders a video element for a passed in video track.
5
+ *
6
+ * @extends Component
7
+ */
8
+class Video extends Component {
9
+    /**
10
+     * Default values for {@code Video} component's properties.
11
+     *
12
+     * @static
13
+     */
14
+    static defaultProps = {
15
+        className: '',
16
+
17
+        id: ''
18
+    };
19
+
20
+    /**
21
+     * {@code Video} component's property types.
22
+     *
23
+     * @static
24
+     */
25
+    static propTypes = {
26
+        /**
27
+         * CSS classes to add to the video element.
28
+         */
29
+        className: React.PropTypes.string,
30
+
31
+        /**
32
+         * The value of the id attribute of the video. Used by the torture tests
33
+         * to locate video elements.
34
+         */
35
+        id: React.PropTypes.string,
36
+
37
+        /**
38
+         * Optional callback to invoke once the video starts playing.
39
+         */
40
+        onVideoPlaying: React.PropTypes.func,
41
+
42
+        /**
43
+         * The JitsiLocalTrack to display.
44
+         */
45
+        videoTrack: React.PropTypes.object
46
+    };
47
+
48
+    /**
49
+     * Initializes a new {@code Video} instance.
50
+     *
51
+     * @param {Object} props - The read-only properties with which the new
52
+     * instance is to be initialized.
53
+     */
54
+    constructor(props) {
55
+        super(props);
56
+
57
+        /**
58
+         * The internal reference to the DOM/HTML element intended for
59
+         * displaying a video. This element may be an HTML video element or a
60
+         * temasys video object.
61
+         *
62
+         * @private
63
+         * @type {HTMLVideoElement|Object}
64
+         */
65
+        this._videoElement = null;
66
+
67
+
68
+        // Bind event handlers so they are only bound once for every instance.
69
+        this._onVideoPlaying = this._onVideoPlaying.bind(this);
70
+        this._setVideoElement = this._setVideoElement.bind(this);
71
+    }
72
+
73
+    /**
74
+     * Invokes the library for rendering the video on initial display. Sets the
75
+     * volume level to zero to ensure no sound plays.
76
+     *
77
+     * @inheritdoc
78
+     * @returns {void}
79
+     */
80
+    componentDidMount() {
81
+        // Add these attributes directly onto the video element so temasys can
82
+        // use them when converting the video to an object.
83
+        this._videoElement.volume = 0;
84
+        this._videoElement.onplaying = this._onVideoPlaying;
85
+
86
+        this._attachTrack(this.props.videoTrack);
87
+    }
88
+
89
+    /**
90
+     * Remove any existing associations between the current video track and the
91
+     * component's video element.
92
+     *
93
+     * @inheritdoc
94
+     * @returns {void}
95
+     */
96
+    componentWillUnmount() {
97
+        this._detachTrack(this.props.videoTrack);
98
+    }
99
+
100
+    /**
101
+     * Updates the video display only if a new track is added. This component's
102
+     * updating is blackboxed from React to prevent re-rendering of video
103
+     * element, as the lib uses track.attach(videoElement) instead. Also,
104
+     * re-rendering cannot be used with temasys, which replaces video elements
105
+     * with an object.
106
+     *
107
+     * @inheritdoc
108
+     * @returns {boolean} - False is always returned to blackbox this component.
109
+     * from React.
110
+     */
111
+    shouldComponentUpdate(nextProps) {
112
+        const currentJitsiTrack = this.props.videoTrack
113
+            && this.props.videoTrack.jitsiTrack;
114
+        const nextJitsiTrack = nextProps.videoTrack
115
+            && nextProps.videoTrack.jitsiTrack;
116
+
117
+        if (currentJitsiTrack !== nextJitsiTrack) {
118
+            this._detachTrack(this.props.videoTrack);
119
+            this._attachTrack(nextProps.videoTrack);
120
+        }
121
+
122
+        return false;
123
+    }
124
+
125
+    /**
126
+     * Renders the video element.
127
+     *
128
+     * @override
129
+     * @returns {ReactElement}
130
+     */
131
+    render() {
132
+        // The wrapping div is necessary because temasys will replace the video
133
+        // with an object but react will keep expecting the video element. The
134
+        // div gives a constant element for react to keep track of.
135
+        return (
136
+            <div>
137
+                <video
138
+                    autoPlay = { true }
139
+                    className = { this.props.className }
140
+                    id = { this.props.id }
141
+                    ref = { this._setVideoElement } />
142
+            </div>
143
+        );
144
+    }
145
+
146
+    /**
147
+     * Calls into the passed in track to associate the track with the
148
+     * component's video element and render video.
149
+     *
150
+     * @param {Object} videoTrack - The redux representation of the
151
+     * {@code JitsiLocalTrack}.
152
+     * @private
153
+     * @returns {void}
154
+     */
155
+    _attachTrack(videoTrack) {
156
+        if (!videoTrack || !videoTrack.jitsiTrack) {
157
+            return;
158
+        }
159
+
160
+        const updatedVideoElement
161
+            = videoTrack.jitsiTrack.attach(this._videoElement);
162
+
163
+        // Sets the instance variable for the video element again as the element
164
+        // maybe have been replaced with a new object by temasys.
165
+        this._setVideoElement(updatedVideoElement);
166
+    }
167
+
168
+    /**
169
+     * Removes the association to the component's video element from the passed
170
+     * in redux representation of jitsi video track to stop the track from
171
+     * rendering. With temasys, the video element must still be visible for
172
+     * detaching to complete.
173
+     *
174
+     * @param {Object} videoTrack -  The redux representation of the
175
+     * {@code JitsiLocalTrack}.
176
+     * @private
177
+     * @returns {void}
178
+     */
179
+    _detachTrack(videoTrack) {
180
+        // Detach the video element from the track only if it has already
181
+        // been attached. This accounts for a special case with temasys
182
+        // where if detach is being called before attach, the video
183
+        // element is converted to Object without updating this
184
+        // component's reference to the video element.
185
+        if (this._videoElement
186
+            && videoTrack
187
+            && videoTrack.jitsiTrack
188
+            && videoTrack.jitsiTrack.containers.includes(this._videoElement)) {
189
+            videoTrack.jitsiTrack.detach(this._videoElement);
190
+        }
191
+    }
192
+
193
+    /**
194
+     * Invokes the onvideoplaying callback if defined.
195
+     *
196
+     * @private
197
+     * @returns {void}
198
+     */
199
+    _onVideoPlaying() {
200
+        if (this.props.onVideoPlaying) {
201
+            this.props.onVideoPlaying();
202
+        }
203
+    }
204
+
205
+    /**
206
+     * Sets an instance variable for the component's video element so it can be
207
+     * referenced later for attaching and detaching a JitsiLocalTrack.
208
+     *
209
+     * @param {Object} element - DOM element for the component's video display.
210
+     * @private
211
+     * @returns {void}
212
+     */
213
+    _setVideoElement(element) {
214
+        this._videoElement = element;
215
+    }
216
+}
217
+
218
+export default Video;

+ 8
- 145
react/features/base/media/components/web/VideoTrack.js Ver fichero

@@ -3,6 +3,8 @@ import { connect } from 'react-redux';
3 3
 
4 4
 import AbstractVideoTrack from '../AbstractVideoTrack';
5 5
 
6
+import Video from './Video';
7
+
6 8
 /**
7 9
  * Component that renders a video element for a passed in video track.
8 10
  *
@@ -42,82 +44,6 @@ class VideoTrack extends AbstractVideoTrack {
42 44
         id: React.PropTypes.string
43 45
     };
44 46
 
45
-    /**
46
-     * Initializes a new VideoTrack instance.
47
-     *
48
-     * @param {Object} props - The read-only properties with which the new
49
-     * instance is to be initialized.
50
-     */
51
-    constructor(props) {
52
-        super(props);
53
-
54
-        /**
55
-         * The internal reference to the DOM/HTML element intended for
56
-         * displaying a video. This element may be an HTML video element or a
57
-         * temasys video object.
58
-         *
59
-         * @private
60
-         * @type {HTMLVideoElement|Object}
61
-         */
62
-        this._videoElement = null;
63
-
64
-
65
-        // Bind event handlers so they are only bound once for every instance.
66
-        this._setVideoElement = this._setVideoElement.bind(this);
67
-    }
68
-
69
-    /**
70
-     * Invokes the library for rendering the video on initial display. Sets the
71
-     * volume level to zero to ensure no sound plays.
72
-     *
73
-     * @inheritdoc
74
-     * @returns {void}
75
-     */
76
-    componentDidMount() {
77
-        // Add these attributes directly onto the video element so temasys can
78
-        // use them when converting the video to an object.
79
-        this._videoElement.volume = 0;
80
-        this._videoElement.onplaying = this._onVideoPlaying;
81
-
82
-        this._attachTrack(this.props.videoTrack);
83
-    }
84
-
85
-    /**
86
-     * Remove any existing associations between the current video track and the
87
-     * component's video element.
88
-     *
89
-     * @inheritdoc
90
-     * @returns {void}
91
-     */
92
-    componentWillUnmount() {
93
-        this._detachTrack(this.props.videoTrack);
94
-    }
95
-
96
-    /**
97
-     * Updates the video display only if a new track is added. This component's
98
-     * updating is blackboxed from React to prevent re-rendering of video
99
-     * element, as the lib uses track.attach(videoElement) instead. Also,
100
-     * re-rendering cannot be used with temasys, which replaces video elements
101
-     * with an object.
102
-     *
103
-     * @inheritdoc
104
-     * @returns {boolean} - False is always returned to blackbox this component.
105
-     * from React.
106
-     */
107
-    shouldComponentUpdate(nextProps) {
108
-        const currentJitsiTrack = this.props.videoTrack
109
-            && this.props.videoTrack.jitsiTrack;
110
-        const nextJitsiTrack = nextProps.videoTrack
111
-            && nextProps.videoTrack.jitsiTrack;
112
-
113
-        if (currentJitsiTrack !== nextJitsiTrack) {
114
-            this._detachTrack(this.props.videoTrack);
115
-            this._attachTrack(nextProps.videoTrack);
116
-        }
117
-
118
-        return false;
119
-    }
120
-
121 47
     /**
122 48
      * Renders the video element.
123 49
      *
@@ -125,78 +51,15 @@ class VideoTrack extends AbstractVideoTrack {
125 51
      * @returns {ReactElement}
126 52
      */
127 53
     render() {
128
-        // The wrapping div is necessary because temasys will replace the video
129
-        // with an object but react will keep expecting the video element. The
130
-        // div gives a constant element for react to keep track of.
131 54
         return (
132
-            <div>
133
-                <video
134
-                    autoPlay = { true }
135
-                    className = { this.props.className }
136
-                    id = { this.props.id }
137
-                    ref = { this._setVideoElement } />
138
-            </div>
55
+            <Video
56
+                autoPlay = { true }
57
+                className = { this.props.className }
58
+                id = { this.props.id }
59
+                onVideoPlaying = { this._onVideoPlaying }
60
+                videoTrack = { this.props.videoTrack } />
139 61
         );
140 62
     }
141
-
142
-    /**
143
-     * Calls into the passed in track to associate the track with the
144
-     * component's video element and render video.
145
-     *
146
-     * @param {Object} videoTrack - The redux representation of the
147
-     * {@code JitsiLocalTrack}.
148
-     * @private
149
-     * @returns {void}
150
-     */
151
-    _attachTrack(videoTrack) {
152
-        if (!videoTrack || !videoTrack.jitsiTrack) {
153
-            return;
154
-        }
155
-
156
-        const updatedVideoElement
157
-            = videoTrack.jitsiTrack.attach(this._videoElement);
158
-
159
-        // Sets the instance variable for the video element again as the element
160
-        // maybe have been replaced with a new object by temasys.
161
-        this._setVideoElement(updatedVideoElement);
162
-    }
163
-
164
-    /**
165
-     * Removes the association to the component's video element from the passed
166
-     * in redux representation of jitsi video track to stop the track from
167
-     * rendering. With temasys, the video element must still be visible for
168
-     * detaching to complete.
169
-     *
170
-     * @param {Object} videoTrack -  The redux representation of the
171
-     * {@code JitsiLocalTrack}.
172
-     * @private
173
-     * @returns {void}
174
-     */
175
-    _detachTrack(videoTrack) {
176
-        // Detach the video element from the track only if it has already
177
-        // been attached. This accounts for a special case with temasys
178
-        // where if detach is being called before attach, the video
179
-        // element is converted to Object without updating this
180
-        // component's reference to the video element.
181
-        if (this._videoElement
182
-            && videoTrack
183
-            && videoTrack.jitsiTrack
184
-            && videoTrack.jitsiTrack.containers.includes(this._videoElement)) {
185
-            videoTrack.jitsiTrack.detach(this._videoElement);
186
-        }
187
-    }
188
-
189
-    /**
190
-     * Sets an instance variable for the component's video element so it can be
191
-     * referenced later for attaching and detaching a JitsiLocalTrack.
192
-     *
193
-     * @param {Object} element - DOM element for the component's video display.
194
-     * @private
195
-     * @returns {void}
196
-     */
197
-    _setVideoElement(element) {
198
-        this._videoElement = element;
199
-    }
200 63
 }
201 64
 
202 65
 export default connect()(VideoTrack);

+ 2
- 2
react/features/device-selection/components/VideoInputPreview.js Ver fichero

@@ -1,6 +1,6 @@
1 1
 import React, { Component } from 'react';
2 2
 
3
-import { VideoTrack } from '../../base/media';
3
+import { Video } from '../../base/media';
4 4
 
5 5
 const VIDEO_ERROR_CLASS = 'video-preview-has-error';
6 6
 
@@ -42,7 +42,7 @@ class VideoInputPreview extends Component {
42 42
 
43 43
         return (
44 44
             <div className = { className }>
45
-                <VideoTrack
45
+                <Video
46 46
                     className = 'video-input-preview-display flipVideoX'
47 47
                     triggerOnPlayingUpdate = { false }
48 48
                     videoTrack = {{ jitsiTrack: this.props.track }} />

Loading…
Cancelar
Guardar