Browse Source

feat(prejoin) improve ux

j8
Tudor-Ovidiu Avram 4 years ago
parent
commit
478f1a731e

+ 29
- 5
css/_connection-status.scss View File

1
 .con-status {
1
 .con-status {
2
     position: absolute;
2
     position: absolute;
3
-    top: 40px;
3
+    top: 24px;
4
     width: 100%;
4
     width: 100%;
5
     z-index: $toolbarZ + 3;
5
     z-index: $toolbarZ + 3;
6
 
6
 
7
     &-container {
7
     &-container {
8
-        background: rgba(28, 32, 37, .5);
9
         border-radius: 3px;
8
         border-radius: 3px;
10
         color: #fff;
9
         color: #fff;
11
         font-size: 13px;
10
         font-size: 13px;
12
-        line-height: 20px;
11
+        line-height: 13px;
13
         margin: 0 auto;
12
         margin: 0 auto;
14
-        width: 304px;
13
+        width: 320px;
15
     }
14
     }
16
 
15
 
17
     &-header {
16
     &-header {
17
+        background: rgba(28, 32, 37, .5);
18
         align-items: center;
18
         align-items: center;
19
         display: flex;
19
         display: flex;
20
         justify-content: space-between;
20
         justify-content: space-between;
21
-        padding: 8px;
22
     }
21
     }
23
 
22
 
24
     &-circle {
23
     &-circle {
25
         border-radius: 50%;
24
         border-radius: 50%;
26
         display: inline-block;
25
         display: inline-block;
27
         padding: 4px;
26
         padding: 4px;
27
+        margin: 8px;
28
     }
28
     }
29
 
29
 
30
     &--good {
30
     &--good {
40
     }
40
     }
41
 
41
 
42
     &-arrow {
42
     &-arrow {
43
+        height: 36px;
44
+        width: 36px;
45
+        border-radius: 3px;
46
+        margin-left: 8px;
47
+        margin-right: 2px;
48
+        display: flex;
49
+        align-items: center;
50
+        justify-content: center;
51
+        transition: background-color 0.16s ease-out;
52
+
43
         &--up {
53
         &--up {
44
             transform: rotate(180deg);
54
             transform: rotate(180deg);
45
         }
55
         }
47
         &>svg {
57
         &>svg {
48
             cursor: pointer;
58
             cursor: pointer;
49
         }
59
         }
60
+
61
+        &:hover {
62
+            background-color: rgba(1,1,1, 0.1);
63
+        }
50
     }
64
     }
51
 
65
 
52
     &-text {
66
     &-text {
54
     }
68
     }
55
 
69
 
56
     &-details {
70
     &-details {
71
+        background: rgba(28, 32, 37, .5);
57
         border-top: 1px solid #5E6D7A;
72
         border-top: 1px solid #5E6D7A;
58
         padding: 16px;
73
         padding: 16px;
74
+        transition: opacity 0.16s ease-out;
75
+
76
+        &-visible {
77
+            opacity: 1;
78
+        }
79
+
80
+        &-hidden {
81
+            opacity: 0;
82
+        }
59
     }
83
     }
60
 }
84
 }

+ 0
- 26
css/_lobby.scss View File

14
                 margin: 10px;
14
                 margin: 10px;
15
             }
15
             }
16
         }
16
         }
17
-
18
-        .form {
19
-            align-items: stretch;
20
-            display: flex;
21
-            flex-direction: column;
22
-            min-width: 400px;
23
-        }
24
-
25
-        .participant-info {
26
-            align-items: center;
27
-            display: flex;
28
-            flex-direction: column;
29
-        }
30
     }
17
     }
31
 }
18
 }
32
 
19
 
100
         }
87
         }
101
     }
88
     }
102
 
89
 
