Browse Source

feat: insecure room name warning

master
Bettenbuk Zoltan 4 years ago
parent
commit
c08638da51

+ 68
- 0
css/_labels.scss View File

@@ -0,0 +1,68 @@
1
+.large-video-labels {
2
+    display: flex;
3
+    position: absolute;
4
+    top: 30px;
5
+    right: 30px;
6
+    transition: right 0.5s;
7
+    z-index: $zindex3;
8
+
9
+    .circular-label {
10
+        align-items: center;
11
+        color: white;
12
+        display: flex;
13
+        font-weight: bold;
14
+        justify-content: center;
15
+        margin-left: 8px;
16
+        opacity: 0.8;
17
+    }
18
+
19
+    .circular-label {
20
+        background: #B8C7E0;
21
+    }
22
+
23
+    .circular-label.e2ee {
24
+        align-items: center;
25
+        background: #76CF9C;
26
+        display: flex;
27
+        justify-content: center;
28
+    }
29
+
30
+    .circular-label.file {
31
+        background: #FF5630;
32
+    }
33
+
34
+    .circular-label.local-rec {
35
+        background: #FF5630;
36
+    }
37
+
38
+    .circular-label.stream {
39
+        background: #0065FF;
40
+    }
41
+
42
+    .circular-label.insecure {
43
+        background: $defaultWarningColor;
44
+    }
45
+
46
+    .recording-label.center-message {
47
+        background: $videoStateIndicatorBackground;
48
+        bottom: 50%;
49
+        display: block;
50
+        left: 50%;
51
+        padding: 10px;
52
+        position: fixed;
53
+        transform: translate(-50%, -50%);
54
+        z-index: $centeredVideoLabelZ;
55
+    }
56
+}
57
+
58
+.circular-label {
59
+    background: $videoStateIndicatorBackground;
60
+    border-radius: 50%;
61
+    box-sizing: border-box;
62
+    cursor: default;
63
+    font-size: 13px;
64
+    height: $videoStateIndicatorSize;
65
+    line-height: $videoStateIndicatorSize;
66
+    text-align: center;
67
+    min-width: $videoStateIndicatorSize;
68
+}

+ 15
- 4
css/_welcome_page.scss View File

