Bläddra i källkod

[RN] Show an indication when connectivity problems occur

The video will switch to the avatar and be tinted with gray. On the large view,
a text message indicating the user has connectivity issues will be shown.
master
Saúl Ibarra Corretgé 7 år sedan
förälder
incheckning
5640524647

+ 93
- 4
react/features/base/participants/components/ParticipantView.native.js Visa fil

@@ -1,19 +1,25 @@
1 1
 import PropTypes from 'prop-types';
2 2
 import React, { Component } from 'react';
3
+import { Text, View } from 'react-native';
3 4
 import { connect } from 'react-redux';
4 5
 
5
-import { JitsiParticipantConnectionStatus } from '../../lib-jitsi-meet';
6 6
 import { prefetch } from '../../../mobile/image-cache';
7
+
8
+import { translate } from '../../i18n';
9
+import { JitsiParticipantConnectionStatus } from '../../lib-jitsi-meet';
7 10
 import {
8 11
     MEDIA_TYPE,
9 12
     shouldRenderVideoTrack,
10 13
     VideoTrack
11 14
 } from '../../media';
12
-import { Container } from '../../react';
15
+import { Container, TintedView } from '../../react';
13 16
 import { getTrackByMediaTypeAndParticipant } from '../../tracks';
14 17
 
18
+import {
19
+    getAvatarURL, getParticipantById, getParticipantDisplayName
20
+} from '../functions';
21
+
15 22
 import Avatar from './Avatar';
16
-import { getAvatarURL, getParticipantById } from '../functions';
17 23
 import styles from './styles';
18 24
 
19 25
 /**
@@ -54,6 +60,13 @@ class ParticipantView extends Component {
54 60
          */
55 61
         _connectionStatus: PropTypes.string,
56 62
 
63
+        /**
64
+         * The name of the participant which this component represents.
65
+         *
66
+         * @private
67
+         */
68
+        _participantName: PropTypes.string,
69
+
57 70
         /**
58 71
          * The video Track of the participant with {@link #participantId}.
59 72
          */
