Browse Source

feat(welcome_page): Redesign welcome page

j8
Vlad Piersec 4 years ago
parent
commit
f8a41aea9c

+ 68
- 25
css/_meetings_list.scss View File

7
     display: flex;
7
     display: flex;
8
     flex-direction: column;
8
     flex-direction: column;
9
     position: relative;
9
     position: relative;
10
-    width: 100%;
11
-    height: 100%;
12
     overflow: auto;
10
     overflow: auto;
11
+    width: 100%;
13
 
12
 
14
     .meetings-list-empty {
13
     .meetings-list-empty {
15
         text-align: center;
14
         text-align: center;
20
         flex-direction: column;
19
         flex-direction: column;
21
 
20
 
22
         .description {
21
         .description {
23
-            font-size: 16px;
24
-            padding: 20px;
22
+           color: #2f3237;
23
+           font-size: 14px;
24
+           line-height: 18px;
25
+           margin-bottom: 16px;
26
+           max-width: 436px;
25
         }
27
         }
26
     }
28
     }
27
 
29
 
30
+    .meetings-list-empty-image {
31
+        text-align: center;
32
+        margin: 24px 0 20px 0;
33
+    }
34
+
35
+    .meetings-list-empty-button {
36
+        align-items: center;
37
+        color: #0163FF;
38
+        cursor: pointer;
39
+        display: flex;
40
+        font-size: 14px;
41
+        line-height: 18px;
42
+        margin: 24px 0 32px 0;
43
+    }
44
+
45
+    .meetings-list-empty-icon {
46
+        display: inline-block;
47
+        margin-right: 8px;
48
+    }
49
+
28
     .button {
50
     .button {
29
         background: #0074E0;
51
         background: #0074E0;
30
         border-radius: 4px;
52
         border-radius: 4px;
32
         display: flex;
54
         display: flex;
33
         justify-content: center;
55
         justify-content: center;
34
         align-items: center;
56
         align-items: center;
35
-        padding: 5px 10px;
57
+        padding: 8px;
36
         cursor: pointer;
58
         cursor: pointer;
37
     }
59
     }
38
 
60
 
43
     }
65
     }
44
 
66
 
45
     .item {
67
     .item {
46
-        background: rgba(255,255,255,0.50);
68
+        background: #fff;
47
         box-sizing: border-box;
69
         box-sizing: border-box;
70
+        border-radius: 4px;
48
         display: inline-flex;
71
         display: inline-flex;
49
-        margin-top: 5px;
50
-        min-height: 92px;
51
-        width: 100%;
72
+        margin: 4px 4px 0 4px;
73
+        min-height: 60px;
74
+        width: calc(100% - 8px);
52
         word-break: break-word;
75
         word-break: break-word;
53
         display: flex;
76
         display: flex;
54
         flex-direction: row;
77
         flex-direction: row;
61
         .left-column {
84
         .left-column {
62
             display: flex;
85
             display: flex;
63
             flex-direction: column;
86
             flex-direction: column;
64
-            width: 140px;
65
             flex-grow: 0;
87
             flex-grow: 0;
66
-            padding-left: 30px;
67
-            padding-top: 25px;
68
-
69
-            .date {
70
-                font-weight: bold;
71
-                padding-bottom: 5px;
72
-            }
88
+            padding-left: 16px;
89
+            padding-top: 13px;
73
         }
90
         }
74
 
91
 
75
         .right-column {
92
         .right-column {
76
             display: flex;
93
             display: flex;
77
             flex-direction: column;
94
             flex-direction: column;
78
             flex-grow: 1;
95
             flex-grow: 1;
79
-            padding-left: 30px;
80
-            padding-top: 25px;
96
+            padding-left: 16px;
97
+            padding-top: 13px;
98
+            position: relative;
99
+        }
81
 
100
 
82
-            .title {
83
-                font-size: 16px;
84
-                font-weight: bold;
85
-                padding-bottom: 5px;
101
+        .title {
102
+                font-size: 12px;
103
+                font-weight: 600;
104
+                line-height: 16px;
105
+                padding-bottom: 4px;
86
             }
106
             }
107
+
108
+        .subtitle {
109
+            color: #5E6D7A;
110
+            font-weight: normal;
111
+            font-size: 12px;
112
+            line-height: 16px;
87
         }
113
         }
88
 
114
 
115
+
89
         .actions {
116
         .actions {
90
             display: flex;
117
             display: flex;
91
             align-items: center;
118
             align-items: center;
92
             justify-content: center;
119
             justify-content: center;
93
             flex-grow: 0;
120
             flex-grow: 0;
94
-            padding-right: 30px;
121
+            margin-right: 16px;
95
         }
122
         }
96
 
123
 
97
         &.with-click-handler {
124
         &.with-click-handler {
99
         }
126
         }
100
 
127
 
101
         &.with-click-handler:hover {
128
         &.with-click-handler:hover {
102
-            background-color: #75A7E7;
129
+            background-color: #c7ddff;
103
         }
130
         }
104
 
131
 
105
         .add-button {
132
         .add-button {
120
             display: block
147
             display: block
121
         }
148
         }
122
     }
149
     }
150
+
151
+    .delete-meeting {
152
+        display: none;
153
+        margin-right: 16px;
154
+        position: absolute;
155
+
156
+        &> svg {
157
+            fill: #0074e0;
158
+        }
159
+    }
160
+
161
+    .item:hover {
162
+        .delete-meeting {
163
+            display: block;
164
+        }
165
+    }
123
 }
166
 }

+ 61
- 0
css/_responsive.scss View File

30
 }
30
 }
31
 
31
 
32
 @media only screen and (max-width: $verySmallScreen) {
32
 @media only screen and (max-width: $verySmallScreen) {
33
+  .welcome {
34
+      #enter_room {
35
+        position: relative;
36
+        height: 42px;
37
+
38
+        .welcome-page-button {
39
+          font-size: 16px;
40
+          left: 0;
41
+          position: absolute;
42
+          top: 68px;
43
+          text-align: center;
44
+          width: 100%;
45
+        }
46
+      }
47
+
48
+      .header {
49
+          background: #06345E;
50
+          background-image: linear-gradient(180deg, rgba(8, 110, 202, 0.8) 0%, rgba(8, 110, 202, 0) 100%);
51
+
52
+          #enter_room {
53
+              .enter-room-input-container {
54
+                  padding-right: 0;
55
+              }
56
+
57
+              .warning-without-link,
58
+              .warning-with-link {
59
+                  top: 120px;
60
+              }
61
+          }
62
+      }
63
+
64
+      .welcome-tabs {
65
+          display: none;
66
+      }
67
+
68
+      .header-text-title {
69
+        text-align: center;
70
+      }
71
+
72
+      .welcome-cards-container {
73
+        padding: 0;
74
+      }
75
+
76
+      &.without-content {
77
+        .header {
78
+          height: 100%;
79
+        }
80
+      }
81
+
82
+      #moderated-meetings {
83
+          display: none;
84
+      }
85
+
86
+      .welcome-footer-row-block {
87
+          display: block;
88
+      }
89
+      .welcome-badge {
90
+          margin-right: 16px;
91
+      }
92
+  }
93
+
33
     #videoResolutionLabel {
94
     #videoResolutionLabel {
34
         display: none;
95
         display: none;
35
     }
96
     }

+ 18
- 42
css/_variables.scss View File

161
 /**
161
 /**
162
  * The size of the default watermark.
162
  * The size of the default watermark.
163
  */
163
  */
164
-$watermarkWidth: 186px;
165
-$watermarkHeight: 74px;
164
+$watermarkWidth: 71px;
165
+$watermarkHeight: 32px;
166
 
166
 
167
-$welcomePageWatermarkWidth: 186px;
168
-$welcomePageWatermarkHeight: 74px;
167
+$welcomePageWatermarkWidth: 71px;
168
+$welcomePageWatermarkHeight: 32px;
169
 
169
 