103
-    input {
104
-        align-self: stretch;
105
-        background-color: transparent;
106
-        border: 1px solid #B8C7E0;
107
-        border-radius: 4px;
108
-        color: white;
109
-        padding: 12px 8px;
110
-
111
-        &:focus {
112
-            border-color: rgb(3, 118, 218);
113
-        }
114
-    }
115
-
116
     button {
90
     button {
117
         align-self: stretch;
91
         align-self: stretch;
118
         margin: 8px 0;
92
         margin: 8px 0;

+ 4
- 72
css/_prejoin.scss View File

3
     &-input-area {
3
     &-input-area {
4
         margin: 0 auto;
4
         margin: 0 auto;
5
         text-align: center;
5
         text-align: center;
6
-        width: 320px;
7
     }
6
     }
8
 
7
 
9
     &-title {
8
     &-title {
42
 
41
 
43
     &-error {
42
     &-error {
44
         color: white;
43
         color: white;
45
-        background-color: rgba(229, 75, 75, 0.5);
44
+        background-color: rgba(225, 45, 45, 0.6);
45
+        border-radius: 3px;
46
         width: 100%;
46
         width: 100%;
47
-        padding: 3px;
47
+        padding: 2px;
48
+        box-sizing: border-box;
48
         margin-top: 4px;
49
         margin-top: 4px;
49
         font-size: 13px;
50
         font-size: 13px;
50
         text-align: center;
51
         text-align: center;
58
 }
59
 }
59
 
60
 
60
 .prejoin-preview {
61
 .prejoin-preview {
61
-    height: 100%;
62
-    position: absolute;
63
-    width: 100%;
64
-
65
-    &--no-video {
66
-        background: radial-gradient(50% 50% at 50% 50%, #5B6F80 0%, #365067 100%), #FFFFFF;
67
-        text-align: center;
68
-    }
69
-
70
-    &-video {
71
-        height: 100%;
72
-        object-fit: cover;
73
-        position: absolute;
74
-        width: 100%;
75
-    }
76
-
77
-    &-name {
78
-        color: #fff;
79
-        font-size: 19px;
80
-        line-height: 28px;
81
-
82
-        &--editable {
83
-            background: none;
84
-            border: 0;
85
-            border-bottom: 1px solid #D1DBE8;
86
-            margin: 24px 0 16px 0;
87
-            outline: none;
88
-            text-align: center;
89
-            width: 100%;
90
-
91
-            &::-webkit-input-placeholder {
92
-                @include name-placeholder;
93
-            }
94
-            &::-moz-placeholder {
95
-                @include name-placeholder;
96
-            }
97
-            &:-ms-input-placeholder {
98
-                @include name-placeholder;
99
-            }
100
-        }
101
-
102
-        &--text {
103
-            margin: 16px 0;
104
-            outline: none;
105
-        }
106
-    }
107
-
108
-    &-avatar.avatar {
109
-        background: #A4B8D1;
110
-        margin: 200px auto 0 auto;
111
-    }
112
-
113
-    &-overlay {
114
-        height: 100%;
115
-        position: absolute;
116
-        width: 100%;
117
-        z-index: 1;
118
-        background: linear-gradient(0deg, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3));
119
-    }
120
-
121
-    &-bottom-overlay {
122
-        background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.9) 100%);
123
-        bottom: 0;
124
-        height: 50%;
125
-        position: absolute;
126
-        width: 100%;
127
-        z-index: 1;
128
-    }
129
-
130
     &-status {
62
     &-status {
131
         align-items: center;
63
         align-items: center;
132
         align-self: stretch;
64
         align-self: stretch;

+ 41
- 28
css/_premeeting-screens.scss View File

12
 
12
 
13
  .premeeting-screen {
13
  .premeeting-screen {
14
     align-items: stretch;
14
     align-items: stretch;
15
-    background: radial-gradient(50% 50% at 50% 50%, #5D95C7 0%, #376288 100%), #FFFFFF;
15
+    background: radial-gradient(50% 50% at 50% 50%, #2A3A4B 20.83%, #1E2A36 100%);
16
     display: flex;
16
     display: flex;
17
     flex-direction: column;
17
     flex-direction: column;
18
     font-size: 1.3em;
18
     font-size: 1.3em;
19
     z-index: $toolbarZ + 1;
19
     z-index: $toolbarZ + 1;
20
 
20
 
21
+    &-avatar {
22
+        background-color: #A4B8D1;
23
+        margin-bottom: 24px;
24
+
25
+        text {
26
+            fill: black;
27
+            font-size: 26px;
28
+            font-weight: 400;  
29
+        }
30
+    }
31
+
21
     .action-btn {
32
     .action-btn {
22
         border-radius: 3px;
33
         border-radius: 3px;
23
         color: #fff;
34
         color: #fff;
59
                     fill: #AFB6BC;
70
                     fill: #AFB6BC;
60
                 }
71
                 }
61
             }
72
             }
62
-
63
-            .options {
64
-                border-left: 1px solid #AFB6BC;
65
-            }
66
         }
73
         }
67
 
74
 
68
         .options {
75
         .options {
76
+            border-radius: 3px;
69
             align-items: center;
77
             align-items: center;
70
-            border-left: 1px solid #fff;
71
             display: flex;
78
             display: flex;
72
             height: 100%;
79
             height: 100%;
73
             justify-content: center;
80
             justify-content: center;
74
             position: absolute;
81
             position: absolute;
75
             right: 0;
82
             right: 0;
76
             top: 0;
83
             top: 0;
77
-            width: 40px;
84
+            width: 36px;
85
+
86
+            &:hover {
87
+                background-color: #0262B6;
88
+            }
89
+
90
+            svg {
91
+                pointer-events: none;
92
+            }
78
         }
93
         }
79
     }
94
     }
80
 
95
 
111
             margin-bottom: 16px;
126
             margin-bottom: 16px;
112
 
127
 
113
             .url {
128
             .url {
129
+                background: rgba(28, 32, 37, 0.5);
130
+                border-radius: 4px;
114
                 display: flex;
131
                 display: flex;
115
                 padding: 8px 10px;
132
                 padding: 8px 10px;
133
+                transition: background 0.16s ease-out;
116
 
134
 
117
                 &:hover {
135
                 &:hover {
118
                     background: #1C2025;
136
                     background: #1C2025;
119
-                    border-radius: 4px;
120
                 }
137
                 }
121
 
138
 
122
                 &.done {
139
                 &.done {
149
         }
166
         }
150
 
167
 
151
         input.field {
168
         input.field {
152
-            background-color: transparent;
153
-            border: 1px solid transparent;
154
-            color: white;
155
-            outline-width: 0;
169
+            background-color: white;
170
+            border: none;
171
+            outline: none;
172
+            border-radius: 3px;
173
+            font-size: 15px;
174
+            line-height: 24px;
175
+            color: #1C2025;
156
             padding: 8px 0;
176
             padding: 8px 0;
157
             text-align: center;
177
             text-align: center;
158
-            width: 100%;
178
+            width: 320px;
159
 
179
 
160
-            &.focused {
161
-                border-bottom: 1px solid white;
180
+            &.error {
181
+                box-shadow: 0px 0px 4px 3px rgba(225, 45, 45, 0.4);
162
             }
182
             }
163
 
183
 
164
-            &.error::placeholder {
165
-                color: $defaultWarningColor;
184
+            &.focused {
185
+                box-shadow: 0px 0px 4px 3px #0376DA;
166
             }
186
             }
167
         }
187
         }
168
     }
188
     }
170
     .media-btn-container {
190
     .media-btn-container {
171
         display: flex;
191
         display: flex;
172
         justify-content: center;
192
         justify-content: center;
173
-        margin: 32px 0;
193
+        margin: 24px 0 16px 0;
174
         width: 100%;
194
         width: 100%;
175
 
195
 
176
         &> div {
196
         &> div {
233
     font-size: 13px;
253
     font-size: 13px;
234
     height: 40px;
254
     height: 40px;
235
     margin: 0 auto;
255
     margin: 0 auto;
256
+    transition: background 0.16s ease-out;
236
     width: 320px;
257
     width: 320px;
237
 
258
 
238
     @include flex-centered();
259
     @include flex-centered();
242
     }
263
     }
243
 
264
 
244
     &:hover {
265
     &:hover {
245
-        background: #1C2025;
266
+        background: rgba(255, 255, 255, 0.1);
246
 
267
 
247
         @include icon-container(#A4B8D1, #1C2025);
268
         @include icon-container(#A4B8D1, #1C2025);
248
     }
269
     }
261
     }
282
     }
262
 
283
 
263
     &--toggled {
284
     &--toggled {
264
-        background: #75757A;
265
-
266
-        &:hover {
267
-            background: #75757A;
268
-
269
-            @include icon-container(#A4B8D1, #75757A);
270
-        }
271
-
272
-        @include icon-container(#A4B8D1, #75757A);
285
+        @include icon-container(white, #1C2025);
273
     }
286
     }
274
 }
287
 }

+ 1
- 1
lang/main.json View File

536
         "dialInMeeting": "Dial into the meeting",
536
         "dialInMeeting": "Dial into the meeting",
537
         "dialInPin": "Dial into the meeting and enter PIN code:",
537
         "dialInPin": "Dial into the meeting and enter PIN code:",
538
         "dialing": "Dialing",
538
         "dialing": "Dialing",
539
-        "doNotShow": "Don't show this again",
539
+        "doNotShow": "Don't show this screen again",
540
         "errorDialOut": "Could not dial out",
540
         "errorDialOut": "Could not dial out",
541
         "errorDialOutDisconnected": "Could not dial out. Disconnected",
541
         "errorDialOutDisconnected": "Could not dial out. Disconnected",
542
         "errorDialOutFailed": "Could not dial out. Call failed",
542
         "errorDialOutFailed": "Could not dial out. Call failed",

+ 19
- 1
react/features/base/avatar/components/Avatar.js View File

37
      */
37
      */
38
     displayName?: string,
38
     displayName?: string,
39
 
39
 
40
+    /**
41
+     * Whether or not to update the background color of the avatar
42
+     */
43
+    dynamicColor?: Boolean,
44
+
40
     /**
45
     /**
41
      * ID of the element, if any.
46
      * ID of the element, if any.
42
      */
47
      */
78
  * Implements a class to render avatars in the app.
83
  * Implements a class to render avatars in the app.
79
  */
84
  */
80
 class Avatar<P: Props> extends PureComponent<P, State> {
85
 class Avatar<P: Props> extends PureComponent<P, State> {
86
+    /**
87
+     * Default values for {@code Avatar} component's properties.
88
+     *
89
+     * @static
90
+     */
91
+    static defaultProps = {
92
+        dynamicColor: true
93
+    };
94
+
81
     /**
95
     /**
82
      * Instantiates a new {@code Component}.
96
      * Instantiates a new {@code Component}.
83
      *
97
      *
123
             _loadableAvatarUrl,
137
             _loadableAvatarUrl,
124
             className,
138
             className,
125
             colorBase,
139
             colorBase,
140
+            dynamicColor,
126
             id,
141
             id,
127
             size,
142
             size,
128
             status,
143
             status,
156
         const initials = getInitials(_initialsBase);
171
         const initials = getInitials(_initialsBase);
157
 
172
 
158
         if (initials) {
173
         if (initials) {
159
-            avatarProps.color = getAvatarColor(colorBase || _initialsBase);
174
+            if (dynamicColor) {
175
+                avatarProps.color = getAvatarColor(colorBase || _initialsBase);
176
+            }
177
+
160
             avatarProps.initials = initials;
178
             avatarProps.initials = initials;
161
         }
179
         }
162
 
180
 

+ 3
- 0
react/features/base/icons/svg/arrow_up.svg View File

1
+<svg width="10" height="7" viewBox="0 0 10 7" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+<path fill-rule="evenodd" clip-rule="evenodd" d="M8.41115 6.05746C8.71903 6.39955 9.24594 6.42729 9.58803 6.1194C9.93012 5.81152 9.95786 5.28461 9.64997 4.94252L5.72917 0.562752C5.39813 0.194935 4.82138 0.194935 4.49034 0.562752L0.63061 4.94252C0.322728 5.28461 0.35046 5.81152 0.692552 6.1194C1.03464 6.42729 1.56155 6.39955 1.86943 6.05746L5.10975 2.36593L8.41115 6.05746Z" fill="white"/>
3
+</svg>

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

5
 export { default as IconArrowBack } from './arrow_back.svg';
5
 export { default as IconArrowBack } from './arrow_back.svg';
6
 export { default as IconArrowDown } from './arrow_down.svg';
6
 export { default as IconArrowDown } from './arrow_down.svg';
7
 export { default as IconArrowDownSmall } from './arrow-down-small.svg';
7
 export { default as IconArrowDownSmall } from './arrow-down-small.svg';
8
+export { default as IconArrowUp } from './arrow_up.svg';
8
 export { default as IconArrowLeft } from './arrow-left.svg';
9
 export { default as IconArrowLeft } from './arrow-left.svg';
9
 export { default as IconAudioOnly } from './visibility.svg';
10
 export { default as IconAudioOnly } from './visibility.svg';
10
 export { default as IconAudioOnlyOff } from './visibility-off.svg';
11
 export { default as IconAudioOnlyOff } from './visibility-off.svg';

+ 7
- 1
react/features/base/premeeting/components/web/ActionButton.js View File

26
      */
26
      */
27
     hasOptions?: boolean,
27
     hasOptions?: boolean,
28
 
28
 
29
+    /**
30
+     * Icon to display in the options section.
31
+     */
32
+    OptionsIcon?: React$Node,
33
+
29
     /**
34
     /**
30
      * TestId of the button. Can be used to locate element when testing UI.
35
      * TestId of the button. Can be used to locate element when testing UI.
31
      */
36
      */
57
     className = '',
62
     className = '',
58
     disabled,
63
     disabled,
59
     hasOptions,
64
     hasOptions,
65
+    OptionsIcon = IconArrowDown,
60
     testId,
66
     testId,
61
     type = 'primary',
67
     type = 'primary',
62
     onClick,
68
     onClick,
75
                 <Icon
81
                 <Icon
76
                     className = 'icon'
82
                     className = 'icon'
77
                     size = { 14 }
83
                     size = { 14 }
78
-                    src = { IconArrowDown } />
84
+                    src = { OptionsIcon } />
79
             </div>
85
             </div>
80
             }
86
             }
81
         </div>
87
         </div>

+ 0
- 61
react/features/base/premeeting/components/web/Avatar.js View File

1
-// @flow
2
-
3
-import React from 'react';
4
-
5
-import { Avatar } from '../../../avatar';
6
-import { connect } from '../../../redux';
7
-import { calculateAvatarDimensions } from '../../functions';
8
-
9
-type Props = {
10
-
11
-   /**
12
-    * The height of the window.
13
-    */
14
-    height: number,
15
-
16
-   /**
17
-    * The name of the participant (if any).
18
-    */
19
-    name: string
20
-}
21
-
22
-/**
23
- * Component displaying the avatar for the premeeting screen.
24
- *
25
- * @param {Props} props - The props of the component.
26
- * @returns {ReactElement}
27
- */
28
-function PremeetingAvatar({ height, name }: Props) {
29
-    const { marginTop, size } = calculateAvatarDimensions(height);
30
-
31
-    if (size <= 5) {
32
-        return null;
33
-    }
34
-
35
-
36
-    return (
37
-        <div style = {{ marginTop }}>
38
-            <Avatar
39
-                className = 'preview-avatar'
40
-                displayName = { name }
41
-                participantId = 'local'
42
-                size = { size } />
43
-        </div>
44
-    );
45
-}
46
-
47
-/**
48
- * Maps (parts of) the redux state to the React {@code Component} props.
49
- *
50
- * @param {Object} state - The redux state.
51
- * @returns {{
52
- *    height: number
53
- * }}
54
- */
55
-function mapStateToProps(state) {
56
-    return {
57
-        height: state['features/base/responsive-ui'].clientHeight
58
-    };
59
-}
60
-
61
-export default connect(mapStateToProps)(PremeetingAvatar);

+ 4
- 2
react/features/base/premeeting/components/web/ConnectionStatus.js View File

61
         ? 'con-status-arrow con-status-arrow--up'
61
         ? 'con-status-arrow con-status-arrow--up'
62
         : 'con-status-arrow';
62
         : 'con-status-arrow';
63
     const detailsText = connectionDetails.map(t).join(' ');
63
     const detailsText = connectionDetails.map(t).join(' ');
64
+    const detailsClassName = showDetails
65
+        ? 'con-status-details-visible'
66
+        : 'con-status-details-hidden';
64
 
67
 
65
     return (
68
     return (
66
         <div className = 'con-status'>
69
         <div className = 'con-status'>
79
                         size = { 24 }
82
                         size = { 24 }
80
                         src = { IconArrowDownSmall } />
83
                         src = { IconArrowDownSmall } />
81
                 </div>
84
                 </div>
82
-                { showDetails
83
-                  && <div className = 'con-status-details'>{detailsText}</div> }
85
+                <div className = { `con-status-details ${detailsClassName}` }>{detailsText}</div>
84
             </div>
86
             </div>
85
         </div>
87
         </div>
86
     );
88
     );

+ 9
- 2
react/features/base/premeeting/components/web/PreMeetingScreen.js View File

3
 import React, { PureComponent } from 'react';
3
 import React, { PureComponent } from 'react';
4
 
4
 
5
 import { AudioSettingsButton, VideoSettingsButton } from '../../../../toolbox/components/web';
5
 import { AudioSettingsButton, VideoSettingsButton } from '../../../../toolbox/components/web';
6
+import { Avatar } from '../../../avatar';
6
 
7
 
7
 import ConnectionStatus from './ConnectionStatus';
8
 import ConnectionStatus from './ConnectionStatus';
8
 import CopyMeetingUrl from './CopyMeetingUrl';
9
 import CopyMeetingUrl from './CopyMeetingUrl';
85
                 id = 'lobby-screen'>
86
                 id = 'lobby-screen'>
86
                 <ConnectionStatus />
87
                 <ConnectionStatus />
87
                 <Preview
88
                 <Preview
88
-                    name = { name }
89
-                    showAvatar = { showAvatar }
90
                     videoMuted = { videoMuted }
89
                     videoMuted = { videoMuted }
91
                     videoTrack = { videoTrack } />
90
                     videoTrack = { videoTrack } />
92
                 {!videoMuted && <div className = 'preview-overlay' />}
91
                 {!videoMuted && <div className = 'preview-overlay' />}
93
                 <div className = 'content'>
92
                 <div className = 'content'>
93
+                    {showAvatar && videoMuted && (
94
+                        <Avatar
95
+                            className = 'premeeting-screen-avatar'
96
+                            displayName = { name }
97
+                            dynamicColor = { false }
98
+                            participantId = 'local'
99
+                            size = { 80 } />
100
+                    )}
94
                     {showConferenceInfo && (
101
                     {showConferenceInfo && (
95
                         <>
102
                         <>
96
                             <div className = 'title'>
103
                             <div className = 'title'>

+ 1
- 27
react/features/base/premeeting/components/web/Preview.js View File

6
 import { connect } from '../../../redux';
6
 import { connect } from '../../../redux';
7
 import { getLocalVideoTrack } from '../../../tracks';
7
 import { getLocalVideoTrack } from '../../../tracks';
8
 
8
 
9
-import PreviewAvatar from './Avatar';
10
-
11
 export type Props = {
9
 export type Props = {
12
 
10
 
13
-    /**
14
-     * The name of the user that is about to join.
15
-     */
16
-    name: string,
17
-
18
-    /**
19
-     * Indicates whether the avatar should be shown when video is off
20
-     */
21
-    showAvatar: boolean,
22
-
23
     /**
11
     /**
24
      * Flag signaling the visibility of camera preview.
12
      * Flag signaling the visibility of camera preview.
25
      */
13
      */
38
  * @returns {ReactElement}
26
  * @returns {ReactElement}
39
  */
27
  */
40
 function Preview(props: Props) {
28
 function Preview(props: Props) {
41
-    const { name, showAvatar, videoMuted, videoTrack } = props;
29
+    const { videoMuted, videoTrack } = props;
42
 
30
 
43
     if (!videoMuted && videoTrack) {
31
     if (!videoMuted && videoTrack) {
44
         return (
32
         return (
50
         );
38
         );
51
     }
39
     }
52
 
40
 
53
-    if (showAvatar) {
54
-        return (
55
-            <div
56
-                className = 'no-video'
57
-                id = 'preview'>
58
-                <PreviewAvatar name = { name } />
59
-            </div>
60
-        );
61
-    }
62
-
63
     return null;
41
     return null;
64
 }
42
 }
65
 
43
 
66
-Preview.defaultProps = {
67
-    showAvatar: true
68
-};
69
-
70
 /**
44
 /**
71
  * Maps part of the Redux state to the props of this component.
45
  * Maps part of the Redux state to the props of this component.
72
  *
46
  *

+ 12
- 18
react/features/lobby/components/web/LobbyScreen.js View File

92
         const { t } = this.props;
92
         const { t } = this.props;
93
 
93
 
94
         return (
94
         return (
95
-            <div className = 'participant-info'>
96
-                <div className = 'form'>
97
-                    <InputField
98
-                        onChange = { this._onChangeDisplayName }
99
-                        placeHolder = { t('lobby.nameField') }
100
-                        testId = 'lobby.nameField'
101
-                        value = { displayName } />
102
-                </div>
103
-            </div>
95
+            <InputField
96
+                onChange = { this._onChangeDisplayName }
97
+                placeHolder = { t('lobby.nameField') }
98
+                testId = 'lobby.nameField'
99
+                value = { displayName } />
104
         );
100
         );
105
     }
101
     }
106
 
102
 
113
         const { _passwordJoinFailed, t } = this.props;
109
         const { _passwordJoinFailed, t } = this.props;
114
 
110
 
115
         return (
111
         return (
116
-            <div className = 'form'>
117
-                <InputField
118
-                    className = { _passwordJoinFailed ? 'error' : '' }
119
-                    onChange = { this._onChangePassword }
120
-                    placeHolder = { _passwordJoinFailed ? t('lobby.invalidPassword') : t('lobby.passwordField') }
121
-                    testId = 'lobby.password'
122
-                    type = 'password'
123
-                    value = { this.state.password } />
124
-            </div>
112
+            <InputField
113
+                className = { _passwordJoinFailed ? 'error' : '' }
114
+                onChange = { this._onChangePassword }
115
+                placeHolder = { _passwordJoinFailed ? t('lobby.invalidPassword') : t('lobby.passwordField') }
116
+                testId = 'lobby.password'
117
+                type = 'password'
118
+                value = { this.state.password } />
125
         );
119
         );
126
     }
120
     }
127
 
121
 

+ 4
- 1
react/features/prejoin/components/Prejoin.js View File

5
 
5
 
6
 import { getRoomName } from '../../base/conference';
6
 import { getRoomName } from '../../base/conference';
7
 import { translate } from '../../base/i18n';
7
 import { translate } from '../../base/i18n';
8
-import { Icon, IconPhone, IconVolumeOff } from '../../base/icons';
8
+import { Icon, IconArrowDown, IconArrowUp, IconPhone, IconVolumeOff } from '../../base/icons';
9
 import { isVideoMutedByUser } from '../../base/media';
9
 import { isVideoMutedByUser } from '../../base/media';
10
 import { ActionButton, InputField, PreMeetingScreen, ToggleButton } from '../../base/premeeting';
10
 import { ActionButton, InputField, PreMeetingScreen, ToggleButton } from '../../base/premeeting';
11
 import { connect } from '../../base/redux';
11
 import { connect } from '../../base/redux';
316
                         <div className = 'prejoin-input-area'>
316
                         <div className = 'prejoin-input-area'>
317
                             <InputField
317
                             <InputField
318
                                 autoFocus = { true }
318
                                 autoFocus = { true }
319
+                                className = { showError ? 'error' : '' }
320
+                                hasError = { showError }
319
                                 onChange = { _setName }
321
                                 onChange = { _setName }
320
                                 onSubmit = { joinConference }
322
                                 onSubmit = { joinConference }
321
                                 placeHolder = { t('dialog.enterDisplayName') }
323
                                 placeHolder = { t('dialog.enterDisplayName') }
352
                                     isOpen = { showJoinByPhoneButtons }
354
                                     isOpen = { showJoinByPhoneButtons }
353
                                     onClose = { _onDropdownClose }>
355
                                     onClose = { _onDropdownClose }>
354
                                     <ActionButton
356
                                     <ActionButton
357
+                                        OptionsIcon = { showJoinByPhoneButtons ? IconArrowUp : IconArrowDown }
355
                                         hasOptions = { true }
358
                                         hasOptions = { true }
356
                                         onClick = { _onJoinButtonClick }
359
                                         onClick = { _onJoinButtonClick }
357
                                         onOptionsClick = { _onOptionsClick }
360
                                         onOptionsClick = { _onOptionsClick }

Loading…
Cancel
Save