Browse Source

Merge pull request #3696 from virtuacoplenny/lenny/stream-key-validation

Add some live stream key validation
master
virtuacoplenny 6 years ago
parent
commit
699b13066e
No account linked to committer's email address

+ 10
- 2
css/_recording.scss View File

65
     }
65
     }
66
 
66
 
67
     .form-footer {
67
     .form-footer {
68
+        display: flex;
69
+        margin-top: 5px;
68
         text-align: right;
70
         text-align: right;
69
     }
71
     }
70
 
72
 
95
 
97
 
96
     .stream-key-form {
98
     .stream-key-form {
97
         .helper-link {
99
         .helper-link {
98
-            display: inline-block;
99
             cursor: pointer;
100
             cursor: pointer;
100
-            margin-top: 5px;
101
+            display: inline-block;
102
+            flex-shrink: 0;
103
+            margin-left: auto;
104
+        }
105
+
106
+        .validation-error {
107
+            color:#FFD740;
108
+            font-size: 12px;
101
         }
109
         }
102
     }
110
     }
103
 }
111
 }

+ 1
- 0
lang/main.json View File

515
         "expandedOn": "The meeting is currently being streamed to YouTube.",
515
         "expandedOn": "The meeting is currently being streamed to YouTube.",
516
         "expandedPending": "The live streaming is being started...",
516
         "expandedPending": "The live streaming is being started...",
517
         "failedToStart": "Live Streaming failed to start",
517
         "failedToStart": "Live Streaming failed to start",
518
+        "invalidStreamKey": "Live stream key may be incorrect.",
518
         "off": "Live Streaming stopped",
519
         "off": "Live Streaming stopped",
519
         "on": "Live Streaming",
520
         "on": "Live Streaming",
520
         "pending": "Starting Live Stream...",
521
         "pending": "Starting Live Stream...",

+ 2
- 1
react/features/recording/components/LiveStream/AbstractStartLiveStreamDialog.js View File

194
      */
194
      */