170
 /**
170
 /**
171
  * Welcome page variables.
171
  * Welcome page variables.
172
  */
172
  */
173
 $welcomePageDescriptionColor: #fff;
173
 $welcomePageDescriptionColor: #fff;
174
 $welcomePageFontFamily: inherit;
174
 $welcomePageFontFamily: inherit;
175
-$welcomePageBackground: linear-gradient(-90deg, #1251AE 0%, #0074FF 50%, #1251AE 100%);
175
+$welcomePageBackground: none;
176
 $welcomePageTitleColor: #fff;
176
 $welcomePageTitleColor: #fff;
177
 
177
 
178
-$welcomePageHeaderBackground: none;
179
-$welcomePageHeaderBackgroundSmall: none;
178
+$welcomePageHeaderBackground: linear-gradient(0deg, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2)), url('/images/welcome-background.png');
180
 $welcomePageHeaderBackgroundPosition: none;
179
 $welcomePageHeaderBackgroundPosition: none;
181
 $welcomePageHeaderBackgroundRepeat: none;
180
 $welcomePageHeaderBackgroundRepeat: none;
182
-$welcomePageHeaderBackgroundSize: none;
181
+$welcomePageHeaderBackgroundSize: cover;
183
 $welcomePageHeaderPaddingBottom: 0px;
182
 $welcomePageHeaderPaddingBottom: 0px;
184
-$welcomePageHeaderMinHeight: fit-content;
183
+$welcomePageHeaderTitleMaxWidth: initial;
184
+$welcomePageHeaderTextAlign: center;
185
 
185
 
186
-$welcomePageHeaderTextMarginTop: 35px;
187
-$welcomePageHeaderTextMarginBottom: 35px;
188
-$welcomePageHeaderTextDisplay: flex;
189
-$welcomePageHeaderTextWidth: 650px;
186
+$welcomePageHeaderContainerDisplay: flex;
187
+$welcomePageHeaderContainerMargin: 146px 32px 0 32px;
190
 
188
 
191
-$welcomePageHeaderTextTitleMarginBottom: 16px;
192
-$welcomePageHeaderTextTitleFontSize: 2.5rem;
193
-$welcomePageHeaderTextTitleFontWeight: 500;
194
-$welcomePageHeaderTextTitleLineHeight: 1.18;
189
+$welcomePageHeaderTextTitleMarginBottom: 0;
190
+$welcomePageHeaderTextTitleFontSize: 42px;
191
+$welcomePageHeaderTextTitleFontWeight: normal;
192
+$welcomePageHeaderTextTitleLineHeight: 50px;
195
 $welcomePageHeaderTextTitleOpacity: 1;
193
 $welcomePageHeaderTextTitleOpacity: 1;
196
 
194
 
197
-$welcomePageHeaderTextDescriptionDisplay: inherit;
198
-$welcomePageHeaderTextDescriptionFontSize: 1rem;
199
-$welcomePageHeaderTextDescriptionFontWeight: 400;
200
-$welcomePageHeaderTextDescriptionLineHeight: 24px;
201
-$welcomePageHeaderTextDescriptionMarginBottom: 20px;
202
-$welcomePageHeaderTextDescriptionAlignSelf: inherit;
203
-
204
 $welcomePageEnterRoomDisplay: flex;
195
 $welcomePageEnterRoomDisplay: flex;
205
-$welcomePageEnterRoomWidth: 680px;
206
-$welcomePageEnterRoomPadding: 25px 30px;
207
-$welcomePageEnterRoomBorderRadius: 0px;
208
-
209
-$welcomePageEnterRoomInputContainerPadding: 0 8px 5px 0px;
210
-$welcomePageEnterRoomInputContainerBorderWidth: 0px 0px 2px 0px;
211
-$welcomePageEnterRoomInputContainerBorderStyle: solid;
212
-$welcomePageEnterRoomInputContainerBorderImage: linear-gradient(to right, #dee1e6, #fff) 1;
213
-
214
-$welcomePageEnterRoomTitleDisplay: inherit;
196
+$welcomePageEnterRoomWidth: calc(100% - 32px);
197
+$welcomePageEnterRoomPadding: 4px;
198
+$welcomePageEnterRoomMargin: 0 auto;
215
 
199
 
216
 $welcomePageTabContainerDisplay: flex;
200
 $welcomePageTabContainerDisplay: flex;
217
 $welcomePageTabContentDisplay: inherit;
201
 $welcomePageTabContentDisplay: inherit;
218
 $welcomePageTabButtonsDisplay: flex;
202
 $welcomePageTabButtonsDisplay: flex;
219
 $welcomePageTabDisplay: block;
203
 $welcomePageTabDisplay: block;
220
 
204
 
221
-$welcomePageButtonWidth: 51px;
222
-$welcomePageButtonMinWidth: inherit;
223
-$welcomePageButtonFontSize: 14px;
224
-$welcomePageButtonHeight: 35px;
225
-$welcomePageButtonFontWeight: inherit;
226
-$welcomePageButtonBorderRadius: 4px;
227
-$welcomePageButtonLineHeight: 35px;
228
-
229
 /**
205
 /**
230
  * Deep-linking page variables.
206
  * Deep-linking page variables.
231
  */
207
  */

+ 167
- 85
css/_welcome_page.scss View File

5
 
5
 
6
 .welcome {
6
 .welcome {
7
     background-image: $welcomePageBackground;
7
     background-image: $welcomePageBackground;
8
+    background-color: #fff;
8
     display: flex;
9
     display: flex;
9
     flex-direction: column;
10
     flex-direction: column;
10
     font-family: $welcomePageFontFamily;
11
     font-family: $welcomePageFontFamily;
18
         background-repeat: $welcomePageHeaderBackgroundRepeat;
19
         background-repeat: $welcomePageHeaderBackgroundRepeat;
19
         background-size: $welcomePageHeaderBackgroundSize;
20
         background-size: $welcomePageHeaderBackgroundSize;
20
         padding-bottom: $welcomePageHeaderPaddingBottom;
21
         padding-bottom: $welcomePageHeaderPaddingBottom;
21
-        align-items: center;
22
-        display: flex;
23
-        flex-direction: column;
24
-        min-height: $welcomePageHeaderMinHeight;
22
+        background-color: #002637;
23
+        height: 480px;
25
         overflow: hidden;
24
         overflow: hidden;
26
         position: relative;
25
         position: relative;
27
-        text-align: center;
28
 
26
 
29
-        .header-text {
30
-            display: $welcomePageHeaderTextDisplay;
27
+        .header-container {
28
+            display: $welcomePageHeaderContainerDisplay;
31
             flex-direction: column;
29
             flex-direction: column;
32
-            margin-top: $watermarkHeight + $welcomePageHeaderTextMarginTop;
33
-            margin-bottom: $welcomePageHeaderTextMarginBottom;
34
-            max-width: calc(100% - 40px);
35
-            width: $welcomePageHeaderTextWidth;
30
+            margin: $welcomePageHeaderContainerMargin;
36
             z-index: $zindex2;
31
             z-index: $zindex2;
37
         }
32
         }
38
 
33
 
42
             font-weight: $welcomePageHeaderTextTitleFontWeight;
37
             font-weight: $welcomePageHeaderTextTitleFontWeight;
43
             line-height: $welcomePageHeaderTextTitleLineHeight;
38
             line-height: $welcomePageHeaderTextTitleLineHeight;
44
             margin-bottom: $welcomePageHeaderTextTitleMarginBottom;
39
             margin-bottom: $welcomePageHeaderTextTitleMarginBottom;
40
+            max-width: $welcomePageHeaderTitleMaxWidth;
45
             opacity: $welcomePageHeaderTextTitleOpacity;
41
             opacity: $welcomePageHeaderTextTitleOpacity;
42
+            text-align: $welcomePageHeaderTextAlign;
46
         }
43
         }
47
 
44
 
48
-        .header-text-description {
49
-            display: $welcomePageHeaderTextDescriptionDisplay;
50
-            color: $welcomePageDescriptionColor;
51
-            font-size: $welcomePageHeaderTextDescriptionFontSize;
52
-            font-weight: $welcomePageHeaderTextDescriptionFontWeight;
53
-            line-height: $welcomePageHeaderTextDescriptionLineHeight;
54
-            margin-bottom: $welcomePageHeaderTextDescriptionMarginBottom;
55
-            align-self: $welcomePageHeaderTextDescriptionAlignSelf;
45
+        .header-text-subtitle {
46
+            color: #fff;
47
+            font-size: 20px;
48
+            font-weight: 600;
49
+            line-height: 26px;
50
+            margin: 16px 0 32px 0;
51
+            text-align: $welcomePageHeaderTextAlign;
52
+
56
         }
53
         }
57
 
54
 
58
         #enter_room {
55
         #enter_room {
59
             display: $welcomePageEnterRoomDisplay;
56
             display: $welcomePageEnterRoomDisplay;
60
             align-items: center;
57
             align-items: center;
61
-            max-width: calc(100% - 40px);
58
+            max-width: 480px;
62
             width: $welcomePageEnterRoomWidth;
59
             width: $welcomePageEnterRoomWidth;
63
             z-index: $zindex2;
60
             z-index: $zindex2;
64
             background-color: #fff;
61
             background-color: #fff;
65
             padding: $welcomePageEnterRoomPadding;
62
             padding: $welcomePageEnterRoomPadding;
66
-            border-radius: $welcomePageEnterRoomBorderRadius;
63
+            border-radius: 4px;
64
+            margin: $welcomePageEnterRoomMargin;
67
 
65
 
68
             .enter-room-input-container {
66
             .enter-room-input-container {
69
-                width: 100%;
70
-                padding: $welcomePageEnterRoomInputContainerPadding;
71
                 text-align: left;
67
                 text-align: left;
72
                 color: #253858;
68
                 color: #253858;
69
+                flex-grow: 1;
73
                 height: fit-content;
70
                 height: fit-content;
74
-
75
-                .enter-room-title {
76
-                    display: $welcomePageEnterRoomTitleDisplay;
77
-                    font-size: 18px;
78
-                    font-weight: bold;
79
-                    padding-bottom: 5px;
80
-                }
71
+                padding-right: 4px;
72
+                position: relative;
81
 
73
 
82
                 .enter-room-input {
74
                 .enter-room-input {
83
-                    border-width: $welcomePageEnterRoomInputContainerBorderWidth;
84
-                    border-style: $welcomePageEnterRoomInputContainerBorderStyle;
85
-                    border-image: $welcomePageEnterRoomInputContainerBorderImage;
75
+                    border: 0;
76
+                    background: #fff;
86
                     display: inline-block;
77
                     display: inline-block;
78
+                    height: 50px;
87
                     width: 100%;
79
                     width: 100%;
88
                     font-size: 14px;
80
                     font-size: 14px;
81
+                    padding-left: 10px;
82
+
83
+                    &:focus {
84
+                        outline: auto 2px #005fcc;
85
+                    }
89
                 }
86
                 }
90
 
87
 
91
                 .insecure-room-name-warning {
88
                 .insecure-room-name-warning {
109
                 }
106
                 }
110
             }
107
             }
111
 
108
 
109
+            .warning-without-link {
110
+                position: absolute;
111
+                top: 44px;
112
+                left: -10px;
113
+            }
114
+
115
+            .warning-with-link {
116
+                position: absolute;
117
+                top: 84px;
118
+            }
119
+
112
         }