@@ -90,6 +103,17 @@ class ParticipantView extends Component {
90 103
          */
91 104
         style: PropTypes.object,
92 105
 
106
+        /**
107
+         * The function to translate human-readable text.
108
+         */
109
+        t: PropTypes.func,
110
+
111
+        /**
112
+         * Indicates if the connectivity info label should be shown, if
113
+         * appropriate. It will be shown in case the connection is interrupted.
114
+         */
115
+        useConnectivityInfoLabel: PropTypes.bool,
116
+
93 117
         /**
94 118
          * The z-order of the Video of ParticipantView in the stacking space of
95 119
          * all Videos. For more details, refer to the zOrder property of the
@@ -98,6 +122,50 @@ class ParticipantView extends Component {
98 122
         zOrder: PropTypes.number
99 123
     };
100 124
 
125
+    /**
126
+     * Renders the connection status label, if appropriate.
127
+     *
128
+     * @param {string} connectionStatus - The status of the participant's
129
+     * connection.
130
+     * @private
131
+     * @returns {ReactElement|null}
132
+     */
133
+    _renderConnectionInfo(connectionStatus) {
134
+        let messageKey;
135
+
136
+        switch (connectionStatus) {
137
+        case JitsiParticipantConnectionStatus.INACTIVE:
138
+            messageKey = 'connection.LOW_BANDWIDTH';
139
+            break;
140
+        case JitsiParticipantConnectionStatus.INTERRUPTED:
141
+            messageKey = 'connection.USER_CONNECTION_INTERRUPTED';
142
+            break;
143
+        default:
144
+            return null;
145
+        }
146
+
147
+        const {
148
+            avatarStyle,
149
+            _participantName: displayName,
150
+            t
151
+        } = this.props;
152
+
153
+        // XXX Consider splitting this component into 2: one for the large
154
+        // view and one for the thumbnail. Some of these don't apply to both.
155
+        const containerStyle = {
156
+            ...styles.connectionInfoContainer,
157
+            width: avatarStyle.width * 1.5
158
+        };
159
+
160
+        return (
161
+            <View style = { containerStyle } >
162
+                <Text style = { styles.connectionInfoText } >
163
+                    { t(messageKey, { displayName }) }
164
+                </Text>
165
+            </View>
166
+        );
167
+    }
168
+
101 169
     /**
102 170
      * Implements React's {@link Component#render()}.
103 171
      *
@@ -115,6 +183,10 @@ class ParticipantView extends Component {
115 183
         // FIXME It's currently impossible to have true as the value of
116 184
         // waitForVideoStarted because videoTrack's state videoStarted will be
117 185
         // updated only after videoTrack is rendered.
186
+        // XXX Note that, unlike on web, we don't render video when the
187
+        // connection status is interrupted, this is because the renderer
188
+        // doesn't retain the last frame forever, so we would end up with a
189
+        // black screen.
118 190
         const waitForVideoStarted = false;
119 191
         const renderVideo
120 192
             = !this.props._audioOnly
@@ -125,6 +197,12 @@ class ParticipantView extends Component {
125 197
         // Is the avatar to be rendered?
126 198
         const renderAvatar = Boolean(!renderVideo && avatar);
127 199
 
200
+        // If the connection has problems we will "tint" the video / avatar.
201
+        const useTint
202
+            = connectionStatus === JitsiParticipantConnectionStatus.INACTIVE
203
+                || connectionStatus
204
+                    === JitsiParticipantConnectionStatus.INTERRUPTED;
205
+
128 206
         return (
129 207
             <Container
130 208
                 style = {{
@@ -154,6 +232,14 @@ class ParticipantView extends Component {
154 232
                     && <Avatar
155 233
                         style = { this.props.avatarStyle }
156 234
                         uri = { avatar } /> }
235
+
236
+                { useTint
237
+
238
+                    // If the connection has problems, tint the video / avatar.
239
+                    && <TintedView /> }
240
+
241
+                { this.props.useConnectivityInfoLabel
242
+                    && this._renderConnectionInfo(connectionStatus) }
157 243
             </Container>
158 244
         );
159 245
     }
@@ -196,10 +282,12 @@ function _mapStateToProps(state, ownProps) {
196 282
             participantId);
197 283
     let avatar;
198 284
     let connectionStatus;
285
+    let participantName;
199 286
 
200 287
     if (participant) {
201 288
         avatar = getAvatarURL(participant);
202 289
         connectionStatus = participant.connectionStatus;
290
+        participantName = getParticipantDisplayName(state);
203 291
 
204 292
         // Avatar (on React Native) now has the ability to generate an
205 293
         // automatically-colored default image when no URI/URL is specified or
@@ -223,6 +311,7 @@ function _mapStateToProps(state, ownProps) {
223 311
         _connectionStatus:
224 312
             connectionStatus
225 313
                 || JitsiParticipantConnectionStatus.ACTIVE,
314
+        _participantName: participantName,
226 315
         _videoTrack:
227 316
             getTrackByMediaTypeAndParticipant(
228 317
                 state['features/base/tracks'],
@@ -231,4 +320,4 @@ function _mapStateToProps(state, ownProps) {
231 320
     };
232 321
 }
233 322
 
234
-export default connect(_mapStateToProps)(ParticipantView);
323
+export default translate(connect(_mapStateToProps)(ParticipantView));

+ 23
- 1
react/features/base/participants/components/styles.js Visa fil

@@ -1,9 +1,31 @@
1
-import { createStyleSheet } from '../../styles';
1
+import { BoxModel, ColorPalette, createStyleSheet } from '../../styles';
2 2
 
3 3
 /**
4 4
  * The styles of the feature base/participants.
5 5
  */
6 6
 export default createStyleSheet({
7
+    /**
8
+     * Style for the text rendered when there is a connectivity problem.
9
+     */
10
+    connectionInfoText: {
11
+        color: ColorPalette.white,
12
+        fontSize: 12,
13
+        marginVertical: BoxModel.margin,
14
+        marginHorizontal: BoxModel.margin,
15
+        textAlign: 'center'
16
+    },
17
+
18
+    /**
19
+     * Style for the container of the text rendered when there is a
20
+     * connectivity problem.
21
+     */
22
+    connectionInfoContainer: {
23
+        alignSelf: 'center',
24
+        backgroundColor: ColorPalette.darkGrey,
25
+        borderRadius: 20,
26
+        marginTop: BoxModel.margin
27
+    },
28
+
7 29
     /**
8 30
      * {@code ParticipantView} style.
9 31
      */

+ 31
- 0
react/features/base/participants/functions.js Visa fil

@@ -122,6 +122,37 @@ export function getParticipantCount(stateful: Object | Function) {
122 122
     return getParticipants(stateful).length;
123 123
 }
124 124
 
125
+/**
126
+ * Returns participant's display name.
127
+ * FIXME: remove the hardcoded strings once interfaceConfig is stored in redux
128
+ * and merge with a similarly named method in conference.js.
129
+ *
130
+ * @param {(Function|Object)} stateful - The (whole) redux state, or redux's
131
+ * {@code getState} function to be used to retrieve the state.
132
+ * @param {string} id - The ID of the participant's display name to retrieve.
133
+ * @private
134
+ * @returns {string}
135
+ */
136
+export function getParticipantDisplayName(
137
+        stateful: Object | Function, id: string) {
138
+    const participant = getParticipantById(stateful, id);
139
+
140
+    if (participant) {
141
+        if (participant.name) {
142
+            return participant.name;
143
+        }
144
+
145
+        if (participant.local) {
146
+            return typeof interfaceConfig === 'object'
147
+                ? interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME
148
+                : 'me';
149
+        }
150
+    }
151
+
152
+    return typeof interfaceConfig === 'object'
153
+        ? interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME
154
+        : 'Fellow Jitster';
155
+}
125 156
 
126 157
 /**
127 158
  * Selectors for getting all known participants with fake participants filtered

+ 1
- 0
react/features/large-video/components/LargeVideo.native.js Visa fil

@@ -41,6 +41,7 @@ class LargeVideo extends Component<*> {
41 41
                 avatarStyle = { styles.avatar }
42 42
                 participantId = { this.props._participantId }
43 43
                 style = { styles.largeVideo }
44
+                useConnectivityInfoLabel = { true }
44 45
                 zOrder = { 0 } />
45 46
         );
46 47
     }

Laddar…
Avbryt
Spara