195
     _onSubmit() {
195
     _onSubmit() {
196
         const { broadcasts, selectedBoundStreamID } = this.state;
196
         const { broadcasts, selectedBoundStreamID } = this.state;
197
-        const key = this.state.streamKey || this.props._streamKey;
197
+        const key
198
+            = (this.state.streamKey || this.props._streamKey || '').trim();
198
 
199
 
199
         if (!key) {
200
         if (!key) {
200
             return false;
201
             return false;

+ 80
- 1
react/features/recording/components/LiveStream/AbstractStreamKeyForm.js View File

1
 // @flow
1
 // @flow
2
 
2
 
3
+import debounce from 'lodash/debounce';
3
 import { Component } from 'react';
4
 import { Component } from 'react';
4
 
5
 
5
 declare var interfaceConfig: Object;
6
 declare var interfaceConfig: Object;
33
     value: string
34
     value: string
34
 };
35
 };
35
 
36
 
37
+/**
38
+ * The state of the component.
39
+ */
40
+type State = {
41
+
42
+    /**
43
+     * Whether or not to show the warnings that the passed in value seems like
44
+     * an improperly formatted stream key.
45
+     */
46
+    showValidationError: boolean
47
+};
48
+
36
 /**
49
 /**
37
  * An abstract React Component for entering a key for starting a YouTube live
50
  * An abstract React Component for entering a key for starting a YouTube live
38
  * stream.
51
  * stream.
39
  *
52
  *
40
  * @extends Component
53
  * @extends Component
41
  */
54
  */
42
-export default class AbstractStreamKeyForm extends Component<Props> {
55
+export default class AbstractStreamKeyForm extends Component<Props, State> {
43
     helpURL: string;
56
     helpURL: string;
57
+    _debouncedUpdateValidationErrorVisibility: Function;
44
 
58
 
45
     /**
59
     /**
46
      * Constructor for the component.
60
      * Constructor for the component.
50
     constructor(props: Props) {
64
     constructor(props: Props) {
51
         super(props);
65
         super(props);
52
 
66
 
67
+        this.state = {
68
+            showValidationError: Boolean(this.props.value)
69
+                && !this._validateStreamKey(this.props.value)
70
+        };
71
+
53
         this.helpURL = (typeof interfaceConfig !== 'undefined'
72
         this.helpURL = (typeof interfaceConfig !== 'undefined'
54
             && interfaceConfig.LIVE_STREAMING_HELP_LINK)
73
             && interfaceConfig.LIVE_STREAMING_HELP_LINK)
55
             || LIVE_STREAMING_HELP_LINK;
74
             || LIVE_STREAMING_HELP_LINK;
56
 
75
 
76
+        this._debouncedUpdateValidationErrorVisibility = debounce(
77
+            this._updateValidationErrorVisibility.bind(this),
78
+            800,
79
+            { leading: false }
80
+        );
81
+
57
         // Bind event handlers so they are only bound once per instance.
82
         // Bind event handlers so they are only bound once per instance.
58
         this._onInputChange = this._onInputChange.bind(this);
83
         this._onInputChange = this._onInputChange.bind(this);
59
     }
84
     }
60
 
85
 
86
+    /**
87
+     * Implements React Component's componentDidUpdate.
88
+     *
89
+     * @inheritdoc
90
+     */
91
+    componentDidUpdate(prevProps: Props) {
92
+        if (this.props.value !== prevProps.value) {
93
+            this._debouncedUpdateValidationErrorVisibility();
94
+        }
95
+    }
96
+
97
+    /**
98
+     * Implements React Component's componentWillUnmount.
99
+     *
100
+     * @inheritdoc
101
+     */
102
+    componentWillUnmount() {
103
+        this._debouncedUpdateValidationErrorVisibility.cancel();
104
+    }
105
+
61
     _onInputChange: Object => void
106
     _onInputChange: Object => void
62
 
107
 
63
     /**
108
     /**
75
 
120
 
76
         this.props.onChange(value);
121
         this.props.onChange(value);
77
     }
122
     }
123
+
124
+    /**
125
+     * Checks if the stream key value seems like a valid stream key and sets the
126
+     * state for showing or hiding the notification about the stream key seeming
127
+     * invalid.
128
+     *
129
+     * @private
130
+     * @returns {boolean}
131
+     */
132
+    _updateValidationErrorVisibility() {
133
+        const newShowValidationError = Boolean(this.props.value)
134
+            && !this._validateStreamKey(this.props.value);
135
+
136
+        if (newShowValidationError !== this.state.showValidationError) {
137
+            this.setState({
138
+                showValidationError: newShowValidationError
139
+            });
140
+        }
141
+    }
142
+
143
+    /**
144
+     * Checks if a passed in stream key appears to be in a valid format.
145
+     *
146
+     * @param {string} streamKey - The stream key to check for valid formatting.
147
+     * @returns {void}
148
+     * @returns {boolean}
149
+     */
150
+    _validateStreamKey(streamKey = '') {
151
+        const trimmedKey = streamKey.trim();
152
+        const fourGroupsDashSeparated = /^(?:[a-zA-Z0-9]{4}(?:-(?!$)|$)){4}/;
153
+        const match = fourGroupsDashSeparated.exec(trimmedKey);
154
+
155
+        return Boolean(match);
156
+    }
78
 }
157
 }

+ 22
- 9
react/features/recording/components/LiveStream/native/StreamKeyForm.js View File

52
                     placeholderTextColor = { PLACEHOLDER_COLOR }
52
                     placeholderTextColor = { PLACEHOLDER_COLOR }
53
                     style = { styles.streamKeyInput }
53
                     style = { styles.streamKeyInput }
54
                     value = { this.props.value } />
54
                     value = { this.props.value } />
55
-                <TouchableOpacity
56
-                    onPress = { this._onOpenHelp }
57
-                    style = { styles.streamKeyHelp } >
58
-                    <Text style = { styles.text }>
59
-                        {
60
-                            t('liveStreaming.streamIdHelp')
61
-                        }
62
-                    </Text>
63
-                </TouchableOpacity>
55
+                <View style = { styles.formFooter }>
56
+                    {
57
+                        this.state.showValidationError
58
+                            ? <View style = { styles.formFooterItem }>
59
+                                <Text style = { styles.warningText }>
60
+                                    { t('liveStreaming.invalidStreamKey') }
61
+                                </Text>
62
+                            </View>
63
+                            : null
64
+                    }
65
+                    <View style = { styles.formFooterItem }>
66
+                        <TouchableOpacity
67
+                            onPress = { this._onOpenHelp }
68
+                            style = { styles.streamKeyHelp } >
69
+                            <Text style = { styles.text }>
70
+                                {
71
+                                    t('liveStreaming.streamIdHelp')
72
+                                }
73
+                            </Text>
74
+                        </TouchableOpacity>
75
+                    </View>
76
+                </View>
64
             </View>
77
             </View>
65
         );
78
         );