@@ -71,9 +71,6 @@ body.welcome-page {
71 71
                 text-align: left;
72 72
                 color: #253858;
73 73
                 height: fit-content;
74
-                border-width: $welcomePageEnterRoomInputContainerBorderWidth;
75
-                border-style: $welcomePageEnterRoomInputContainerBorderStyle;
76
-                border-image: $welcomePageEnterRoomInputContainerBorderImage;
77 74
 
78 75
                 .enter-room-title {
79 76
                     display: $welcomePageEnterRoomTitleDisplay;
@@ -83,12 +80,26 @@ body.welcome-page {
83 80
                 }
84 81
 
85 82
                 .enter-room-input {
86
-                    border: none;
83
+                    border-width: $welcomePageEnterRoomInputContainerBorderWidth;
84
+                    border-style: $welcomePageEnterRoomInputContainerBorderStyle;
85
+                    border-image: $welcomePageEnterRoomInputContainerBorderImage;
87 86
                     display: inline-block;
88 87
                     width: 100%;
89 88
                     font-size: 14px;
90 89
                 }
91 90
 
91
+                .insecure-room-name-warning {
92
+                    align-items: center;
93
+                    color: $defaultWarningColor;
94
+                    display: flex;
95
+                    flex-direction: row;
96
+                    margin-top: 5px;
97
+
98
+                    svg {
99
+                        fill: $defaultWarningColor
100
+                    }
101
+                }
102
+
92 103
                 ::placeholder {
93 104
                     color: #253858;
94 105
                 }

+ 1
- 0
css/main.scss View File

@@ -75,6 +75,7 @@ $flagsImagePath: "../images/";
75 75
 @import 'filmstrip/tile_view_overrides';
76 76
 @import 'filmstrip/vertical_filmstrip';
77 77
 @import 'filmstrip/vertical_filmstrip_overrides';
78
+@import 'labels';
78 79
 @import 'unsupported-browser/main';
79 80
 @import 'modals/invite/add-people';
80 81
 @import 'deep-linking/main';

+ 0
- 62
css/modals/video-quality/_video-quality.scss View File

@@ -144,65 +144,3 @@
144 144
 #videoResolutionLabel {
145 145
     z-index: $zindex3 + 1;
146 146
 }
147
-
148
-.large-video-labels {
149
-    display: flex;
150
-    position: absolute;
151
-    top: 30px;
152
-    right: 30px;
153
-    transition: right 0.5s;
154
-    z-index: $zindex3;
155
-
156
-    .circular-label {
157
-        color: white;
158
-        font-weight: bold;
159
-        margin-left: 8px;
160
-        opacity: 0.8;
161
-    }
162
-
163
-    .circular-label {
164
-        background: #B8C7E0;
165
-    }
166
-
167
-    .circular-label.e2ee {
168
-        align-items: center;
169
-        background: #76CF9C;
170
-        display: flex;
171
-        justify-content: center;
172
-    }
173
-
174
-    .circular-label.file {
175
-        background: #FF5630;
176
-    }
177
-
178
-    .circular-label.local-rec {
179
-        background: #FF5630;
180
-    }
181
-
182
-    .circular-label.stream {
183
-        background: #0065FF;
184
-    }
185
-
186
-    .recording-label.center-message {
187
-        background: $videoStateIndicatorBackground;
188
-        bottom: 50%;
189
-        display: block;
190
-        left: 50%;
191
-        padding: 10px;
192
-        position: fixed;
193
-        transform: translate(-50%, -50%);
194
-        z-index: $centeredVideoLabelZ;
195
-    }
196
-}
197
-
198
-.circular-label {
199
-    background: $videoStateIndicatorBackground;
200
-    border-radius: 50%;
201
-    box-sizing: border-box;
202
-    cursor: default;
203
-    font-size: 13px;
204
-    height: $videoStateIndicatorSize;
205
-    line-height: $videoStateIndicatorSize;
206
-    text-align: center;
207
-    min-width: $videoStateIndicatorSize;
208
-}

+ 3
- 0
lang/main.json View File

@@ -561,6 +561,9 @@
561 561
     "sectionList": {
562 562
         "pullToRefresh": "Pull to refresh"
563 563
     },
564
+    "security": {
565
+        "insecureRoomNameWarning": "The room name is insecure. Unwanted participants may join your conference."
566
+    },
564 567
     "settings": {
565 568
         "calendar": {
566 569
             "about": "The {{appName}} calendar integration is used to securely access your calendar so it can read upcoming events.",

+ 5
- 0
package-lock.json View File

@@ -19178,6 +19178,11 @@
19178 19178
           "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
19179 19179
         }
19180 19180
       }
19181
+    },
19182
+    "zxcvbn": {
19183
+      "version": "4.4.2",
19184
+      "resolved": "https://registry.npmjs.org/zxcvbn/-/zxcvbn-4.4.2.tgz",
19185
+      "integrity": "sha1-KOwXzwl0PtyrBW3dixsGJizHPDA="
19181 19186
     }
19182 19187
   }
19183 19188
 }

+ 2
- 1
package.json View File

@@ -93,7 +93,8 @@
93 93
     "util": "0.12.1",
94 94
     "uuid": "3.1.0",
95 95
     "windows-iana": "^3.1.0",
96
-    "xmldom": "0.1.27"
96
+    "xmldom": "0.1.27",
97
+    "zxcvbn": "4.4.2"
97 98
   },
