Browse Source

feat(welcome_page): Redesign welcome page

master
Vlad Piersec 4 years ago
parent
commit
f8a41aea9c

+ 68
- 25
css/_meetings_list.scss View File

@@ -7,9 +7,8 @@
7 7
     display: flex;
8 8
     flex-direction: column;
9 9
     position: relative;
10
-    width: 100%;
11
-    height: 100%;
12 10
     overflow: auto;
11
+    width: 100%;
13 12
 
14 13
     .meetings-list-empty {
15 14
         text-align: center;
@@ -20,11 +19,34 @@
20 19
         flex-direction: column;
21 20
 
22 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 50
     .button {
29 51
         background: #0074E0;
30 52
         border-radius: 4px;
@@ -32,7 +54,7 @@
32 54
         display: flex;
33 55
         justify-content: center;
34 56
         align-items: center;
35
-        padding: 5px 10px;
57
+        padding: 8px;
36 58
         cursor: pointer;
37 59
     }
38 60
 
@@ -43,12 +65,13 @@
43 65
     }
44 66
 
45 67
     .item {
46
-        background: rgba(255,255,255,0.50);
68
+        background: #fff;
47 69
         box-sizing: border-box;
70
+        border-radius: 4px;
48 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 75
         word-break: break-word;
53 76
         display: flex;
54 77
         flex-direction: row;
@@ -61,37 +84,41 @@
61 84
         .left-column {
62 85
             display: flex;
63 86
             flex-direction: column;
64
-            width: 140px;
65 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 92
         .right-column {
76 93
             display: flex;
77 94
             flex-direction: column;
78 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 116
         .actions {
90 117
             display: flex;
91 118
             align-items: center;
92 119
             justify-content: center;
93 120
             flex-grow: 0;
94
-            padding-right: 30px;
121
+            margin-right: 16px;
95 122
         }
96 123
 
97 124
         &.with-click-handler {
@@ -99,7 +126,7 @@
99 126
         }
100 127
 
101 128
         &.with-click-handler:hover {
102
-            background-color: #75A7E7;
129
+            background-color: #c7ddff;
103 130
         }
104 131
 
105 132
         .add-button {
@@ -120,4 +147,20 @@
120 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,6 +30,67 @@
30 30
 }
31 31
 
32 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 94
     #videoResolutionLabel {
34 95
         display: none;
35 96
     }

+ 18
- 42
css/_variables.scss View File

@@ -161,71 +161,47 @@ $unsupportedDesktopBrowserTextFontSize: 21px;
161 161
 /**
162 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 171
  * Welcome page variables.
172 172
  */
173 173
 $welcomePageDescriptionColor: #fff;
174 174
 $welcomePageFontFamily: inherit;
175
-$welcomePageBackground: linear-gradient(-90deg, #1251AE 0%, #0074FF 50%, #1251AE 100%);
175
+$welcomePageBackground: none;
176 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 179
 $welcomePageHeaderBackgroundPosition: none;
181 180
 $welcomePageHeaderBackgroundRepeat: none;
182
-$welcomePageHeaderBackgroundSize: none;
181
+$welcomePageHeaderBackgroundSize: cover;
183 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 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 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 200
 $welcomePageTabContainerDisplay: flex;
217 201
 $welcomePageTabContentDisplay: inherit;
218 202
 $welcomePageTabButtonsDisplay: flex;
219 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 206
  * Deep-linking page variables.
231 207
  */

+ 167
- 85
css/_welcome_page.scss View File

@@ -5,6 +5,7 @@ body.welcome-page {
5 5
 
6 6
 .welcome {
7 7
     background-image: $welcomePageBackground;
8
+    background-color: #fff;
8 9
     display: flex;
9 10
     flex-direction: column;
10 11
     font-family: $welcomePageFontFamily;
@@ -18,21 +19,15 @@ body.welcome-page {
18 19
         background-repeat: $welcomePageHeaderBackgroundRepeat;
19 20
         background-size: $welcomePageHeaderBackgroundSize;
20 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 24
         overflow: hidden;
26 25
         position: relative;
27
-        text-align: center;
28 26
 
29
-        .header-text {
30
-            display: $welcomePageHeaderTextDisplay;
27
+        .header-container {
28
+            display: $welcomePageHeaderContainerDisplay;
31 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 31
             z-index: $zindex2;
37 32
         }
38 33
 
@@ -42,50 +37,52 @@ body.welcome-page {
42 37
             font-weight: $welcomePageHeaderTextTitleFontWeight;
43 38
             line-height: $welcomePageHeaderTextTitleLineHeight;
44 39
             margin-bottom: $welcomePageHeaderTextTitleMarginBottom;
40
+            max-width: $welcomePageHeaderTitleMaxWidth;
45 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 55
         #enter_room {
59 56
             display: $welcomePageEnterRoomDisplay;
60 57
             align-items: center;
61
-            max-width: calc(100% - 40px);
58
+            max-width: 480px;
62 59
             width: $welcomePageEnterRoomWidth;
63 60
             z-index: $zindex2;
64 61
             background-color: #fff;
65 62
             padding: $welcomePageEnterRoomPadding;
66
-            border-radius: $welcomePageEnterRoomBorderRadius;
63
+            border-radius: 4px;
64
+            margin: $welcomePageEnterRoomMargin;
67 65
 
68 66
             .enter-room-input-container {
69
-                width: 100%;
70
-                padding: $welcomePageEnterRoomInputContainerPadding;
71 67
                 text-align: left;
72 68
                 color: #253858;
69
+                flex-grow: 1;
73 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 74
                 .enter-room-input {
83
-                    border-width: $welcomePageEnterRoomInputContainerBorderWidth;
84
-                    border-style: $welcomePageEnterRoomInputContainerBorderStyle;
85
-                    border-image: $welcomePageEnterRoomInputContainerBorderImage;
75
+                    border: 0;
76
+                    background: #fff;
86 77
                     display: inline-block;
78
+                    height: 50px;
87 79
                     width: 100%;
88 80
                     font-size: 14px;
81
+                    padding-left: 10px;
82
+
83
+                    &:focus {
84
+                        outline: auto 2px #005fcc;
85
+                    }
89 86
                 }
90 87
 
91 88
                 .insecure-room-name-warning {
@@ -109,16 +106,28 @@ body.welcome-page {
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 122
         #moderated-meetings {
115 123
             max-width: calc(100% - 40px);
116 124
             padding: 16px 0 39px 0;
125
+            margin: $welcomePageEnterRoomMargin;
117 126
             width: $welcomePageEnterRoomWidth;
118 127
 
119 128
             p {
120 129
                 color: $welcomePageDescriptionColor;
121
-                text-align: left;
130
+                text-align: $welcomePageHeaderTextAlign;
122 131
 
123 132
                 a {
124 133
                     color: inherit;
@@ -126,76 +135,70 @@ body.welcome-page {
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 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 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 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 186
         background: #0074E0;
189
-        border-radius: $welcomePageButtonBorderRadius;
187
+        border-radius: 3px;
190 188
         color: #FFFFFF;
191
-        text-align: center;
192
-        vertical-align: middle;
193
-        line-height: $welcomePageButtonLineHeight;
194 189
         cursor: pointer;
190
+        padding: 16px 20px;
191
+
192
+        &:focus-within {
193
+            outline: auto 2px #022e61;
194
+        }
195 195
     }
196 196
 
197 197
     .welcome-page-settings {
198
+        background: rgba(255, 255, 255, 0.38);
199
+        border-radius: 3px;
198 200
         color: $welcomePageDescriptionColor;
201
+        padding: 4px;
199 202
         position: absolute;
200 203
         top: 32px;
201 204
         right: 32px;
@@ -217,4 +220,83 @@ body.welcome-page {
217 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

@@ -0,0 +1,21 @@
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,6 +182,7 @@
182 182
     <!--#include virtual="title.html" -->
183 183
     <!--#include virtual="plugin.head.html" -->
184 184
     <!--#include virtual="static/welcomePageAdditionalContent.html" -->
185
+    <!--#include virtual="static/welcomePageAdditionalCard.html" -->
185 186
     <!--#include virtual="static/settingsToolbarAdditionalContent.html" -->
186 187
   </head>
187 188
   <body>

+ 20
- 13
interface_config.js View File

@@ -46,9 +46,9 @@ var interfaceConfig = {
46 46
 
47 47
     DEFAULT_BACKGROUND: '#474747',
48 48
     DEFAULT_LOCAL_DISPLAY_NAME: 'me',
49
-    DEFAULT_LOGO_URL: 'images/watermark.png',
49
+    DEFAULT_LOGO_URL: 'images/watermark.svg',
50 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 53
     DISABLE_DOMINANT_SPEAKER_INDICATOR: false,
54 54
 
@@ -86,7 +86,9 @@ var interfaceConfig = {
86 86
      */
87 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 92
     DISPLAY_WELCOME_PAGE_TOOLBAR_ADDITIONAL_CONTENT: false,
91 93
 
92 94
     ENABLE_DIAL_OUT: true,
@@ -136,6 +138,21 @@ var interfaceConfig = {
136 138
      */
137 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 156
     NATIVE_APP_NAME: 'Jitsi Meet',
140 157
 
141 158
     // Names of browsers which should show a warning stating the current browser
@@ -234,16 +251,6 @@ var interfaceConfig = {
234 251
      */
235 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 255
      * Specify Firebase dynamic link properties for the mobile apps.
249 256
      */

+ 4
- 0
lang/main.json View File

@@ -878,6 +878,8 @@
878 878
         "goSmall": "GO",
879 879
         "info": "Dial-in info",
880 880
         "join": "CREATE / JOIN",
881
+        "jitsiMeet": "Jitsi Meet",
882
+        "jitsiOnMobile": "Jitsi on mobile – download our apps and start a meeting from anywhere",
881 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 884
         "privacy": "Privacy",
883 885
         "recentList": "Recent",
@@ -888,6 +890,8 @@
888 890
         "roomname": "Enter room name",
889 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 892
         "sendFeedback": "Send feedback",
893
+        "secureMeetings": "Secure and high quality meetings",
894
+        "startMeeting": "Start meeting",
891 895
         "terms": "Terms",
892 896
         "title": "Secure, fully featured, and completely free video conferencing"
893 897
     },

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

@@ -0,0 +1,3 @@
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,6 +11,7 @@ export { default as IconAudioOnly } from './visibility.svg';
11 11
 export { default as IconAudioOnlyOff } from './visibility-off.svg';
12 12
 export { default as IconAudioRoute } from './volume.svg';
13 13
 export { default as IconBlurBackground } from './blur-background.svg';
14
+export { default as IconPlusCalendar } from './calendar-plus.svg';
14 15
 export { default as IconCamera } from './camera.svg';
15 16
 export { default as IconCameraDisabled } from './camera-disabled.svg';
16 17
 export { default as IconCancelSelection } from './cancel.svg';

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

@@ -6,6 +6,7 @@ import {
6 6
     getLocalizedDateFormatter,
7 7
     getLocalizedDurationFormatter
8 8
 } from '../../../i18n';
9
+import { Icon, IconTrash } from '../../../icons';
9 10
 
10 11
 import Container from './Container';
11 12
 import Text from './Text';
@@ -38,9 +39,9 @@ type Props = {
38 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,6 +139,25 @@ export default class MeetingsList extends Component<Props> {
138 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 161
     _renderItem: (Object, number) => React$Node;
142 162
 
143 163
     /**
@@ -156,7 +176,7 @@ export default class MeetingsList extends Component<Props> {
156 176
             title,
157 177
             url
158 178
         } = meeting;
159
-        const { hideURL = false } = this.props;
179
+        const { hideURL = false, onItemDelete } = this.props;
160 180
         const onPress = this._onPress(url);
161 181
         const rootClassName
162 182
             = `item ${
@@ -168,10 +188,10 @@ export default class MeetingsList extends Component<Props> {
168 188
                 key = { index }
169 189
                 onClick = { onPress }>
170 190
                 <Container className = 'left-column'>
171
-                    <Text className = 'date'>
191
+                    <Text className = 'title'>
172 192
                         { _toDateString(date) }
173 193
                     </Text>
174
-                    <Text>
194
+                    <Text className = 'subtitle'>
175 195
                         { _toTimeString(time) }
176 196
                     </Text>
177 197
                 </Container>
@@ -187,13 +207,18 @@ export default class MeetingsList extends Component<Props> {
187 207
                     }
188 208
                     {
189 209
                         typeof duration === 'number' ? (
190
-                            <Text>
210
+                            <Text className = 'subtitle'>
191 211
                                 { getLocalizedDurationFormatter(duration) }
192 212
                             </Text>) : null
193 213
                     }
194 214
                 </Container>
195 215
                 <Container className = 'actions'>
196 216
                     { elementAfter || null }
217
+
218
+                    { onItemDelete && <Icon
219
+                        className = 'delete-meeting'
220
+                        onClick = { this._onDelete(meeting) }
221
+                        src = { IconTrash } />}
197 222
                 </Container>
198 223
             </Container>
199 224
         );

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

@@ -8,6 +8,7 @@ import {
8 8
     sendAnalytics
9 9
 } from '../../analytics';
10 10
 import { translate } from '../../base/i18n';
11
+import { Icon, IconPlusCalendar } from '../../base/icons';
11 12
 import { AbstractPage } from '../../base/react';
12 13
 import { connect } from '../../base/redux';
13 14
 import { openSettingsDialog, SETTINGS_TABS } from '../../settings';
@@ -185,16 +186,22 @@ class CalendarList extends AbstractPage<Props> {
185 186
 
186 187
         return (
187 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 193
                     { t('welcomepage.connectCalendarText', {
190 194
                         app: interfaceConfig.APP_NAME,
191 195
                         provider: interfaceConfig.PROVIDER_NAME
192 196
                     }) }
193
-                </p>
197
+                </div>
194 198
                 <div
195
-                    className = 'button'
199
+                    className = 'meetings-list-empty-button'
196 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 205
                 </div>
199 206
             </div>
200 207
         );

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

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

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

@@ -6,6 +6,7 @@ import type { Dispatch } from 'redux';
6 6
 import { translate } from '../../base/i18n';
7 7
 import { MeetingsList } from '../../base/react';
8 8
 import { connect } from '../../base/redux';
9
+import { deleteRecentListEntry } from '../actions';
9 10
 import { isRecentListEnabled, toDisplayableList } from '../functions';
10 11
 
11 12
 import AbstractRecentList from './AbstractRecentList';
@@ -55,6 +56,19 @@ class RecentList extends AbstractRecentList<Props> {
55 56
         this._getRenderListEmptyComponent
56 57
             = this._getRenderListEmptyComponent.bind(this);
57 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,6 +92,7 @@ class RecentList extends AbstractRecentList<Props> {
78 92
                 hideURL = { true }
79 93
                 listEmptyComponent = { this._getRenderListEmptyComponent() }
80 94
                 meetings = { recentList }
95
+                onItemDelete = { this._onItemDelete }
81 96
                 onPress = { this._onPress } />
82 97
         );
83 98
     }

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

@@ -12,7 +12,7 @@ import { parseURIString, safeDecodeURIComponent } from '../base/util';
12 12
  */
13 13
 export function toDisplayableList(recentList) {
14 14
     return (
15
-        recentList.slice(-3).reverse()
15
+        recentList.reverse()
16 16
             .map(item => {
17 17
                 return {
18 18
                     date: item.date,

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

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

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

@@ -20,12 +20,6 @@ import Tabs from './Tabs';
20 20
  */
21 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 24
  * The Web container rendering the welcome page.
31 25
  *
@@ -78,6 +72,17 @@ class WelcomePage extends AbstractWelcomePage {
78 72
          */
79 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 87
          * The template to use as the main content for the welcome page. If
83 88
          * not found then only the welcome page head will display.
@@ -102,12 +107,14 @@ class WelcomePage extends AbstractWelcomePage {
102 107
         // Bind event handlers so they are only bound once per instance.
103 108
         this._onFormSubmit = this._onFormSubmit.bind(this);
104 109
         this._onRoomChange = this._onRoomChange.bind(this);
110
+        this._setAdditionalCardRef = this._setAdditionalCardRef.bind(this);
105 111
         this._setAdditionalContentRef
106 112
             = this._setAdditionalContentRef.bind(this);
107 113
         this._setRoomInputRef = this._setRoomInputRef.bind(this);
108 114
         this._setAdditionalToolbarContentRef
109 115
             = this._setAdditionalToolbarContentRef.bind(this);
110 116
         this._onTabSelected = this._onTabSelected.bind(this);
117
+        this._renderFooter = this._renderFooter.bind(this);
111 118
     }
112 119
 
113 120
     /**
@@ -137,6 +144,12 @@ class WelcomePage extends AbstractWelcomePage {
137 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,10 +172,10 @@ class WelcomePage extends AbstractWelcomePage {
159 172
      */
160 173
     render() {
161 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 177
         const showAdditionalContent = this._shouldShowAdditionalContent();
164 178
         const showAdditionalToolbarContent = this._shouldShowAdditionalToolbarContent();
165
-        const showResponsiveText = this._shouldShowResponsiveText();
166 179
 
167 180
         return (
168 181
             <div
@@ -172,6 +185,7 @@ class WelcomePage extends AbstractWelcomePage {
172 185
                 <div className = 'welcome-watermark'>
173 186
                     <Watermarks defaultJitsiLogoURL = { DEFAULT_WELCOME_PAGE_LOGO_URL } />
174 187
                 </div>
188
+
175 189
                 <div className = 'header'>
176 190
                     <div className = 'welcome-page-settings'>
177 191
                         <SettingsButton
@@ -184,64 +198,82 @@ class WelcomePage extends AbstractWelcomePage {
184 198
                         }
185 199
                     </div>
186 200
                     <div className = 'header-image' />
187
-                    <div className = 'header-text'>
201
+                    <div className = 'header-container'>
188 202
                         <h1 className = 'header-text-title'>
189
-                            { t('welcomepage.title') }
203
+                            { t('welcomepage.jitsiMeet') }
190 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 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 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 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 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 273
                 </div>
239
-                { showAdditionalContent
240
-                    ? <div
241
-                        className = 'welcome-page-content'
242
-                        ref = { this._setAdditionalContentRef } />
243
-                    : null }
274
+                { DISPLAY_WELCOME_FOOTER && this._renderFooter()}
244 275
             </div>
276
+
245 277
         );
246 278
     }
247 279
 
@@ -302,6 +334,45 @@ class WelcomePage extends AbstractWelcomePage {
302 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 377
      * Renders tabs to show previous meetings and upcoming calendar events. The
307 378
      * tabs are purposefully hidden on mobile browsers.
@@ -342,6 +413,19 @@ class WelcomePage extends AbstractWelcomePage {
342 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 430
      * Sets the internal reference to the HTMLDivElement used to hold the
347 431
      * welcome page content.
@@ -380,6 +464,19 @@ class WelcomePage extends AbstractWelcomePage {
380 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 481
      * Returns whether or not additional content should be displayed below
385 482
      * the welcome page's header for entering a room name.
@@ -407,20 +504,6 @@ class WelcomePage extends AbstractWelcomePage {
407 504
             && this._additionalToolbarContentTemplate.content
408 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 509
 export default translate(connect(_mapStateToProps)(WelcomePage));

+ 1
- 0
static/welcomePageAdditionalCard.html View File

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

Loading…
Cancel
Save