66
     }
79
     }

+ 21
- 1
react/features/recording/components/LiveStream/native/styles.js View File

48
         padding: BoxModel.padding
48
         padding: BoxModel.padding
49
     },
49
     },
50
 
50
 
51
+    /**
52
+     * Wrapper for the last element in the form.
53
+     */
54
+    formFooter: {
55
+        flexDirection: 'row'
56
+    },
57
+
58
+    /**
59
+     * Wrapper for individual children in the last element of the form.
60
+     */
61
+    formFooterItem: {
62
+        flex: 1
63
+    },
64
+
51
     /**
65
     /**
52
      * Explaining text on the top of the sign in form.
66
      * Explaining text on the top of the sign in form.
53
      */
67
      */
133
 
147
 
134
     text: {
148
     text: {
135
         color: ColorPalette.white
149
         color: ColorPalette.white
136
-    }
150
+    },
137
 
151
 
152
+    /**
153
+     * A different colored text to indicate information needing attention.
154
+     */
155
+    warningText: {
156
+        color: ColorPalette.Y200
157
+    }
138
 });
158
 });

+ 14
- 7
react/features/recording/components/LiveStream/web/StreamKeyForm.js View File

36
      * @returns {ReactElement}
36
      * @returns {ReactElement}
37
      */
37
      */
38
     render() {
38
     render() {
39
-        const { value, t } = this.props;
39
+        const { t, value } = this.props;
40
 
40
 
41
         return (
41
         return (
42
             <div className = 'stream-key-form'>
42
             <div className = 'stream-key-form'>
52
                     shouldFitContainer = { true }
52
                     shouldFitContainer = { true }
53
                     type = 'text'
53
                     type = 'text'
54
                     value = { this.props.value } />
54
                     value = { this.props.value } />
55
-                { this.helpURL
56
-                    ? <div className = 'form-footer'>
57
-                        <a
55
+                <div className = 'form-footer'>
56
+                    {
57
+                        this.state.showValidationError
58
+                            ? <span className = 'validation-error'>
59
+                                { t('liveStreaming.invalidStreamKey') }
60
+                            </span>
61
+                            : null
62
+                    }
63
+                    { this.helpURL
64
+                        ? <a
58
                             className = 'helper-link'
65
                             className = 'helper-link'
59
                             onClick = { this._onOpenHelp }>
66
                             onClick = { this._onOpenHelp }>
60
                             { t('liveStreaming.streamIdHelp') }
67
                             { t('liveStreaming.streamIdHelp') }
61
                         </a>
68
                         </a>
62
-                    </div>
63
-                    : null
64
-                }
69
+                        : null
70
+                    }
71
+                </div>
65
             </div>
72
             </div>
66
         );
73
         );
67
     }
74
     }

Loading…
Cancel
Save