98 99
   "devDependencies": {
99 100
     "@babel/core": "7.5.5",

+ 1
- 0
react/features/base/icons/svg/index.js View File

@@ -86,3 +86,4 @@ export { default as IconVideoQualitySD } from './SD.svg';
86 86
 export { default as IconVolume } from './volume.svg';
87 87
 export { default as IconVolumeEmpty } from './volume-empty.svg';
88 88
 export { default as IconVolumeOff } from './volume-off.svg';
89
+export { default as IconWarning } from './warning.svg';

+ 1
- 0
react/features/base/icons/svg/warning.svg View File

@@ -0,0 +1 @@
1
+<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/></svg>

+ 24
- 24
react/features/base/util/helpers.js View File

@@ -1,5 +1,29 @@
1 1
 // @flow
2 2
 
3
+/**
4
+ * A helper function that behaves similar to Object.assign, but only reassigns a
5
+ * property in target if it's defined in source.
6
+ *
7
+ * @param {Object} target - The target object to assign the values into.
8
+ * @param {Object} source - The source object.
9
+ * @returns {Object}
10
+ */
11
+export function assignIfDefined(target: Object, source: Object) {
12
+    const to = Object(target);
13
+
14
+    for (const nextKey in source) {
15
+        if (source.hasOwnProperty(nextKey)) {
16
+            const value = source[nextKey];
17
+
18
+            if (typeof value !== 'undefined') {
19
+                to[nextKey] = value;
20
+            }
21
+        }
22
+    }
23
+
24
+    return to;
25
+}
26
+
3 27
 /**
4 28
  * Creates a deferred object.
5 29
  *
@@ -72,30 +96,6 @@ export function getJitsiMeetGlobalNS() {
72 96
     return window.JitsiMeetJS.app;
73 97
 }
74 98
 
75
-/**
76
- * A helper function that behaves similar to Object.assign, but only reassigns a
77
- * property in target if it's defined in source.
78
- *
79
- * @param {Object} target - The target object to assign the values into.
80
- * @param {Object} source - The source object.
81
- * @returns {Object}
82
- */
83
-export function assignIfDefined(target: Object, source: Object) {
84
-    const to = Object(target);
85
-
86
-    for (const nextKey in source) {
87
-        if (source.hasOwnProperty(nextKey)) {
88
-            const value = source[nextKey];
89
-
90
-            if (typeof value !== 'undefined') {
91
-                to[nextKey] = value;
92
-            }
93
-        }
94
-    }
95
-
96
-    return to;
97
-}
98
-
99 99
 /**
100 100
  * Prints the error and reports it to the global error handler.
101 101
  *

+ 13
- 0
react/features/base/util/isInsecureRoomName.js View File

@@ -0,0 +1,13 @@
1
+// @flow
2
+
3
+import zxcvbn from 'zxcvbn';
4
+
5
+/**
6
+ * Returns true if the room name is considered a weak (insecure) one.
7
+ *
8
+ * @param {string} roomName - The room name.
9
+ * @returns {boolean}
10
+ */
11
+export default function isInsecureRoomName(roomName: string = ''): boolean {
12
+    return zxcvbn(roomName).score < 3;
13
+}

+ 57
- 0
react/features/conference/components/AbstractInsecureRoomNameLabel.js View File

@@ -0,0 +1,57 @@
1
+// @flow
2
+
3
+import { PureComponent } from 'react';
4
+
5
+import isInsecureRoomName from '../../base/util/isInsecureRoomName';
6
+
7
+type Props = {
8
+
9
+    /**
10
+     * True of the label should be visible.
11
+     */
12
+    _visible: boolean;
13
+
14
+    /**
15
+     * Function to be used to translate i18n labels.
16
+     */
17
+    t: Function
18
+}
19
+
20
+/**
21
+ * Abstrsact class for the {@Code InsecureRoomNameLabel} component.
22
+ */
23
+export default class AbstractInsecureRoomNameLabel extends PureComponent<Props> {
24
+    /**
25
+     * Implements {@code Component#render}.
26
+     *
27
+     * @inheritdoc
28
+     */
29
+    render() {
30
+        if (!this.props._visible) {
31
+            return null;
32
+        }
33
+
34
+        return this._render();
35
+    }
36
+
37
+    /**
38
+     * Renders the platform dependant content.
39
+     *
40
+     * @returns {ReactElement}
41
+     */
42
+    _render: () => Object;
43
+}
44
+
45
+/**
46
+ * Maps part of the Redux state to the props of this component.
47
+ *
48
+ * @param {Object} state - The Redux state.
49
+ * @returns {Props}
50
+ */
51
+export function _mapStateToProps(state: Object): $Shape<Props> {
52
+    const { room } = state['features/base/conference'];
53
+
54
+    return {
55
+        _visible: room && isInsecureRoomName(room)
56
+    };
57
+}

+ 14
- 0
react/features/conference/components/AbstractLabels.js View File

@@ -10,6 +10,8 @@ import { TranscribingLabel } from '../../transcribing';
10 10
 import { shouldDisplayTileView } from '../../video-layout';
11 11
 import { VideoQualityLabel } from '../../video-quality';
12 12
 
13
+import { InsecureRoomNameLabel } from '.';
14
+
13 15
 /**
14 16
  * The type of the React {@code Component} props of {@link AbstractLabels}.
15 17
  */
@@ -84,6 +86,18 @@ export default class AbstractLabels<P: Props, S> extends Component<P, S> {
84 86
         );
85 87
     }