120
         }
113
 
121
 
114
         #moderated-meetings {
122
         #moderated-meetings {
115
             max-width: calc(100% - 40px);
123
             max-width: calc(100% - 40px);
116
             padding: 16px 0 39px 0;
124
             padding: 16px 0 39px 0;
125
+            margin: $welcomePageEnterRoomMargin;
117
             width: $welcomePageEnterRoomWidth;
126
             width: $welcomePageEnterRoomWidth;
118
 
127
 
119
             p {
128
             p {
120
                 color: $welcomePageDescriptionColor;
129
                 color: $welcomePageDescriptionColor;
121
-                text-align: left;
130
+                text-align: $welcomePageHeaderTextAlign;
122
 
131
 
123
                 a {
132
                 a {
124
                     color: inherit;
133
                     color: inherit;
126
                 }
135
                 }
127
             }
136
             }
128
         }
137
         }
138
+    }
129
 
139
 
130
-        .tab-container {
131
-            font-size: 16px;
140
+    .tab-container {
141
+        font-size: 16px;
142
+        position: relative;
143
+        text-align: left;
144
+        display: $welcomePageTabContainerDisplay;
145
+        flex-direction: column;
146
+
147
+        .tab-content{
148
+            display: $welcomePageTabContentDisplay;
149
+            height: 250px;
150
+            margin: 5px 0px;
151
+            overflow: hidden;
152
+            flex-grow: 1;
132
             position: relative;
153
             position: relative;
133
-            text-align: left;
134
-            min-height: 354px;
135
-            width: 710px;
136
-            background: #75A7E7;
137
-            display: $welcomePageTabContainerDisplay;
138
-            flex-direction: column;
154
+        }
139
 
155
 
140
-            .tab-content{
141
-                display: $welcomePageTabContentDisplay;
142
-                margin: 5px 0px;
143
-                overflow: hidden;
156
+        .tab-buttons {
157
+            background-color: #c7ddff;
158
+            border-radius: 6px;
159
+            color: #0163FF;
160
+            font-size: 14px;
161
+            line-height: 18px;
162
+            margin: 4px;
163
+            display: $welcomePageTabButtonsDisplay;
164
+
165
+            .tab {
166
+                background-color: #c7ddff;
167
+                border-radius: 7px;
168
+                cursor: pointer;
169
+                display: $welcomePageTabDisplay;
144
                 flex-grow: 1;
170
                 flex-grow: 1;
145
-                position: relative;
171
+                margin: 2px;
172
+                padding: 7px 0;
173
+                text-align: center;
146
 
174
 
147
-                > * {
148
-                    position: absolute;
175
+                &.selected {
176
+                    background-color: #FFF;
149
                 }
177
                 }
150
             }
178
             }
151
 
179
 
152
-            .tab-buttons {
153
-                font-size: 18px;
154
-                color: #FFFFFF;
155
-                display: $welcomePageTabButtonsDisplay;
156
-                flex-grow: 0;
157
-                flex-direction: row;
158
-                min-height: 54px;
159
-                width: 100%;
160
-
161
-                .tab {
162
-                    display: $welcomePageTabDisplay;
163
-                    text-align: center;
164
-                    background: rgba(9,30,66,0.37);
165
-                    height: 55px;
166
-                    line-height: 54px;
167
-                    flex-grow: 1;
168
-                    cursor: pointer;
169
-
170
-                    &.selected, &:hover {
171
-                        background: rgba(9,30,66,0.71);
172
-                    }
173
-
174
-                    &:last-child {
175
-                        margin-left: 1px;
176
-                    }
177
-                }
178
-            }
179
         }
180
         }
180
     }
181
     }
181
 
182
 
182
     .welcome-page-button {
183
     .welcome-page-button {
183
-        width: $welcomePageButtonWidth;
184
-        min-width: $welcomePageButtonMinWidth;
185
-        height: $welcomePageButtonHeight;
186
-        font-size: $welcomePageButtonFontSize;
187
-        font-weight: $welcomePageButtonFontWeight;
184
+        border: 0;
185
+        font-size: 14px;
188
         background: #0074E0;
186
         background: #0074E0;
189
-        border-radius: $welcomePageButtonBorderRadius;
187
+        border-radius: 3px;
190
         color: #FFFFFF;
188
         color: #FFFFFF;
191
-        text-align: center;
192
-        vertical-align: middle;
193
-        line-height: $welcomePageButtonLineHeight;
194
         cursor: pointer;
189
         cursor: pointer;
190
+        padding: 16px 20px;
191
+
192
+        &:focus-within {
193
+            outline: auto 2px #022e61;
194
+        }
195
     }
195
     }
