瀏覽代碼

[RN] Add RecordingLabel indicator for mobile

master
Bettenbuk Zoltan 7 年之前
父節點
當前提交
5499599720

+ 10
- 1
react/features/conference/components/Conference.native.js 查看文件

@@ -10,6 +10,7 @@ import { appNavigate } from '../../app';
10 10
 import { connect, disconnect } from '../../base/connection';
11 11
 import { DialogContainer } from '../../base/dialog';
12 12
 import { CalleeInfoContainer } from '../../base/jwt';
13
+import { JitsiRecordingConstants } from '../../base/lib-jitsi-meet';
13 14
 import { getParticipantCount } from '../../base/participants';
14 15
 import { Container, LoadingIndicator, TintedView } from '../../base/react';
15 16
 import { TestConnectionInfo } from '../../base/testing';
@@ -17,6 +18,7 @@ import { createDesiredLocalTracks } from '../../base/tracks';
17 18
 import { ConferenceNotification } from '../../calendar-sync';
18 19
 import { Filmstrip } from '../../filmstrip';
19 20
 import { LargeVideo } from '../../large-video';
21
+import { RecordingLabel } from '../../recording';
20 22
 import { setToolboxVisible, Toolbox } from '../../toolbox';
21 23
 import { VideoQualityLabel } from '../../video-quality';
22 24
 
@@ -246,7 +248,14 @@ class Conference extends Component<Props> {
246 248
                       * participants.
247 249
                       */}
248 250
                     <Filmstrip />
249
-                    <VideoQualityLabel style = { styles.videoQualityLabel } />
251
+
252
+                    <View style = { styles.indicatorContainer }>
253
+                        <RecordingLabel
254
+                            mode = { JitsiRecordingConstants.mode.FILE } />
255
+                        <RecordingLabel
256
+                            mode = { JitsiRecordingConstants.mode.STREAM } />
257
+                        <VideoQualityLabel />
258
+                    </View>
250 259
                 </View>
251 260
                 <TestConnectionInfo />
252 261
 

+ 12
- 6
react/features/conference/components/styles.js 查看文件

@@ -18,6 +18,18 @@ export default createStyleSheet({
18 18
         flex: 1
19 19
     }),
20 20
 
21
+    /**
22
+     * View that contains the indicators.
23
+     */
24
+    indicatorContainer: {
25
+        flex: 1,
26
+        flexDirection: 'row',
27
+        margin: BoxModel.margin,
28
+        position: 'absolute',
29
+        right: 0,
30
+        top: 0
31
+    },
32
+
21 33
     /**
22 34
      * The style of the {@link View} which expands over the whole
23 35
      * {@link Conference} area and splits it between the {@link Filmstrip} and
@@ -35,11 +47,5 @@ export default createStyleSheet({
35 47
         // On iPhone X there is the notch. In the two cases BoxModel.margin is
36 48
         // not enough.
37 49
         top: BoxModel.margin * 3
38
-    },
39
-
40
-    videoQualityLabel: {
41
-        right: 0,
42
-        top: 0,
43
-        position: 'absolute'
44 50
     }
45 51
 });

+ 66
- 0
react/features/recording/components/AbstractRecordingLabel.js 查看文件

@@ -0,0 +1,66 @@
1
+// @flow
2
+
3
+import { Component } from 'react';
4
+
5
+import { JitsiRecordingConstants } from '../../base/lib-jitsi-meet';
6
+
7
+/**
8
+ * NOTE: Web currently renders multiple indicators if multiple recording
9
+ * sessions are running. This is however may not be a good UX as it's not
10
+ * obvious why there are multiple similar 'REC' indicators rendered. Mobile
11
+ * only renders one indicator if there is at least one recording session
12
+ * running. These boolean are shared across the two components to make it
13
+ * easier to align web's behaviour to mobile's later if necessary.
14
+ */
15
+export type Props = {
16
+
17
+    /**
18
+     * True if there is an active recording with the provided mode therefore the
19
+     * component must be rendered.
20
+     */
21
+    _visible: boolean,
22
+
23
+    /**
24
+     * The recording mode this indicator should display.
25
+     */
26
+    mode: string,
27
+
28
+    /**
29
+     * Invoked to obtain translated strings.
30
+     */
31
+    t: Function
32
+};
33
+
34
+/**
35
+ * Abstract class for the {@code RecordingLabel} component.
36
+ */
37
+export default class AbstractRecordingLabel<P: Props, S: *>
38
+    extends Component<P, S> {
39
+
40
+}
41
+
42
+/**
43
+ * Maps (parts of) the Redux state to the associated
44
+ * {@code AbstractRecordingLabel}'s props.
45
+ *
46
+ * @param {Object} state - The Redux state.
47
+ * @param {Props} ownProps - The component's own props.
48
+ * @private
49
+ * @returns {{
50
+ *     _visible: boolean
51
+ * }}
52
+ */
53
+export function _abstractMapStateToProps(state: Object, ownProps: Props) {
54
+    const { mode } = ownProps;
55
+    const _recordingSessions = state['features/recording'].sessionDatas;
56
+    const _visible
57
+        = Array.isArray(_recordingSessions)
58
+        && _recordingSessions.some(
59
+            session => session.status === JitsiRecordingConstants.status.ON
60
+            && session.mode === mode
61
+        );
62
+
63
+    return {
64
+        _visible
65
+    };
66
+}