86 88
 
89
+    /**
90
+     * Renders the {@code InsecureRoomNameLabel}.
91
+     *
92
+     * @protected
93
+     * @returns {React$Element}
94
+     */
95
+    _renderInsecureRoomNameLabel() {
96
+        return (
97
+            <InsecureRoomNameLabel />
98
+        );
99
+    }
100
+
87 101
     /**
88 102
      * Renders the {@code VideoQualityLabel} that is platform independent.
89 103
      *

+ 36
- 0
react/features/conference/components/native/InsecureRoomNameExpandedLabel.js View File

@@ -0,0 +1,36 @@
1
+// @flow
2
+
3
+import { translate } from '../../../base/i18n';
4
+import { ExpandedLabel, type Props as AbstractProps } from '../../../base/label';
5
+
6
+import { INSECURE_ROOM_NAME_LABEL_COLOR } from './styles';
7
+
8
+type Props = AbstractProps & {
9
+    t: Function
10
+}
11
+
12
+/**
13
+ * A react {@code Component} that implements an expanded label as tooltip-like
14
+ * component to explain the meaning of the {@code InsecureRoomNameExpandedLabel}.
15
+ */
16
+class InsecureRoomNameExpandedLabel extends ExpandedLabel<Props> {
17
+    /**
18
+     * Returns the color this expanded label should be rendered with.
19
+     *
20
+     * @returns {string}
21
+     */
22
+    _getColor() {
23
+        return INSECURE_ROOM_NAME_LABEL_COLOR;
24
+    }
25
+
26
+    /**
27
+     * Returns the label specific text of this {@code ExpandedLabel}.
28
+     *
29
+     * @returns {string}
30
+     */
31
+    _getLabel() {
32
+        return this.props.t('security.insecureRoomNameWarning');
33
+    }
34
+}
35
+
36
+export default translate(InsecureRoomNameExpandedLabel);

+ 31
- 0
react/features/conference/components/native/InsecureRoomNameLabel.js View File

@@ -0,0 +1,31 @@
1
+// @flow
2
+
3
+import React from 'react';
4
+
5
+import { IconWarning } from '../../../base/icons';
6
+import { CircularLabel } from '../../../base/label';
7
+import { connect } from '../../../base/redux';
8
+
9
+import AbstractInsecureRoomNameLabel, { _mapStateToProps } from '../AbstractInsecureRoomNameLabel';
10
+
11
+import styles from './styles';
12
+
13
+/**
14
+ * Renders a label indicating that we are in a room with an insecure name.
15
+ */
16
+class InsecureRoomNameLabel extends AbstractInsecureRoomNameLabel {
17
+    /**
18
+     * Renders the platform dependant content.
19
+     *
20
+     * @inheritdoc
21
+     */
22
+    _render() {
23
+        return (
24
+            <CircularLabel
25
+                icon = { IconWarning }
26
+                style = { styles.insecureRoomNameLabel } />
27
+        );
28
+    }
29
+}
30
+
31
+export default connect(_mapStateToProps)(InsecureRoomNameLabel);

+ 30
- 37
react/features/conference/components/native/Labels.js View File

@@ -20,6 +20,8 @@ import AbstractLabels, {
20 20
     type Props as AbstractLabelsProps
21 21
 } from '../AbstractLabels';
22 22
 import { shouldDisplayNotifications } from '../../functions';
23
+
24
+import InsecureRoomNameExpandedLabel from './InsecureRoomNameExpandedLabel';
23 25
 import styles from './styles';
24 26
 
25 27
 /**
@@ -32,14 +34,6 @@ type Props = AbstractLabelsProps & {
32 34
      */
33 35
     t: Function,
34 36
 
35
-    /**
36
-     * The indicator which determines whether the UI is reduced (to accommodate
37
-     * smaller display areas).
38
-     *
39
-     * @private
40
-     */
41
-    _reducedUI: boolean,
42
-
43 37
     /**
44 38
      * True if the labels should be visible, false otherwise.
45 39
      */
@@ -85,6 +79,7 @@ const LABEL_ID_QUALITY = 'quality';
85 79
 const LABEL_ID_RECORDING = 'recording';
86 80
 const LABEL_ID_STREAMING = 'streaming';
87 81
 const LABEL_ID_TRANSCRIBING = 'transcribing';
82
+const LABEL_ID_INSECURE_ROOM_NAME = 'insecure-room-name';
88 83
 