196
 
196
 
197
     .welcome-page-settings {
197
     .welcome-page-settings {
198
+        background: rgba(255, 255, 255, 0.38);
199
+        border-radius: 3px;
198
         color: $welcomePageDescriptionColor;
200
         color: $welcomePageDescriptionColor;
201
+        padding: 4px;
199
         position: absolute;
202
         position: absolute;
200
         top: 32px;
203
         top: 32px;
201
         right: 32px;
204
         right: 32px;
217
             height: $welcomePageWatermarkHeight;
220
             height: $welcomePageWatermarkHeight;
218
         }
221
         }
219
     }
222
     }
223
+
224
+    &.without-content {
225
+        .welcome-card {
226
+            min-width: 500px;
227
+        }
228
+    }
229
+
230
+    .welcome-cards-container {
231
+        color:#131519;
232
+        padding-top: 40px;
233
+    }
234
+
235
+    .welcome-card-row {
236
+        display: flex;
237
+        justify-content: center;
238
+        padding: 0 32px;
239
+    }
240
+
241
+    .welcome-card-text {
242
+        padding: 32px;
243
+    }
244
+
245
+    .welcome-card {
246
+        width: 49%;
247
+        border-radius: 8px;
248
+
249
+        &--dark {
250
+            background: #444447;
251
+            color: #fff;
252
+        }
253
+
254
+        &--blue {
255
+            background: #D5E5FF;
256
+        }
257
+
258
+        &--grey {
259
+            background: #F2F3F4;
260
+        }
261
+
262
+        &--shadow {
263
+            box-shadow: 0px 4px 30px rgba(0, 0, 0, 0.15);
264
+        }
265
+    }
266
+
267
+    .welcome-footer {
268
+        background: #131519;
269
+        color: #fff;
270
+        margin-top: 40px;
271
+        position: relative;
272
+    }
273
+
274
+    .welcome-footer-centered {
275
+        max-width: 688px;
276
+        margin: 0 auto;
277
+    }
278
+
279
+    .welcome-footer-padded {
280
+        padding: 0px 16px;
281
+    }
282
+
283
+    .welcome-footer-row-block {
284
+        display: flex;
285
+        justify-content: space-between;
286
+        align-items: center;
287
+        border-bottom: 1px solid #424447;
288
+
289
+        &:last-child {
290
+            border-bottom: none;
291
+        }
292
+    }
293
+
294
+    .welcome-footer--row-1 {
295
+        padding: 40px 0 24px 0;
296
+    }
297
+
298
+    .welcome-footer-row-1-text {
299
+        max-width: 200px;
300
+        margin-right: 16px;
301
+    }
220
 }
302
 }

BIN
images/app-store-badge.png View File


+ 21
- 0
images/calendar.svg View File

1
+<svg width="68" height="72" viewBox="0 0 68 72" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+<rect x="1" y="5.64514" width="65.3548" height="65.3548" rx="7" stroke="#A4B8D1" stroke-width="2"/>
3
+<rect y="23.2258" width="67.3548" height="2.0213" fill="#A4B8D1"/>
4
+<rect x="14.5161" width="2.32258" height="14.5161" fill="#A4B8D1"/>
5
+<rect x="11.6129" y="12.1935" width="8.12903" height="2.32258" fill="#A4B8D1"/>
6
+<rect x="50.5161" width="2.32258" height="14.5161" fill="#A4B8D1"/>
7
+<rect x="47.6129" y="12.1935" width="8.12903" height="2.32258" fill="#A4B8D1"/>
8
+<circle cx="24.387" cy="37.7419" r="2.32258" fill="#A4B8D1"/>
9
+<circle cx="33.6774" cy="37.7419" r="2.32258" fill="#A4B8D1"/>
10
+<circle cx="42.9677" cy="37.7419" r="2.32258" fill="#A4B8D1"/>
11
+<circle cx="52.258" cy="37.7419" r="2.32258" fill="#A4B8D1"/>
12
+<circle cx="24.387" cy="47.0322" r="2.32258" fill="#A4B8D1"/>
13
+<circle cx="15.0968" cy="47.0322" r="2.32258" fill="#A4B8D1"/>
14
+<circle cx="33.6774" cy="47.0322" r="2.32258" fill="#A4B8D1"/>
15
+<circle cx="42.9677" cy="47.0322" r="2.32258" fill="#A4B8D1"/>
16
+<circle cx="24.387" cy="56.3226" r="2.32258" fill="#A4B8D1"/>
17
+<circle cx="15.0968" cy="56.3226" r="2.32258" fill="#A4B8D1"/>
18
+<circle cx="33.6774" cy="56.3226" r="2.32258" fill="#A4B8D1"/>
19
+<circle cx="42.9677" cy="56.3226" r="2.32258" fill="#A4B8D1"/>
20
+<circle cx="52.258" cy="47.0322" r="2.32258" fill="#A4B8D1"/>
21
+</svg>

BIN
images/f-droid-badge.png View File


BIN
images/google-play-badge.png View File


BIN
images/watermark.png View File


+ 8
- 0
images/watermark.svg
File diff suppressed because it is too large
View File


BIN
images/welcome-background.png View File


+ 1
- 0
index.html View File

182
     <!--#include virtual="title.html" -->
182
     <!--#include virtual="title.html" -->
183
     <!--#include virtual="plugin.head.html" -->
183
     <!--#include virtual="plugin.head.html" -->
184
     <!--#include virtual="static/welcomePageAdditionalContent.html" -->
184
     <!--#include virtual="static/welcomePageAdditionalContent.html" -->
185
+    <!--#include virtual="static/welcomePageAdditionalCard.html" -->
185
     <!--#include virtual="static/settingsToolbarAdditionalContent.html" -->
186
     <!--#include virtual="static/settingsToolbarAdditionalContent.html" -->
186
   </head>
187
   </head>
187
   <body>
188
   <body>

+ 20
- 13
interface_config.js View File

46
 
46
 
47
     DEFAULT_BACKGROUND: '#474747',
47
     DEFAULT_BACKGROUND: '#474747',
48
     DEFAULT_LOCAL_DISPLAY_NAME: 'me',
48
     DEFAULT_LOCAL_DISPLAY_NAME: 'me',
49
-    DEFAULT_LOGO_URL: 'images/watermark.png',
49
+    DEFAULT_LOGO_URL: 'images/watermark.svg',
50
     DEFAULT_REMOTE_DISPLAY_NAME: 'Fellow Jitster',
50
     DEFAULT_REMOTE_DISPLAY_NAME: 'Fellow Jitster',
51
-    DEFAULT_WELCOME_PAGE_LOGO_URL: 'images/watermark.png',
51
+    DEFAULT_WELCOME_PAGE_LOGO_URL: 'images/watermark.svg',
52
 
52
 
53
     DISABLE_DOMINANT_SPEAKER_INDICATOR: false,
53
     DISABLE_DOMINANT_SPEAKER_INDICATOR: false,
54
 
54
 
86
      */
86
      */
87
     DISABLE_VIDEO_BACKGROUND: false,
87
     DISABLE_VIDEO_BACKGROUND: false,
88
 
88
 
89
-    DISPLAY_WELCOME_PAGE_CONTENT: true,
89
+    DISPLAY_WELCOME_FOOTER: true,
90
+    DISPLAY_WELCOME_PAGE_ADDITIONAL_CARD: false,
91
+    DISPLAY_WELCOME_PAGE_CONTENT: false,
90
     DISPLAY_WELCOME_PAGE_TOOLBAR_ADDITIONAL_CONTENT: false,
92
     DISPLAY_WELCOME_PAGE_TOOLBAR_ADDITIONAL_CONTENT: false,
91
 
93
 
