Browse Source

[RN] Add RecordingLabel indicator for mobile

master
Bettenbuk Zoltan 7 years ago
parent
commit
5499599720

+ 10
- 1
react/features/conference/components/Conference.native.js View File

10
 import { connect, disconnect } from '../../base/connection';
10
 import { connect, disconnect } from '../../base/connection';
11
 import { DialogContainer } from '../../base/dialog';
11
 import { DialogContainer } from '../../base/dialog';
12
 import { CalleeInfoContainer } from '../../base/jwt';
12
 import { CalleeInfoContainer } from '../../base/jwt';
13
+import { JitsiRecordingConstants } from '../../base/lib-jitsi-meet';
13
 import { getParticipantCount } from '../../base/participants';
14
 import { getParticipantCount } from '../../base/participants';
14
 import { Container, LoadingIndicator, TintedView } from '../../base/react';
15
 import { Container, LoadingIndicator, TintedView } from '../../base/react';
15
 import { TestConnectionInfo } from '../../base/testing';
16
 import { TestConnectionInfo } from '../../base/testing';
17
 import { ConferenceNotification } from '../../calendar-sync';
18
 import { ConferenceNotification } from '../../calendar-sync';
18
 import { Filmstrip } from '../../filmstrip';
19
 import { Filmstrip } from '../../filmstrip';
19
 import { LargeVideo } from '../../large-video';
20
 import { LargeVideo } from '../../large-video';
21
+import { RecordingLabel } from '../../recording';
20
 import { setToolboxVisible, Toolbox } from '../../toolbox';
22
 import { setToolboxVisible, Toolbox } from '../../toolbox';
21
 import { VideoQualityLabel } from '../../video-quality';
23
 import { VideoQualityLabel } from '../../video-quality';
22
 
24
 
246
                       * participants.
248
                       * participants.
247
                       */}
249
                       */}
248
                     <Filmstrip />
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
                 </View>
259
                 </View>
251
                 <TestConnectionInfo />
260
                 <TestConnectionInfo />
252
 
261
 

+ 12
- 6
react/features/conference/components/styles.js View File

18
         flex: 1
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
      * The style of the {@link View} which expands over the whole
34
      * The style of the {@link View} which expands over the whole
23
      * {@link Conference} area and splits it between the {@link Filmstrip} and
35
      * {@link Conference} area and splits it between the {@link Filmstrip} and
35
         // On iPhone X there is the notch. In the two cases BoxModel.margin is
47
         // On iPhone X there is the notch. In the two cases BoxModel.margin is
36
         // not enough.
48
         // not enough.
37
         top: BoxModel.margin * 3
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 View File

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 View File

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 View File

1
 // @flow
1
 // @flow
2
 
2
 
3
-import React, { Component } from 'react';
3
+import React from 'react';
4
+import { connect } from 'react-redux';
4
 
5
 
5
 import { CircularLabel } from '../../base/label';
6
 import { CircularLabel } from '../../base/label';
6
 import { translate } from '../../base/i18n';
7
 import { translate } from '../../base/i18n';
7
 import { JitsiRecordingConstants } from '../../base/lib-jitsi-meet';
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
  * The translation keys to use when displaying messages. The values are set
16
  * The translation keys to use when displaying messages. The values are set
11
  * lazily to work around circular dependency issues with lib-jitsi-meet causing
17
  * lazily to work around circular dependency issues with lib-jitsi-meet causing
61
 /**
67
 /**
62
  * The type of the React {@code Component} props of {@link RecordingLabel}.
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
      * The redux representation of a recording session.
73
      * The redux representation of a recording session.
91
  *
97
  *
92
  * @extends {Component}
98
  * @extends {Component}
93
  */
99
  */
94
-class RecordingLabel extends Component<Props, State> {
100
+class RecordingLabel extends AbstractRecordingLabel<Props, State> {
95
     _autohideTimeout: number;
101
     _autohideTimeout: number;
96
 
102
 
97
     state = {
103
     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 View File

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…
Cancel
Save