89 84
 /**
90 85
  * The {@code ExpandedLabel} components to be rendered for the individual
@@ -104,7 +99,8 @@ const EXPANDED_LABELS = {
104 99
             mode: JitsiRecordingConstants.mode.STREAM
105 100
         }
106 101
     },
107
-    transcribing: TranscribingExpandedLabel
102
+    transcribing: TranscribingExpandedLabel,
103
+    'insecure-room-name': InsecureRoomNameExpandedLabel
108 104
 };
109 105
 
110 106
 /**
@@ -159,7 +155,7 @@ class Labels extends AbstractLabels<Props, State> {
159 155
         }
160 156
 
161 157
         const wide = !isNarrowAspectRatio(this);
162
-        const { _filmstripVisible, _reducedUI } = this.props;
158
+        const { _filmstripVisible } = this.props;
163 159
 
164 160
         return (
165 161
             <View
@@ -200,24 +196,24 @@ class Labels extends AbstractLabels<Props, State> {
200 196
                             this._renderTranscribingLabel()
201 197
                         }
202 198
                     </TouchableOpacity>
203
-                    {/*
204
-                      * Emil, Lyubomir, Nichole, and Zoli said that the Labels
205
-                      * should not be rendered in Picture-in-Picture. Saul
206
-                      * argued that the recording Labels should be rendered. As
207
-                      * a temporary compromise, don't render the
208
-                      * VideoQualityLabel at least because it's not that
209
-                      * important.
210
-                      */
211
-                        _reducedUI || (
212
-                            <TouchableOpacity
213
-                                onLayout = {
214
-                                    this._createOnLayout(LABEL_ID_QUALITY) }
215
-                                onPress = {
216
-                                    this._createOnPress(LABEL_ID_QUALITY) } >
217
-                                { this._renderVideoQualityLabel() }
218
-                            </TouchableOpacity>
219
-                        )
220
-                    }
199
+                    <TouchableOpacity
200
+                        onLayout = {
201
+                            this._createOnLayout(LABEL_ID_INSECURE_ROOM_NAME)
202
+                        }
203
+                        onPress = {
204
+                            this._createOnPress(LABEL_ID_INSECURE_ROOM_NAME)
205
+                        } >
206
+                        {
207
+                            this._renderInsecureRoomNameLabel()
208
+                        }
209
+                    </TouchableOpacity>
210
+                    <TouchableOpacity
211
+                        onLayout = {
212
+                            this._createOnLayout(LABEL_ID_QUALITY) }
213
+                        onPress = {
214
+                            this._createOnPress(LABEL_ID_QUALITY) } >
215
+                        { this._renderVideoQualityLabel() }
216
+                    </TouchableOpacity>
221 217
                 </View>
222 218
                 <View
223 219
                     style = { [
@@ -339,11 +335,13 @@ class Labels extends AbstractLabels<Props, State> {
339 335
         return null;
340 336
     }
341 337
 
342
-    _renderRecordingLabel: string => React$Element<*>;
338
+    _renderRecordingLabel: string => React$Element<any>;
339
+
340
+    _renderTranscribingLabel: () => React$Element<any>;
343 341
 
344
-    _renderTranscribingLabel: () => React$Element<*>
342
+    _renderInsecureRoomNameLabel: () => React$Element<any>;
345 343
 
346
-    _renderVideoQualityLabel: () => React$Element<*>;
344
+    _renderVideoQualityLabel: () => React$Element<any>;
347 345
 }
348 346
 
349 347
 /**
@@ -352,16 +350,11 @@ class Labels extends AbstractLabels<Props, State> {
352 350
  *
353 351
  * @param {Object} state - The redux state.
354 352
  * @private
355
- * @returns {{
356
- *     _filmstripVisible: boolean,
357
- *     _reducedUI: boolean,
358
- *     _visible: boolean
359
- * }}
353
+ * @returns {Props}
360 354
  */
361 355
 function _mapStateToProps(state) {
362 356
     return {
363 357
         ..._abstractMapStateToProps(state),
364
-        _reducedUI: state['features/base/responsive-ui'].reducedUI,
365 358
         _visible: !shouldDisplayNotifications(state)
366 359
     };
367 360
 }

+ 1
- 0
react/features/conference/components/native/index.js View File

@@ -2,3 +2,4 @@
2 2
 
3 3
 export { default as Conference } from './Conference';
4 4
 export { default as renderConferenceTimer } from './ConferenceTimerDisplay';
5
+export { default as InsecureRoomNameLabel } from './InsecureRoomNameLabel';

+ 5
- 0
react/features/conference/components/native/styles.js View File

@@ -3,6 +3,7 @@ import { ColorSchemeRegistry, schemeColor } from '../../../base/color-scheme';
3 3
 import { FILMSTRIP_SIZE } from '../../../filmstrip';
4 4
 
5 5
 export const NAVBAR_GRADIENT_COLORS = [ '#000000FF', '#00000000' ];
6
+export const INSECURE_ROOM_NAME_LABEL_COLOR = ColorPalette.warning;
6 7
 
7 8
 // From brand guideline
8 9
 const BOTTOM_GRADIENT_HEIGHT = 290;
@@ -167,6 +168,10 @@ export default {
167 168
         // On iPhone X there is the notch. In the two cases BoxModel.margin is
168 169
         // not enough.
169 170
         top: BoxModel.margin * 3
171
+    },
172
+
173
+    insecureRoomNameLabel: {
174
+        backgroundColor: INSECURE_ROOM_NAME_LABEL_COLOR
170 175
     }
171 176
 };