92
     ENABLE_DIAL_OUT: true,
94
     ENABLE_DIAL_OUT: true,
136
      */
138
      */
137
     MOBILE_APP_PROMO: true,
139
     MOBILE_APP_PROMO: true,
138
 
140
 
141
+    /**
142
+     * Specify custom URL for downloading android mobile app.
143
+     */
144
+    MOBILE_DOWNLOAD_LINK_ANDROID: 'https://play.google.com/store/apps/details?id=org.jitsi.meet',
145
+
146
+    /**
147
+     * Specify custom URL for downloading f droid app.
148
+     */
149
+    MOBILE_DOWNLOAD_LINK_F_DROID: 'https://f-droid.org/en/packages/org.jitsi.meet/',
150
+
151
+    /**
152
+     * Specify URL for downloading ios mobile app.
153
+     */
154
+    MOBILE_DOWNLOAD_LINK_IOS: 'https://itunes.apple.com/us/app/jitsi-meet/id1165103905',
155
+
139
     NATIVE_APP_NAME: 'Jitsi Meet',
156
     NATIVE_APP_NAME: 'Jitsi Meet',
140
 
157
 
141
     // Names of browsers which should show a warning stating the current browser
158
     // Names of browsers which should show a warning stating the current browser
234
      */
251
      */
235
     // TILE_VIEW_MAX_COLUMNS: 5,
252
     // TILE_VIEW_MAX_COLUMNS: 5,
236
 
253
 
237
-    /**
238
-     * Specify custom URL for downloading android mobile app.
239
-     */
240
-    // MOBILE_DOWNLOAD_LINK_ANDROID: 'https://play.google.com/store/apps/details?id=org.jitsi.meet',
241
-
242
-    /**
243
-     * Specify URL for downloading ios mobile app.
244
-     */
245
-    // MOBILE_DOWNLOAD_LINK_IOS: 'https://itunes.apple.com/us/app/jitsi-meet/id1165103905',
246
-
247
     /**
254
     /**
248
      * Specify Firebase dynamic link properties for the mobile apps.
255
      * Specify Firebase dynamic link properties for the mobile apps.
249
      */
256
      */

+ 4
- 0
lang/main.json View File

878
         "goSmall": "GO",
878
         "goSmall": "GO",
879
         "info": "Dial-in info",
879
         "info": "Dial-in info",
880
         "join": "CREATE / JOIN",
880
         "join": "CREATE / JOIN",
881
+        "jitsiMeet": "Jitsi Meet",
882
+        "jitsiOnMobile": "Jitsi on mobile – download our apps and start a meeting from anywhere",
881
         "moderatedMessage": "Or <a href=\"{{url}}\" rel=\"noopener noreferrer\" target=\"_blank\">book a meeting URL</a> in advance where you are the only moderator.",
883
         "moderatedMessage": "Or <a href=\"{{url}}\" rel=\"noopener noreferrer\" target=\"_blank\">book a meeting URL</a> in advance where you are the only moderator.",
882
         "privacy": "Privacy",
884
         "privacy": "Privacy",
883
         "recentList": "Recent",
885
         "recentList": "Recent",
888
         "roomname": "Enter room name",
890
         "roomname": "Enter room name",
889
         "roomnameHint": "Enter the name or URL of the room you want to join. You may make a name up, just let the people you are meeting know it so that they enter the same name.",
891
         "roomnameHint": "Enter the name or URL of the room you want to join. You may make a name up, just let the people you are meeting know it so that they enter the same name.",
890
         "sendFeedback": "Send feedback",
892
         "sendFeedback": "Send feedback",
893
+        "secureMeetings": "Secure and high quality meetings",
894
+        "startMeeting": "Start meeting",
891
         "terms": "Terms",
895
         "terms": "Terms",
892
         "title": "Secure, fully featured, and completely free video conferencing"
896
         "title": "Secure, fully featured, and completely free video conferencing"
893
     },
897
     },

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

1
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+<path fill-rule="evenodd" clip-rule="evenodd" d="M4.99996 2.50002C4.99996 2.03978 5.37306 1.66669 5.83329 1.66669C6.29353 1.66669 6.66663 2.03978 6.66663 2.50002V3.33335H13.3333V2.50002C13.3333 2.03978 13.7064 1.66669 14.1666 1.66669C14.6269 1.66669 15 2.03978 15 2.50002V3.33335H16.6666C17.5871 3.33335 18.3333 4.07955 18.3333 5.00002V16.6667C18.3333 17.5872 17.5871 18.3334 16.6666 18.3334H3.33329C2.41282 18.3334 1.66663 17.5872 1.66663 16.6667V5.00002C1.66663 4.07955 2.41282 3.33335 3.33329 3.33335H4.99996V2.50002ZM3.33329 16.6667V5.00002H16.6666V16.6667H3.33329ZM9.99996 6.66669C9.53972 6.66669 9.16663 7.03978 9.16663 7.50002V10H6.66662C6.20639 10 5.83329 10.3731 5.83329 10.8334C5.83329 11.2936 6.20639 11.6667 6.66662 11.6667H9.16663V14.1667C9.16663 14.6269 9.53972 15 9.99996 15C10.4602 15 10.8333 14.6269 10.8333 14.1667V11.6667H13.3333C13.7935 11.6667 14.1666 11.2936 14.1666 10.8334C14.1666 10.3731 13.7935 10 13.3333 10H10.8333V7.50002C10.8333 7.03978 10.4602 6.66669 9.99996 6.66669Z" fill="#0163FF"/>
3
+</svg>

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

11
 export { default as IconAudioOnlyOff } from './visibility-off.svg';
11
 export { default as IconAudioOnlyOff } from './visibility-off.svg';
12
 export { default as IconAudioRoute } from './volume.svg';
12
 export { default as IconAudioRoute } from './volume.svg';
13
 export { default as IconBlurBackground } from './blur-background.svg';
13
 export { default as IconBlurBackground } from './blur-background.svg';
14
+export { default as IconPlusCalendar } from './calendar-plus.svg';
14
 export { default as IconCamera } from './camera.svg';
15
 export { default as IconCamera } from './camera.svg';
15
 export { default as IconCameraDisabled } from './camera-disabled.svg';
16
 export { default as IconCameraDisabled } from './camera-disabled.svg';
16
 export { default as IconCancelSelection } from './cancel.svg';
17
 export { default as IconCancelSelection } from './cancel.svg';

+ 31
- 6
react/features/base/react/components/web/MeetingsList.js View File

6
     getLocalizedDateFormatter,
6
     getLocalizedDateFormatter,
7
     getLocalizedDurationFormatter
7
     getLocalizedDurationFormatter
8
 } from '../../../i18n';
8
 } from '../../../i18n';
9
+import { Icon, IconTrash } from '../../../icons';
9
 
10
 
10
 import Container from './Container';
11
 import Container from './Container';
11
 import Text from './Text';
12
 import Text from './Text';
38
     meetings: Array<Object>,
39
     meetings: Array<Object>,
39
 
40
 
40
     /**
41
     /**
41
-     * Defines what happens when  an item in the section list is clicked
42
+     * Handler for deleting an item.
42
      */
43
      */
43
-    onItemClick: Function
44
+    onItemDelete?: Function
44
 };
45
 };
45
 
46
 
46
 /**
47
 /**
138
         return null;
139
         return null;
139
     }
140
     }
140
 
141
 
142
+    _onDelete: Object => Function;
143
+
144
+    /**
145
+     * Returns a function that is used on the onDelete callback.
146
+     *
147
+     * @param {Object} item - The item to be deleted.
148
+     * @private
149
+     * @returns {Function}
150
+     */
151
+    _onDelete(item) {
152
+        const { onItemDelete } = this.props;
153
+
154
+        return evt => {
155
+            evt.stopPropagation();
156
+
157
+            onItemDelete && onItemDelete(item);
158
+        };
159
+    }
160
+
141
     _renderItem: (Object, number) => React$Node;