+ 91
- 0
react/features/recording/components/RecordingLabel.native.js 查看文件

@@ -0,0 +1,91 @@
1
+// @flow
2
+
3
+import React from 'react';
4
+import { connect } from 'react-redux';
5
+
6
+import { translate } from '../../base/i18n';
7
+import { CircularLabel } from '../../base/label';
8
+import { JitsiRecordingConstants } from '../../base/lib-jitsi-meet';
9
+import { combineStyles } from '../../base/styles';
10
+
11
+import AbstractRecordingLabel, {
12
+    type Props as AbstractProps,
13
+    _abstractMapStateToProps
14
+} from './AbstractRecordingLabel';
15
+import styles from './styles';
16
+
17
+type Props = AbstractProps & {
18
+
19
+    /**
20
+     * Style of the component passed as props.
21
+     */
22
+    style: ?Object
23
+};
24
+
25
+/**
26
+ * Implements a React {@link Component} which displays the current state of
27
+ * conference recording.
28
+ *
29
+ * @extends {Component}
30
+ */
31
+class RecordingLabel extends AbstractRecordingLabel<Props, *> {
32
+
33
+    /**
34
+     * Implements React {@code Component}'s render.
35
+     *
36
+     * @inheritdoc
37
+     */
38
+    render() {
39
+        const { _visible, mode, style, t } = this.props;
40
+
41
+        if (!_visible) {
42
+            return null;
43
+        }
44
+
45
+        let labelKey;
46
+        let indicatorStyle;
47
+
48
+        switch (mode) {
49
+        case JitsiRecordingConstants.mode.STREAM:
50
+            labelKey = 'recording.live';
51
+            indicatorStyle = styles.indicatorLive;
52
+            break;
53
+        case JitsiRecordingConstants.mode.FILE:
54
+            labelKey = 'recording.rec';
55
+            indicatorStyle = styles.indicatorRecording;
56
+            break;
57
+        default:
58
+            // Invalid mode is passed to the component.
59
+            return null;
60
+        }
61
+
62
+        return (
63
+            <CircularLabel
64
+                label = { t(labelKey) }
65
+                style = {
66
+                    combineStyles(indicatorStyle, style)
67
+                } />
68
+        );
69
+    }
70
+}
71
+
72
+/**
73
+ * Maps (parts of) the Redux state to the associated
74
+ * {@code RecordingLabel}'s props.
75
+ *
76
+ * NOTE: This component has no props other than the abstract ones but keeping
77
+ * the coding style the same for consistency reasons.
78
+ *
79
+ * @param {Object} state - The Redux state.
80
+ * @param {Object} ownProps - The component's own props.
81
+ * @private
82
+ * @returns {{
83
+ * }}
84
+ */
85
+function _mapStateToProps(state: Object, ownProps: Object) {
86
+    return {
87
+        ..._abstractMapStateToProps(state, ownProps)
88
+    };
89
+}
90
+
91
+export default translate(connect(_mapStateToProps)(RecordingLabel));