172 177
 

+ 35
- 0
react/features/conference/components/web/InsecureRoomNameLabel.js View File

@@ -0,0 +1,35 @@
1
+// @flow
2
+
3
+import Tooltip from '@atlaskit/tooltip';
4
+import React from 'react';
5
+
6
+import { translate } from '../../../base/i18n';
7
+import { IconWarning } from '../../../base/icons';
8
+import { CircularLabel } from '../../../base/label';
9
+import { connect } from '../../../base/redux';
10
+
11
+import AbstractInsecureRoomNameLabel, { _mapStateToProps } from '../AbstractInsecureRoomNameLabel';
12
+
13
+/**
14
+ * Renders a label indicating that we are in a room with an insecure name.
15
+ */
16
+class InsecureRoomNameLabel extends AbstractInsecureRoomNameLabel {
17
+    /**
18
+     * Renders the platform dependant content.
19
+     *
20
+     * @inheritdoc
21
+     */
22
+    _render() {
23
+        return (
24
+            <Tooltip
25
+                content = { this.props.t('security.insecureRoomNameWarning') }
26
+                position = 'left'>
27
+                <CircularLabel
28
+                    className = 'insecure'
29
+                    icon = { IconWarning } />
30
+            </Tooltip>
31
+        );
32
+    }
33
+}
34
+
35
+export default translate(connect(_mapStateToProps)(InsecureRoomNameLabel));

+ 5
- 0
react/features/conference/components/web/Labels.js View File

@@ -95,6 +95,9 @@ class Labels extends AbstractLabels<Props, State> {
95 95
                     this.props._showVideoQualityLabel
96 96
                         && this._renderVideoQualityLabel()
97 97
                 }
98
+                {
99
+                    this._renderInsecureRoomNameLabel()
100
+                }
98 101
             </div>
99 102
         );
100 103
     }
@@ -107,6 +110,8 @@ class Labels extends AbstractLabels<Props, State> {
107 110
 
108 111
     _renderTranscribingLabel: () => React$Element<*>;
109 112
 
113
+    _renderInsecureRoomNameLabel: () => React$Element<any>;
114
+
110 115
     _renderVideoQualityLabel: () => React$Element<*>;
111 116
 }
112 117
 

+ 1
- 1
react/features/conference/components/web/index.js View File

@@ -2,4 +2,4 @@
2 2
 
3 3
 export { default as Conference } from './Conference';
4 4
 export { default as renderConferenceTimer } from './ConferenceTimerDisplay';
5
-
5
+export { default as InsecureRoomNameLabel } from './InsecureRoomNameLabel';

+ 29
- 1
react/features/welcome/components/AbstractWelcomePage.js View File

@@ -6,6 +6,7 @@ import type { Dispatch } from 'redux';
6 6
 
7 7
 import { createWelcomePageEvent, sendAnalytics } from '../../analytics';
8 8
 import { appNavigate } from '../../app';
9
+import isInsecureRoomName from '../../base/util/isInsecureRoomName';
9 10
 import { isCalendarEnabled } from '../../calendar-sync';
10 11
 import { isRecentListEnabled } from '../../recent-list/functions';
11 12
 