161
     _renderItem: (Object, number) => React$Node;
142
 
162
 
143
     /**
163
     /**
156
             title,
176
             title,
157
             url
177
             url
158
         } = meeting;
178
         } = meeting;
159
-        const { hideURL = false } = this.props;
179
+        const { hideURL = false, onItemDelete } = this.props;
160
         const onPress = this._onPress(url);
180
         const onPress = this._onPress(url);
161
         const rootClassName
181
         const rootClassName
162
             = `item ${
182
             = `item ${
168
                 key = { index }
188
                 key = { index }
169
                 onClick = { onPress }>
189
                 onClick = { onPress }>
170
                 <Container className = 'left-column'>
190
                 <Container className = 'left-column'>
171
-                    <Text className = 'date'>
191
+                    <Text className = 'title'>
172
                         { _toDateString(date) }
192
                         { _toDateString(date) }
173
                     </Text>
193
                     </Text>
174
-                    <Text>
194
+                    <Text className = 'subtitle'>
175
                         { _toTimeString(time) }
195
                         { _toTimeString(time) }
176
                     </Text>
196
                     </Text>
177
                 </Container>
197
                 </Container>
187
                     }
207
                     }
188
                     {
208
                     {
189
                         typeof duration === 'number' ? (
209
                         typeof duration === 'number' ? (
190
-                            <Text>
210
+                            <Text className = 'subtitle'>
191
                                 { getLocalizedDurationFormatter(duration) }
211
                                 { getLocalizedDurationFormatter(duration) }
192
                             </Text>) : null
212
                             </Text>) : null
193
                     }
213
                     }
194
                 </Container>
214
                 </Container>
195
                 <Container className = 'actions'>
215
                 <Container className = 'actions'>
196
                     { elementAfter || null }
216
                     { elementAfter || null }
217
+
218
+                    { onItemDelete && <Icon
219
+                        className = 'delete-meeting'
220
+                        onClick = { this._onDelete(meeting) }
221
+                        src = { IconTrash } />}
197
                 </Container>
222
                 </Container>
198
             </Container>
223
             </Container>
199
         );
224
         );

+ 11
- 4
react/features/calendar-sync/components/CalendarList.web.js View File

8
     sendAnalytics
8
     sendAnalytics
9
 } from '../../analytics';
9
 } from '../../analytics';
10
 import { translate } from '../../base/i18n';
10
 import { translate } from '../../base/i18n';
11
+import { Icon, IconPlusCalendar } from '../../base/icons';
11
 import { AbstractPage } from '../../base/react';
12
 import { AbstractPage } from '../../base/react';
12
 import { connect } from '../../base/redux';
13
 import { connect } from '../../base/redux';
13
 import { openSettingsDialog, SETTINGS_TABS } from '../../settings';
14
 import { openSettingsDialog, SETTINGS_TABS } from '../../settings';
185
 
186
 
186
         return (
187
         return (
187
             <div className = 'meetings-list-empty'>
188
             <div className = 'meetings-list-empty'>
188
-                <p className = 'description'>
189
+                <div className = 'meetings-list-empty-image'>
190
+                    <img src = '/images/calendar.svg' />
191
+                </div>
192
+                <div className = 'description'>
189
                     { t('welcomepage.connectCalendarText', {
193
                     { t('welcomepage.connectCalendarText', {
190
                         app: interfaceConfig.APP_NAME,
194
                         app: interfaceConfig.APP_NAME,
191
                         provider: interfaceConfig.PROVIDER_NAME
195
                         provider: interfaceConfig.PROVIDER_NAME
192
                     }) }
196
                     }) }
193
-                </p>
197
+                </div>
194
                 <div
198
                 <div
195
-                    className = 'button'
199
+                    className = 'meetings-list-empty-button'
196
                     onClick = { this._onOpenSettings }>
200
                     onClick = { this._onOpenSettings }>
197
-                    { t('welcomepage.connectCalendarButton') }
201
+                    <Icon
202
+                        className = 'meetings-list-empty-icon'
203
+                        src = { IconPlusCalendar } />
204
+                    <span>{ t('welcomepage.connectCalendarButton') }</span>
198
                 </div>
205
                 </div>
199
             </div>
206
             </div>
200
         );
207
         );

+ 4
- 1
react/features/calendar-sync/components/JoinButton.web.js View File

4
 import React, { Component } from 'react';
4
 import React, { Component } from 'react';
5
 
5
 
6
 import { translate } from '../../base/i18n';
6
 import { translate } from '../../base/i18n';
7
+import { Icon, IconAdd } from '../../base/icons';
7
 
8
 
8
 /**
9
 /**
9
  * The type of the React {@code Component} props of {@link JoinButton}.
10
  * The type of the React {@code Component} props of {@link JoinButton}.
60
                 <div
61
                 <div
61
                     className = 'button join-button'
62
                     className = 'button join-button'
62
                     onClick = { this._onClick }>
63
                     onClick = { this._onClick }>
63
-                    { t('calendarSync.join') }
64
+                    <Icon
65
+                        size = '14'
66
+                        src = { IconAdd } />
64
                 </div>
67
                 </div>
65
             </Tooltip>
68
             </Tooltip>
66
         );
69
         );

+ 15
- 0
react/features/recent-list/components/RecentList.web.js View File

6
 import { translate } from '../../base/i18n';
6
 import { translate } from '../../base/i18n';
7
 import { MeetingsList } from '../../base/react';
7
 import { MeetingsList } from '../../base/react';
8
 import { connect } from '../../base/redux';
8
 import { connect } from '../../base/redux';
9
+import { deleteRecentListEntry } from '../actions';
9
 import { isRecentListEnabled, toDisplayableList } from '../functions';
10
 import { isRecentListEnabled, toDisplayableList } from '../functions';
10
 
11
 
11
 import AbstractRecentList from './AbstractRecentList';
12
 import AbstractRecentList from './AbstractRecentList';
55
         this._getRenderListEmptyComponent
56
         this._getRenderListEmptyComponent
56
             = this._getRenderListEmptyComponent.bind(this);
57
             = this._getRenderListEmptyComponent.bind(this);
57
         this._onPress = this._onPress.bind(this);
58
         this._onPress = this._onPress.bind(this);
59
+        this._onItemDelete = this._onItemDelete.bind(this);
60
+    }
61
+
62
+    _onItemDelete: Object => void;
63
+
64
+    /**
65
+     * Deletes a recent entry.
66
+     *
67
+     * @param {Object} entry - The entry to be deleted.
68
+     * @inheritdoc
69
+     */
70
+    _onItemDelete(entry) {
71
+        this.props.dispatch(deleteRecentListEntry(entry));
58
     }
72
     }
59
 
73
 
60
     /**
74
     /**
78
                 hideURL = { true }
92
                 hideURL = { true }
79
                 listEmptyComponent = { this._getRenderListEmptyComponent() }
93
                 listEmptyComponent = { this._getRenderListEmptyComponent() }
80
                 meetings = { recentList }
94
                 meetings = { recentList }
95
+                onItemDelete = { this._onItemDelete }
81
                 onPress = { this._onPress } />
96
                 onPress = { this._onPress } />
82
         );
97
         );
83
     }
98
     }

+ 1
- 1
react/features/recent-list/functions.web.js View File

12
  */
12
  */
