Procházet zdrojové kódy

[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é před 7 roky
rodič
revize
5640524647

+ 93
- 4
react/features/base/participants/components/ParticipantView.native.js Zobrazit soubor

1
 import PropTypes from 'prop-types';
1
 import PropTypes from 'prop-types';
2
 import React, { Component } from 'react';
2
 import React, { Component } from 'react';
3
+import { Text, View } from 'react-native';
3
 import { connect } from 'react-redux';
4
 import { connect } from 'react-redux';
4
 
5
 
5
-import { JitsiParticipantConnectionStatus } from '../../lib-jitsi-meet';
6
 import { prefetch } from '../../../mobile/image-cache';
6
 import { prefetch } from '../../../mobile/image-cache';
7
+
8
+import { translate } from '../../i18n';
9
+import { JitsiParticipantConnectionStatus } from '../../lib-jitsi-meet';
7
 import {
10
 import {
8
     MEDIA_TYPE,
11
     MEDIA_TYPE,
9
     shouldRenderVideoTrack,
12
     shouldRenderVideoTrack,
10
     VideoTrack
13
     VideoTrack
11
 } from '../../media';
14
 } from '../../media';
12
-import { Container } from '../../react';
15
+import { Container, TintedView } from '../../react';
13
 import { getTrackByMediaTypeAndParticipant } from '../../tracks';
16
 import { getTrackByMediaTypeAndParticipant } from '../../tracks';
14
 
17
 
18
+import {
19
+    getAvatarURL, getParticipantById, getParticipantDisplayName
20
+} from '../functions';
21
+
15
 import Avatar from './Avatar';
22
 import Avatar from './Avatar';
16
-import { getAvatarURL, getParticipantById } from '../functions';
17
 import styles from './styles';
23
 import styles from './styles';
18
 
24
 
19
 /**
25
 /**
54
          */
60
          */
55
         _connectionStatus: PropTypes.string,
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
          * The video Track of the participant with {@link #participantId}.
71
          * The video Track of the participant with {@link #participantId}.
59
          */
72
          */
90
          */
103
          */
91
         style: PropTypes.object,
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
          * The z-order of the Video of ParticipantView in the stacking space of
118
          * The z-order of the Video of ParticipantView in the stacking space of
95
          * all Videos. For more details, refer to the zOrder property of the
119
          * all Videos. For more details, refer to the zOrder property of the
98
         zOrder: PropTypes.number
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
      * Implements React's {@link Component#render()}.
170
      * Implements React's {@link Component#render()}.
103
      *
171
      *
115
         // FIXME It's currently impossible to have true as the value of
183
         // FIXME It's currently impossible to have true as the value of
116
         // waitForVideoStarted because videoTrack's state videoStarted will be
184
         // waitForVideoStarted because videoTrack's state videoStarted will be
117
         // updated only after videoTrack is rendered.
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
         const waitForVideoStarted = false;
190
         const waitForVideoStarted = false;
119
         const renderVideo
191
         const renderVideo
120
             = !this.props._audioOnly
192
             = !this.props._audioOnly
125
         // Is the avatar to be rendered?
197
         // Is the avatar to be rendered?
126
         const renderAvatar = Boolean(!renderVideo && avatar);
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
         return (
206
         return (
129
             <Container
207
             <Container
130
                 style = {{
208
                 style = {{
154
                     && <Avatar
232
                     && <Avatar
155
                         style = { this.props.avatarStyle }
233
                         style = { this.props.avatarStyle }
156
                         uri = { avatar } /> }
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
             </Container>
243
             </Container>
158
         );
244
         );
159
     }
245
     }
196
             participantId);
282
             participantId);
197
     let avatar;
283
     let avatar;
198
     let connectionStatus;
284
     let connectionStatus;
285
+    let participantName;
199
 
286
 
200
     if (participant) {
287
     if (participant) {
201
         avatar = getAvatarURL(participant);
288
         avatar = getAvatarURL(participant);
202
         connectionStatus = participant.connectionStatus;
289
         connectionStatus = participant.connectionStatus;
290
+        participantName = getParticipantDisplayName(state);
203
 
291
 
204
         // Avatar (on React Native) now has the ability to generate an
292
         // Avatar (on React Native) now has the ability to generate an
205
         // automatically-colored default image when no URI/URL is specified or
293
         // automatically-colored default image when no URI/URL is specified or
223
         _connectionStatus:
311
         _connectionStatus:
224
             connectionStatus
312
             connectionStatus
225
                 || JitsiParticipantConnectionStatus.ACTIVE,
313
                 || JitsiParticipantConnectionStatus.ACTIVE,
314
+        _participantName: participantName,
226
         _videoTrack:
315
         _videoTrack:
227
             getTrackByMediaTypeAndParticipant(
316
             getTrackByMediaTypeAndParticipant(
228
                 state['features/base/tracks'],
317
                 state['features/base/tracks'],
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 Zobrazit soubor

1
-import { createStyleSheet } from '../../styles';
1
+import { BoxModel, ColorPalette, createStyleSheet } from '../../styles';
2
 
2
 
3
 /**
3
 /**
4
  * The styles of the feature base/participants.
4
  * The styles of the feature base/participants.
5
  */
5
  */
6
 export default createStyleSheet({
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
      * {@code ParticipantView} style.
30
      * {@code ParticipantView} style.
9
      */
31
      */

+ 31
- 0
react/features/base/participants/functions.js Zobrazit soubor

122
     return getParticipants(stateful).length;
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
  * Selectors for getting all known participants with fake participants filtered
158
  * Selectors for getting all known participants with fake participants filtered

+ 1
- 0
react/features/large-video/components/LargeVideo.native.js Zobrazit soubor

41
                 avatarStyle = { styles.avatar }
41
                 avatarStyle = { styles.avatar }
42
                 participantId = { this.props._participantId }
42
                 participantId = { this.props._participantId }
43
                 style = { styles.largeVideo }
43
                 style = { styles.largeVideo }
44
+                useConnectivityInfoLabel = { true }
44
                 zOrder = { 0 } />
45
                 zOrder = { 0 } />
45
         );
46
         );
46
     }
47
     }

Načítá se…
Zrušit
Uložit