@@ -75,6 +76,7 @@ export class AbstractWelcomePage extends Component<Props, *> {
75 76
     state = {
76 77
         animateTimeoutId: undefined,
77 78
         generatedRoomname: '',
79
+        insecureRoomName: false,
78 80
         joining: false,
79 81
         room: '',
80 82
         roomPlaceholder: '',
@@ -95,6 +97,7 @@ export class AbstractWelcomePage extends Component<Props, *> {
95 97
             = this._animateRoomnameChanging.bind(this);
96 98
         this._onJoin = this._onJoin.bind(this);
97 99
         this._onRoomChange = this._onRoomChange.bind(this);
100
+        this._renderInsecureRoomNameWarning = this._renderInsecureRoomNameWarning.bind(this);
98 101
         this._updateRoomname = this._updateRoomname.bind(this);
99 102
     }
100 103
 
@@ -160,6 +163,13 @@ export class AbstractWelcomePage extends Component<Props, *> {
160 163
         clearTimeout(this.state.updateTimeoutId);
161 164
     }
162 165
 
166
+    /**
167
+     * Renders the insecure room name warning.
168
+     *
169
+     * @returns {ReactElement}
170
+     */
171
+    _doRenderInsecureRoomNameWarning: () => React$Component<any>;
172
+
163 173
     _onJoin: () => void;
164 174
 
165 175
     /**
@@ -202,7 +212,25 @@ export class AbstractWelcomePage extends Component<Props, *> {
202 212
      * @returns {void}
203 213
      */
204 214
     _onRoomChange(value: string) {
205
-        this.setState({ room: value });
215
+        this.setState({
216
+            room: value,
217
+            insecureRoomName: value && isInsecureRoomName(value)
218
+        });
219
+    }
220
+
221
+    _renderInsecureRoomNameWarning: () => React$Component<any>;;
222
+
223
+    /**
224
+     * Renders the insecure room name warning if needed.
225
+     *
226
+     * @returns {ReactElement}
227
+     */
228
+    _renderInsecureRoomNameWarning() {
229
+        if (this.state.insecureRoomName) {
230
+            return this._doRenderInsecureRoomNameWarning();
231
+        }
232
+
233
+        return null;
206 234
     }
207 235
 
208 236
     _updateRoomname: () => void;

+ 27
- 1
react/features/welcome/components/WelcomePage.native.js View File

@@ -13,7 +13,7 @@ import { getName } from '../../app';
13 13
 
14 14
 import { ColorSchemeRegistry } from '../../base/color-scheme';
15 15
 import { translate } from '../../base/i18n';
16
-import { Icon, IconMenu } from '../../base/icons';
16
+import { Icon, IconMenu, IconWarning } from '../../base/icons';
17 17
 import { MEDIA_TYPE } from '../../base/media';
18 18
 import { Header, LoadingIndicator, Text } from '../../base/react';
19 19
 import { connect } from '../../base/redux';
@@ -119,6 +119,28 @@ class WelcomePage extends AbstractWelcomePage {
119 119
         return this._renderFullUI();
120 120
     }
121 121
 
122
+    /**
123
+     * Renders the insecure room name warning.
124
+     *
125
+     * @inheritdoc
126
+     */
127
+    _doRenderInsecureRoomNameWarning() {
128
+        return (
129
+            <View
130
+                style = { [
131
+                    styles.messageContainer,
132
+                    styles.insecureRoomNameWarningContainer
133
+                ] }>
134
+                <Icon
135
+                    src = { IconWarning }
136
+                    style = { styles.insecureRoomNameWarningIcon } />
137
+                <Text style = { styles.insecureRoomNameWarningText }>
138
+                    { this.props.t('security.insecureRoomNameWarning') }
139
+                </Text>
140
+            </View>
141
+        );
142
+    }
143
+
122 144
     /**
123 145
      * Constructs a style array to handle the hint box animation.
124 146
      *
@@ -127,6 +149,7 @@ class WelcomePage extends AbstractWelcomePage {
127 149
      */
128 150
     _getHintBoxStyle() {
129 151
         return [
152
+            styles.messageContainer,
130 153
             styles.hintContainer,
131 154
             {
132 155
                 opacity: this.state.hintBoxAnimation
@@ -283,6 +306,9 @@ class WelcomePage extends AbstractWelcomePage {
283 306
                                 style = { styles.textInput }
284 307
                                 underlineColorAndroid = 'transparent'
285 308
                                 value = { this.state.room } />
309
+                            {
310
+                                this._renderInsecureRoomNameWarning()
311
+                            }
286 312
                             {
287 313
                                 this._renderHintBox()
288 314
                             }

+ 18
- 0
react/features/welcome/components/WelcomePage.web.js View File

@@ -3,6 +3,7 @@
3 3
 import React from 'react';
4 4
 
5 5
 import { translate } from '../../base/i18n';
6
+import { Icon, IconWarning } from '../../base/icons';
6 7
 import { Watermarks } from '../../base/react';
7 8
 import { connect } from '../../base/redux';
8 9
 import { isMobileBrowser } from '../../base/environment/utils';
@@ -209,6 +210,7 @@ class WelcomePage extends AbstractWelcomePage {
209 210
                                     title = { t('welcomepage.roomNameAllowedChars') }
210 211
                                     type = 'text'
211 212
                                     value = { this.state.room } />
213
+                                { this._renderInsecureRoomNameWarning() }
212 214
                             </form>
213 215
                         </div>
214 216
                         <div
@@ -233,6 +235,22 @@ class WelcomePage extends AbstractWelcomePage {
233 235
         );
234 236
     }
235 237
 
238
+    /**
239
+     * Renders the insecure room name warning.
240
+     *
241
+     * @inheritdoc
242
+     */
243
+    _doRenderInsecureRoomNameWarning() {
244
+        return (
245
+            <div className = 'insecure-room-name-warning'>
246
+                <Icon src = { IconWarning } />
247
+                <span>
248
+                    { this.props.t('security.insecureRoomNameWarning') }
249
+                </span>
250
+            </div>
251
+        );
252
+    }
253
+
236 254
     /**
237 255
      * Prevents submission of the form and delegates join logic.
238 256
      *

+ 28
- 8
react/features/welcome/components/styles.js View File

@@ -108,15 +108,8 @@ export default {
108 108
      * Container for the hint box.
109 109
      */
110 110
     hintContainer: {
111
-        backgroundColor: ColorPalette.white,
112
-        borderColor: ColorPalette.white,
113
-        borderRadius: 4,
114
-        borderWidth: 1,
115 111
         flexDirection: 'column',
116
-        marginVertical: 5,
117
-        overflow: 'hidden',
118
-        paddingHorizontal: BoxModel.padding,
119
-        paddingVertical: 2 * BoxModel.padding
112
+        overflow: 'hidden'
120 113
     },
121 114
 
122 115
     /**
@@ -148,6 +141,16 @@ export default {
148 141
         padding: BoxModel.padding
149 142
     },
150 143
 
144
+    messageContainer: {
145
+        backgroundColor: ColorPalette.white,
146
+        borderColor: ColorPalette.white,
147
+        borderRadius: 4,
148
+        borderWidth: 1,
149
+        marginVertical: 5,
150
+        paddingHorizontal: BoxModel.padding,
151
+        paddingVertical: 2 * BoxModel.padding
152
+    },
153
+
151 154
     /**
152 155
      * The style of the top-level container/{@code View} of
153 156
      * {@code LocalVideoTrackUnderlay}.
@@ -280,6 +283,23 @@ export default {
280 283
         textAlign: 'center'
281 284
     },
282 285
 
286
+    insecureRoomNameWarningContainer: {
287
+        alignItems: 'center',
288
+        flexDirection: 'row',
289
+        paddingHorizontal: 5
290
+    },
291
+
292
+    insecureRoomNameWarningIcon: {
293
+        color: ColorPalette.warning,
294
+        fontSize: 24,
295
+        marginRight: 10
296
+    },
297
+
298
+    insecureRoomNameWarningText: {
299
+        color: ColorPalette.warning,
300
+        flex: 1
301
+    },
302
+
283 303
     /**
284 304
      * The style of the top-level container of {@code WelcomePage}.
285 305
      */

+ 1
- 1
webpack.config.js View File

@@ -179,7 +179,7 @@ module.exports = [
179 179
         entry: {
180 180
             'app.bundle': './app.js'
181 181
         },
182
-        performance: getPerformanceHints(3 * 1024 * 1024)
182
+        performance: getPerformanceHints(4 * 1024 * 1024)
183 183
     }),
184 184
     Object.assign({}, config, {
185 185
         entry: {

Loading…
Cancel
Save