+ 29
- 4
react/features/recording/components/RecordingLabel.web.js 查看文件

@@ -1,11 +1,17 @@
1 1
 // @flow
2 2
 
3
-import React, { Component } from 'react';
3
+import React from 'react';
4
+import { connect } from 'react-redux';
4 5
 
5 6
 import { CircularLabel } from '../../base/label';
6 7
 import { translate } from '../../base/i18n';
7 8
 import { JitsiRecordingConstants } from '../../base/lib-jitsi-meet';
8 9
 
10
+import AbstractRecordingLabel, {
11
+    type Props as AbstractProps,
12
+    _abstractMapStateToProps
13
+} from './AbstractRecordingLabel';
14
+
9 15
 /**
10 16
  * The translation keys to use when displaying messages. The values are set
11 17
  * lazily to work around circular dependency issues with lib-jitsi-meet causing
@@ -61,7 +67,7 @@ function _getTranslationKeysByMode() {
61 67
 /**
62 68
  * The type of the React {@code Component} props of {@link RecordingLabel}.
63 69
  */
64
-type Props = {
70
+type Props = AbstractProps & {
65 71
 
66 72
     /**
67 73
      * The redux representation of a recording session.
@@ -91,7 +97,7 @@ type State = {
91 97
  *
92 98
  * @extends {Component}
93 99
  */
94
-class RecordingLabel extends Component<Props, State> {
100
+class RecordingLabel extends AbstractRecordingLabel<Props, State> {
95 101
     _autohideTimeout: number;
96 102
 
97 103
     state = {
@@ -219,4 +225,23 @@ class RecordingLabel extends Component<Props, State> {
219 225
     }
220 226
 }
221 227
 
222
-export default translate(RecordingLabel);
228
+/**
229
+ * Maps (parts of) the Redux state to the associated
230
+ * {@code RecordingLabel}'s props.
231
+ *
232
+ * NOTE: This component has no props other than the abstract ones but keeping
233
+ * the coding style the same for consistency reasons.
234
+ *
235
+ * @param {Object} state - The Redux state.
236
+ * @param {Object} ownProps - The component's own props.
237
+ * @private
238
+ * @returns {{
239
+ * }}
240
+ */
241
+function _mapStateToProps(state: Object, ownProps: Object) {
242
+    return {
243
+        ..._abstractMapStateToProps(state, ownProps)
244
+    };
245
+}
246
+
247
+export default translate(connect(_mapStateToProps)(RecordingLabel));

+ 23
- 0
react/features/recording/components/styles.js 查看文件

@@ -0,0 +1,23 @@
1
+// @flow
2
+
3
+import { ColorPalette, createStyleSheet } from '../../base/styles';
4
+
5
+/**
6
+ * The styles of the React {@code Components} of the feature recording.
7
+ */
8
+export default createStyleSheet({
9
+
10
+    /**
11
+     * Style for the recording indicator.
12
+     */
13
+    indicatorLive: {
14
+        backgroundColor: ColorPalette.blue
15
+    },
16
+
17
+    /**
18
+     * Style for the recording indicator.
19
+     */
20
+    indicatorRecording: {
21
+        backgroundColor: ColorPalette.red
22
+    }
23
+});

Loading…
取消
儲存