13
 export function toDisplayableList(recentList) {
13
 export function toDisplayableList(recentList) {
14
     return (
14
     return (
15
-        recentList.slice(-3).reverse()
15
+        recentList.reverse()
16
             .map(item => {
16
             .map(item => {
17
                 return {
17
                 return {
18
                     date: item.date,
18
                     date: item.date,

+ 3
- 3
react/features/welcome/components/Tabs.js View File

47
 
47
 
48
         return (
48
         return (
49
             <div className = 'tab-container'>
49
             <div className = 'tab-container'>
50
-                <div className = 'tab-content'>
51
-                    { content }
52
-                </div>
53
                 { tabs.length > 1 ? (
50
                 { tabs.length > 1 ? (
54
                     <div className = 'tab-buttons'>
51
                     <div className = 'tab-buttons'>
55
                         {
52
                         {
64
                         }
61
                         }
65
                     </div>) : null
62
                     </div>) : null
66
                 }
63
                 }
64
+                <div className = 'tab-content'>
65
+                    { content }
66
+                </div>
67
             </div>
67
             </div>
68
         );
68
         );
69
     }
69
     }

+ 155
- 72
react/features/welcome/components/WelcomePage.web.js View File

20
  */
20
  */
21
 export const ROOM_NAME_VALIDATE_PATTERN_STR = '^[^?&:\u0022\u0027%#]+$';
21
 export const ROOM_NAME_VALIDATE_PATTERN_STR = '^[^?&:\u0022\u0027%#]+$';
22
 
22
 
23
-/**
24
- * Maximum number of pixels corresponding to a mobile layout.
25
- * @type {number}
26
- */
27
-const WINDOW_WIDTH_THRESHOLD = 425;
28
-
29
 /**
23
 /**
30
  * The Web container rendering the welcome page.
24
  * The Web container rendering the welcome page.
31
  *
25
  *
78
          */
72
          */
79
         this._additionalToolbarContentRef = null;
73
         this._additionalToolbarContentRef = null;
80
 
74
 
75
+        this._additionalCardRef = null;
76
+
77
+        /**
78
+         * The template to use as the additional card displayed near the main one.
79
+         *
80
+         * @private
81
+         * @type {HTMLTemplateElement|null}
82
+         */
83
+        this._additionalCardTemplate = document.getElementById(
84
+            'welcome-page-additional-card-template');
85
+
81
         /**
86
         /**
82
          * The template to use as the main content for the welcome page. If
87
          * The template to use as the main content for the welcome page. If
83
          * not found then only the welcome page head will display.
88
          * not found then only the welcome page head will display.
102
         // Bind event handlers so they are only bound once per instance.
107
         // Bind event handlers so they are only bound once per instance.
103
         this._onFormSubmit = this._onFormSubmit.bind(this);
108
         this._onFormSubmit = this._onFormSubmit.bind(this);
104
         this._onRoomChange = this._onRoomChange.bind(this);
109
         this._onRoomChange = this._onRoomChange.bind(this);
110
+        this._setAdditionalCardRef = this._setAdditionalCardRef.bind(this);
105
         this._setAdditionalContentRef
111
         this._setAdditionalContentRef
106
             = this._setAdditionalContentRef.bind(this);
112
             = this._setAdditionalContentRef.bind(this);
107
         this._setRoomInputRef = this._setRoomInputRef.bind(this);
113
         this._setRoomInputRef = this._setRoomInputRef.bind(this);
108
         this._setAdditionalToolbarContentRef
114
         this._setAdditionalToolbarContentRef
109
             = this._setAdditionalToolbarContentRef.bind(this);
115
             = this._setAdditionalToolbarContentRef.bind(this);
110
         this._onTabSelected = this._onTabSelected.bind(this);
116
         this._onTabSelected = this._onTabSelected.bind(this);
117
+        this._renderFooter = this._renderFooter.bind(this);
111
     }
118
     }
112
 
119
 
113
     /**
120
     /**
137
                 this._additionalToolbarContentTemplate.content.cloneNode(true)
144
                 this._additionalToolbarContentTemplate.content.cloneNode(true)
138
             );
145
             );
139
         }
146
         }
147
+
148
+        if (this._shouldShowAdditionalCard()) {
149
+            this._additionalCardRef.appendChild(
150
+                this._additionalCardTemplate.content.cloneNode(true)
151
+            );
152
+        }
140
     }
153
     }
141
 
154
 
142
     /**
155
     /**
159
      */
172
      */
160
     render() {
173
     render() {
161
         const { _moderatedRoomServiceUrl, t } = this.props;
174
         const { _moderatedRoomServiceUrl, t } = this.props;
162
-        const { APP_NAME, DEFAULT_WELCOME_PAGE_LOGO_URL } = interfaceConfig;
175
+        const { DEFAULT_WELCOME_PAGE_LOGO_URL, DISPLAY_WELCOME_FOOTER } = interfaceConfig;
176
+        const showAdditionalCard = this._shouldShowAdditionalCard();
163
         const showAdditionalContent = this._shouldShowAdditionalContent();
177
         const showAdditionalContent = this._shouldShowAdditionalContent();
164
         const showAdditionalToolbarContent = this._shouldShowAdditionalToolbarContent();
178
         const showAdditionalToolbarContent = this._shouldShowAdditionalToolbarContent();
165
-        const showResponsiveText = this._shouldShowResponsiveText();
166
 
179
 
167
         return (
180
         return (
168
             <div
181
             <div
172
                 <div className = 'welcome-watermark'>
185
                 <div className = 'welcome-watermark'>
173
                     <Watermarks defaultJitsiLogoURL = { DEFAULT_WELCOME_PAGE_LOGO_URL } />
186
                     <Watermarks defaultJitsiLogoURL = { DEFAULT_WELCOME_PAGE_LOGO_URL } />
174
                 </div>
187
                 </div>
188
+
175
                 <div className = 'header'>
189
                 <div className = 'header'>
176
                     <div className = 'welcome-page-settings'>
190
                     <div className = 'welcome-page-settings'>
177
                         <SettingsButton
191
                         <SettingsButton
184
                         }
198
                         }
185
                     </div>
199
                     </div>
186
                     <div className = 'header-image' />
200
                     <div className = 'header-image' />
187
-                    <div className = 'header-text'>
201
+                    <div className = 'header-container'>
188
                         <h1 className = 'header-text-title'>
202
                         <h1 className = 'header-text-title'>
189
-                            { t('welcomepage.title') }
203
+                            { t('welcomepage.jitsiMeet') }
190
                         </h1>
204
                         </h1>
191
-                        <p className = 'header-text-description'>
192
-                            { t('welcomepage.appDescription',
193
-                                { app: APP_NAME }) }
194
-                        </p>
195
-                    </div>
196
-                    <div id = 'enter_room'>
197
-                        <div className = 'enter-room-input-container'>
198
-                            <div className = 'enter-room-title'>
199
-                                { t('welcomepage.enterRoomTitle') }
205
+                        <span className = 'header-text-subtitle'>
206
+                            { t('welcomepage.secureMeetings')}
207
+                        </span>
208
+                        <div id = 'enter_room'>
209
+                            <div className = 'enter-room-input-container'>
210
+                                <form onSubmit = { this._onFormSubmit }>
211
+                                    <input
212
+                                        aria-disabled = 'false'
213
+                                        aria-label = 'Meeting name input'
214
+                                        autoFocus = { true }
215
+                                        className = 'enter-room-input'
216
+                                        id = 'enter_room_field'
217
+                                        onChange = { this._onRoomChange }
218
+                                        pattern = { ROOM_NAME_VALIDATE_PATTERN_STR }
219
+                                        placeholder = { this.state.roomPlaceholder }
220
+                                        ref = { this._setRoomInputRef }
221
+                                        title = { t('welcomepage.roomNameAllowedChars') }
222
+                                        type = 'text'
223
+                                        value = { this.state.room } />
224
+                                    <div
225
+                                        className = { _moderatedRoomServiceUrl
226
+                                            ? 'warning-with-link'
227
+                                            : 'warning-without-link' }>
228
+                                        { this._renderInsecureRoomNameWarning() }
229
+                                    </div>
230
+                                </form>
200
                             </div>
231
                             </div>
201
-                            <form onSubmit = { this._onFormSubmit }>
202
-                                <input
203
-                                    autoFocus = { true }
204
-                                    className = 'enter-room-input'
205
-                                    id = 'enter_room_field'
206
-                                    onChange = { this._onRoomChange }
207
-                                    pattern = { ROOM_NAME_VALIDATE_PATTERN_STR }
208
-                                    placeholder = { this.state.roomPlaceholder }
209
-                                    ref = { this._setRoomInputRef }
210
-                                    title = { t('welcomepage.roomNameAllowedChars') }
211
-                                    type = 'text'
212
-                                    value = { this.state.room } />
213
-                                { this._renderInsecureRoomNameWarning() }
214
-                            </form>
232
+                            <button
233
+                                aria-disabled = 'false'
234
+                                aria-label = 'Start meeting'
235
+                                className = 'welcome-page-button'
236
+                                id = 'enter_room_button'
237
+                                onClick = { this._onFormSubmit }
238
+                                tabIndex = '0'
239
+                                type = 'button'>
240
+                                { t('welcomepage.startMeeting') }
241
+                            </button>
215
                         </div>
242
                         </div>
216
-                        <div
217
-                            className = 'welcome-page-button'
218
-                            id = 'enter_room_button'
219
-                            onClick = { this._onFormSubmit }>
220
-                            {
221
-                                showResponsiveText
222
-                                    ? t('welcomepage.goSmall')
223
-                                    : t('welcomepage.go')
224
-                            }
225
-                        </div>
226
-                    </div>
227
-                    { _moderatedRoomServiceUrl && (
228
-                        <div id = 'moderated-meetings'>
229
-                            <p>
230
-                                {
231
-                                    translateToHTML(
243
+
244
+                        { _moderatedRoomServiceUrl && (
245
+                            <div id = 'moderated-meetings'>
246
+                                <p>
247
+                                    {
248
+                                        translateToHTML(
232
                                         t, 'welcomepage.moderatedMessage', { url: _moderatedRoomServiceUrl })
249
                                         t, 'welcomepage.moderatedMessage', { url: _moderatedRoomServiceUrl })
233
-                                }
234
-                            </p>
250
+                                    }
251
+                                </p>
252
+                            </div>)}
253
+                    </div>
254
+                </div>
255
+
256
+                <div className = 'welcome-cards-container'>
257
+                    <div className = 'welcome-card-row'>
258
+                        <div className = 'welcome-tabs welcome-card welcome-card--blue'>
259
+                            { this._renderTabs() }
235
                         </div>
260
                         </div>
236
-                    ) }
237
-                    { this._renderTabs() }
261
+                        { showAdditionalCard
262
+                            ? <div
263
+                                className = 'welcome-card welcome-card--dark'
264
+                                ref = { this._setAdditionalCardRef } />
265
+                            : null }
266
+                    </div>
267
+
268
+                    { showAdditionalContent
269
+                        ? <div
270
+                            className = 'welcome-page-content'
271
+                            ref = { this._setAdditionalContentRef } />
272
+                        : null }
238
                 </div>
273
                 </div>
239
-                { showAdditionalContent
240
-                    ? <div
241
-                        className = 'welcome-page-content'
242
-                        ref = { this._setAdditionalContentRef } />
243
-                    : null }
274
+                { DISPLAY_WELCOME_FOOTER && this._renderFooter()}
244
             </div>
275
             </div>
276
+
245
         );
277
         );
246
     }
278
     }
247
 
279
 
302
         this.setState({ selectedTab: tabIndex });
334
         this.setState({ selectedTab: tabIndex });
303
     }
335
     }
304
 
336
 
337
+    /**
338
+     * Renders the footer.
339
+     *
340
+     * @returns {ReactElement}
341
+     */
342
+    _renderFooter() {
343
+        const { t } = this.props;
344
+        const {
345
+            MOBILE_DOWNLOAD_LINK_ANDROID,
346
+            MOBILE_DOWNLOAD_LINK_F_DROID,
347
+            MOBILE_DOWNLOAD_LINK_IOS
348
+        } = interfaceConfig;
349
+
350
+        return (<footer className = 'welcome-footer'>
351
+            <div className = 'welcome-footer-centered'>
352
+                <div className = 'welcome-footer-padded'>
353
+                    <div className = 'welcome-footer-row-block welcome-footer--row-1'>
354
+                        <div className = 'welcome-footer-row-1-text'>{t('welcomepage.jitsiOnMobile')}</div>
355
+                        <a
356
+                            className = 'welcome-badge'
357
+                            href = { MOBILE_DOWNLOAD_LINK_IOS }>
358
+                            <img src = './images/app-store-badge.png' />
359
+                        </a>
360
+                        <a
361
+                            className = 'welcome-badge'
362
+                            href = { MOBILE_DOWNLOAD_LINK_ANDROID }>
363
+                            <img src = './images/google-play-badge.png' />
364
+                        </a>
365
+                        <a
366
+                            className = 'welcome-badge'
367
+                            href = { MOBILE_DOWNLOAD_LINK_F_DROID }>
368
+                            <img src = './images/f-droid-badge.png' />
369
+                        </a>
370
+                    </div>
371
+                </div>
372
+            </div>
373
+        </footer>);
374
+    }
375
+
305
     /**
376
     /**
306
      * Renders tabs to show previous meetings and upcoming calendar events. The
377
      * Renders tabs to show previous meetings and upcoming calendar events. The
307
      * tabs are purposefully hidden on mobile browsers.
378
      * tabs are purposefully hidden on mobile browsers.
342
                 tabs = { tabs } />);
413
                 tabs = { tabs } />);
343
     }
414
     }
344
 
415
 
416
+    /**
417
+     * Sets the internal reference to the HTMLDivElement used to hold the
418
+     * additional card shown near the tabs card.
419
+     *
420
+     * @param {HTMLDivElement} el - The HTMLElement for the div that is the root
421
+     * of the welcome page content.
422
+     * @private
423
+     * @returns {void}
424
+     */
425
+    _setAdditionalCardRef(el) {
426
+        this._additionalCardRef = el;
427
+    }
428
+
345
     /**
429
     /**
346
      * Sets the internal reference to the HTMLDivElement used to hold the
430
      * Sets the internal reference to the HTMLDivElement used to hold the
347
      * welcome page content.
431
      * welcome page content.
380
         this._roomInputRef = el;
464
         this._roomInputRef = el;
381
     }
465
     }
382
 
466
 
467
+    /**
468
+     * Returns whether or not an additional card should be displayed near the tabs.
469
+     *
470
+     * @private
471
+     * @returns {boolean}
472
+     */
473
+    _shouldShowAdditionalCard() {
474
+        return interfaceConfig.DISPLAY_WELCOME_PAGE_ADDITIONAL_CARD
475
+            && this._additionalCardTemplate
476
+            && this._additionalCardTemplate.content
477
+            && this._additionalCardTemplate.innerHTML.trim();
478
+    }
479
+
383
     /**
480
     /**
384
      * Returns whether or not additional content should be displayed below
481
      * Returns whether or not additional content should be displayed below
385
      * the welcome page's header for entering a room name.
482
      * the welcome page's header for entering a room name.
407
             && this._additionalToolbarContentTemplate.content
504
             && this._additionalToolbarContentTemplate.content
408
             && this._additionalToolbarContentTemplate.innerHTML.trim();
505
             && this._additionalToolbarContentTemplate.innerHTML.trim();
409
     }
506
     }
410
-
411
-    /**
412
-     * Returns whether or not the screen has a size smaller than a custom margin
413
-     * and therefore display different text in the go button.
414
-     *
415
-     * @private
416
-     * @returns {boolean}
417
-     */
418
-    _shouldShowResponsiveText() {
419
-        const { innerWidth } = window;
420
-
421
-        return innerWidth <= WINDOW_WIDTH_THRESHOLD;
422
-    }
423
-
424
 }
507
 }
425
 
508
 
426
 export default translate(connect(_mapStateToProps)(WelcomePage));
509
 export default translate(connect(_mapStateToProps)(WelcomePage));

+ 1
- 0
static/welcomePageAdditionalCard.html View File

1
+<template id = "welcome-page-additional-card-template"></template>

Loading…
Cancel
Save