소스 검색

[RN] Add recent-list feature

j8
Zoltan Bettenbuk 7 년 전
부모
커밋
45c405de0e

+ 9
- 0
css/_font.scss 파일 보기

@@ -25,6 +25,15 @@
25 25
     -moz-osx-font-smoothing: grayscale;
26 26
 }
27 27
 
28
+.icon-public:before {
29
+  content: "\e80b";
30
+}
31
+.icon-event_note:before {
32
+    content: "\e616";
33
+}
34
+.icon-timer:before {
35
+    content: "\e425";
36
+}
28 37
 .icon-thumb-menu:before {
29 38
     content: "\e5d4";
30 39
 }

+ 7
- 6
doc/adding-an-icon.md 파일 보기

@@ -2,11 +2,12 @@
2 2
 1. Go to https://icomoon.io/app/
3 3
 2. Go to "Manage Projects" from the menu on the top left.
4 4
 3. Use "Import project" and select <code>fonts/selection.json</code> from Jitsi Meet.
5
-4. Import icons (e.g. svg files) using the "import items" button.
6
-5. Go to "generate font" and make sure the identifiers for the new icons are correct.
7
-6. Download the result in a zip file using the "download" button.
8
-7. Copy <code>selection.json</code> and <code>fonts/jitsi.*</code> from the zip file to <code>fonts/</code> in Jitsi Meet
9
-8. Copy the class for the new icon from <code>style.css</code> in the zip file to <code>css/font.css</code> in Jitsi Meet (do *not* copy the whole file)
5
+4. Click "load".
6
+5. Add the new icons using the "Add icons from library" button...
7
+6. Go to "generate font" and make sure the identifiers for the new icons are correct.
8
+7. Download the result in a zip file using the "download" button.
9
+8. Copy <code>selection.json</code> and <code>fonts/jitsi.*</code> from the zip file to <code>fonts/</code> in Jitsi Meet
10
+9. Copy the class for the new icon from <code>style.css</code> in the zip file to <code>css/_font.scss</code> in Jitsi Meet (do *not* copy the whole file)
11
+10. Copy the <code>selection.json</code> file to <code>react/features/base/font-icons</code> overwriting <code>jitsi.json</code>
10 12
 
11 13
 Sample commit: https://github.com/jitsi/jitsi-meet/commit/68bc819b89aec12364fcf07b81efa83a1900eed6
12
-

BIN
fonts/jitsi.eot 파일 보기


+ 3
- 0
fonts/jitsi.svg 파일 보기

@@ -11,11 +11,14 @@
11 11
 <glyph unicode="&#xe145;" glyph-name="add" d="M810 470h-256v-256h-84v256h-256v84h256v256h84v-256h256v-84z" />
12 12
 <glyph unicode="&#xe1aa;" glyph-name="bluetooth" d="M550 328l-80 82v-162zM470 776v-162l80 82zM670 696l-184-184 184-184-244-242h-42v324l-196-196-60 60 238 238-238 238 60 60 196-196v324h42zM834 738c40-64 62-142 62-222 0-84-24-160-66-226l-50 50c26 52 42 110 42 172s-16 120-42 172zM608 512l98 98c12-30 20-64 20-98s-8-70-20-100z" />
13 13
 <glyph unicode="&#xe310;" glyph-name="headset" d="M512 982c212 0 384-172 384-384v-300c0-70-58-128-128-128h-128v342h170v86c0 166-132 298-298 298s-298-132-298-298v-86h170v-342h-128c-70 0-128 58-128 128v300c0 212 172 384 384 384z" />
14
+<glyph unicode="&#xe425;" glyph-name="timer" d="M512 170c166 0 298 134 298 300s-132 298-298 298-298-132-298-298 132-300 298-300zM812 708c52-66 84-148 84-238 0-212-172-384-384-384s-384 172-384 384 172 384 384 384c90 0 174-34 240-86l60 62c22-18 42-38 60-60zM470 426v256h84v-256h-84zM640 982v-86h-256v86h256z" />
14 15
 <glyph unicode="&#xe5d4;" glyph-name="thumb-menu" d="M512 342c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM512 598c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM512 682c-46 0-86 40-86 86s40 86 86 86 86-40 86-86-40-86-86-86z" />
15 16
 <glyph unicode="&#xe603;" glyph-name="presentation" horiz-adv-x="1088" d="M952.495 1019.065h-818.689c-72.81 0-132.183-60.63-132.183-135.162v-750.719c0-74.473 59.372-135.101 132.183-135.101h818.686c72.936 0 132.314 60.625 132.314 135.101v750.722c0.003 74.532-59.378 135.159-132.311 135.159zM946.346 139.651h-806.14v737.822h806.015l0.126-737.822zM685.753 738.544h216.911v-566.758h-216.911v566.758zM428.672 610.002h216.911v-438.216h-216.911v438.216zM172.339 481.46h216.161v-309.677h-216.161v309.677z" />
16 17
 <glyph unicode="&#xe613;" glyph-name="recDisable" horiz-adv-x="1140" d="M1123.444 1003.015c-23.593 26.481-64.131 28.989-90.74 5.395l-1008.269-893.436c-26.609-23.468-28.991-64.131-5.46-90.676 12.674-14.306 30.308-21.649 48.126-21.649 15.123 0 30.372 5.401 42.544 16.195l130.045 115.22c90.743-81.844 210.569-132.165 342.473-132.101 282.816 0.061 510.913 227.969 511.287 510.972 0.126 109.934-34.682 211.367-93.499 294.72l118.088 104.625c26.483 23.526 28.997 64.129 5.404 90.735zM944.422 513.818c0.128-200.922-161.896-363.201-362.509-362.952-87.56 0.123-167.573 31.151-230.061 82.569l331.277 293.509v-73.176c1.071-60.993 32.696-92.18 94.944-93.692 61.997 1.512 93.686 32.763 95.131 93.756v41.096h-72.227v-47.499c0.251-4.642-0.564-10.607-2.511-17.949-1.25-3.261-3.448-6.020-6.525-8.093-3.197-2.572-7.845-3.828-13.868-3.828-10.543 0.31-17.132 4.268-19.827 11.921-1.068 3.512-1.947 6.905-2.508 10.163-0.254 2.887-0.377 5.532-0.377 7.786v143.511l42.477 37.634c0.215-0.432 0.452-0.851 0.63-1.303 1.947-6.467 2.762-12.799 2.511-19.076v-36.772h72.227v30.121c-0.246 31.245-9.086 54.699-26.363 70.447l40.711 36.069c35.787-56.055 56.803-122.585 56.867-194.244zM239.795 395.47c-12.613 37.023-19.827 76.557-19.827 117.913-0.19 200.236 161.584 362.009 361.945 362.135 56.853 0 110.313-13.302 158.133-36.398l117.846 104.421c-79.444 50.952-173.758 80.817-275.292 80.948-283.377 0.181-511.354-227.729-511.789-511.675-0.126-79.567 18.636-154.679 51.137-221.882l117.848 104.538zM388.576 690.020h-97.514v-249.057l72.23 64.070v0.689h0.815l117.72 104.418c0 0.564 0.123 0.94 0.123 1.509 0.753 53.898-30.369 80.069-93.374 78.37zM405.959 625.517c1.942-2.767 3.074-6.469 3.323-11.112 0.312-4.452 0.438-9.6 0.438-15.246 0.251-10.916-0.689-19.83-2.949-26.985-2.952-7.594-10.983-11.357-24.159-11.357h-19.325v74.043h15.31c7.842 0 13.865-0.683 18.072-2.19 4.397-1.573 7.468-3.953 9.29-7.153z" />
17 18
 <glyph unicode="&#xe614;" glyph-name="recEnable" horiz-adv-x="1142" d="M581.278 1025.708c284.857-0.19 514.807-230.517 514.427-514.997-0.378-285.047-230.073-514.553-514.869-514.615-284.541-0.062-515.311 230.517-514.933 514.422 0.439 285.936 230.009 515.439 515.375 515.19zM580.579 875.756c-201.764-0.123-364.666-163.032-364.478-364.663 0-202.018 162.524-364.735 364.478-364.984 202.018-0.316 365.174 163.030 365.048 365.423-0.252 201.767-163.156 364.35-365.048 364.224zM287.698 688.907h98.196c63.442 1.767 94.785-24.518 94.027-78.863 0.254-19.081-2.211-34.882-7.456-47.521-6.005-12.508-18.706-21.988-38.167-28.181v-0.819c28.373-6.259 43.031-23.573 43.981-51.946v-57.689c0-11.247 0.254-22.813 0.758-34.756 0.819-12.005 3.033-20.979 6.696-27.043h-71.846c-3.727 6.064-6.128 15.038-7.14 27.043-1.012 11.943-1.454 23.509-1.138 34.756v52.321c0 9.603-2.214 16.553-6.573 20.979-4.675 4.107-12.701 6.19-24.012 6.19h-14.599v-141.291h-72.73v326.82zM360.428 558.861h19.463c13.271 0 21.359 3.794 24.331 11.375 2.276 7.204 3.221 16.304 2.969 27.171 0 5.815-0.126 10.867-0.442 15.418-0.252 4.675-1.392 8.404-3.352 11.247-1.831 3.157-4.926 5.561-9.352 7.14-4.233 1.454-10.299 2.211-18.2 2.211h-15.418v-74.564zM498.372 688.907h162.082v-62.687h-89.35v-65.587h78.103v-62.685h-78.103v-73.11h92.822v-62.749h-165.557v326.818zM682.507 599.999c0.316 31.782 9.416 55.542 27.425 71.407 17.44 15.29 40.185 22.936 68.181 22.936 28.247 0 51.119-7.646 68.623-23 17.82-15.798 26.92-39.623 27.171-71.407v-30.333h-72.73v37.031c0.254 6.192-0.57 12.639-2.527 19.209-1.264 3.157-3.475 5.938-6.573 8.214-3.221 1.515-7.898 2.404-13.964 2.404-10.615-0.316-17.249-3.855-19.967-10.618-2.211-6.573-3.223-13.017-2.907-19.209v-161.956c0-2.273 0.126-4.865 0.38-7.772 0.568-3.411 1.454-6.824 2.527-10.233 2.717-7.775 9.352-11.756 19.967-12.007 6.067 0 10.744 1.261 13.964 3.791 3.098 2.15 5.309 4.867 6.573 8.216 1.96 7.33 2.782 13.33 2.527 18.007v47.837h72.73v-41.328c-1.451-61.547-33.364-93.015-95.794-94.469-62.685 1.454-94.53 32.922-95.607 94.343v148.937z" />
19
+<glyph unicode="&#xe616;" glyph-name="event_note" d="M598 426v-84h-300v84h300zM810 214v468h-596v-468h596zM810 896c46 0 86-40 86-86v-596c0-46-40-86-86-86h-596c-48 0-86 40-86 86v596c0 46 38 86 86 86h42v86h86v-86h340v86h86v-86h42zM726 598v-86h-428v86h428z" />
18 20
 <glyph unicode="&#xe61d;" glyph-name="phone-talk" d="M640 512c0 70-58 128-128 128v86c118 0 214-96 214-214h-86zM810 512c0 166-132 298-298 298v86c212 0 384-172 384-384h-86zM854 362c24 0 42-18 42-42v-150c0-24-18-42-42-42-400 0-726 326-726 726 0 24 18 42 42 42h150c24 0 42-18 42-42 0-54 8-104 24-152 4-14 2-32-10-44l-94-94c62-122 162-220 282-282l94 94c12 12 30 14 44 10 48-16 98-24 152-24z" />
21
+<glyph unicode="&#xe80b;" glyph-name="public" d="M764 282c56 60 90 142 90 230 0 142-88 266-214 316v-18c0-46-40-84-86-84h-84v-86c0-24-20-42-44-42h-84v-86h256c24 0 42-18 42-42v-128h42c38 0 70-26 82-60zM470 174v82c-46 0-86 40-86 86v42l-204 204c-6-24-10-50-10-76 0-174 132-318 300-338zM512 938c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426z" />
19 22
 <glyph unicode="&#xe901;" glyph-name="avatar" d="M512 204c106 0 200 56 256 138-2 84-172 132-256 132-86 0-254-48-256-132 56-82 150-138 256-138zM512 810c-70 0-128-58-128-128s58-128 128-128 128 58 128 128-58 128-128 128zM512 938c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426z" />
20 23
 <glyph unicode="&#xe902;" glyph-name="download" d="M726 470h-128v170h-172v-170h-128l214-214zM826 596c110-8 198-100 198-212 0-118-96-214-214-214h-554c-142 0-256 114-256 256 0 132 100 240 228 254 54 102 160 174 284 174 156 0 284-110 314-258z" />
21 24
 <glyph unicode="&#xe903;" glyph-name="mic-camera-combined" d="M756.704 628.138l267.296 202.213v-635.075l-267.296 202.213v-191.923c0-12.085-11.296-21.863-25.216-21.863h-706.272c-13.92 0-25.216 9.777-25.216 21.863v612.25c0 12.085 11.296 21.863 25.216 21.863h706.272c13.92 0 25.216-9.777 25.216-21.863v-189.679zM371.338 376.228c47.817 0 86.529 40.232 86.529 89.811v184.835c0 49.651-38.713 89.883-86.529 89.883-47.788 0-86.515-40.232-86.515-89.883v-184.835c0-49.579 38.756-89.811 86.515-89.811v0zM356.754 314.070v-32.78h33.718v33.412c73.858 9.606 131.235 73.73 131.235 151.351v88.232h-30.636v-88.232c0-67.57-53.696-122.534-119.734-122.534-66.024 0-119.691 54.964-119.691 122.534v88.232h-30.636v-88.232c0-79.215 59.674-144.502 135.744-151.969v-0.014z" />

BIN
fonts/jitsi.ttf 파일 보기


BIN
fonts/jitsi.woff 파일 보기


+ 134
- 53
fonts/selection.json 파일 보기

@@ -1,6 +1,87 @@
1 1
 {
2 2
   "IcoMoonType": "selection",
3 3
   "icons": [
4
+    {
5
+      "icon": {
6
+        "paths": [
7
+          "M764 742c56-60 90-142 90-230 0-142-88-266-214-316v18c0 46-40 84-86 84h-84v86c0 24-20 42-44 42h-84v86h256c24 0 42 18 42 42v128h42c38 0 70 26 82 60zM470 850v-82c-46 0-86-40-86-86v-42l-204-204c-6 24-10 50-10 76 0 174 132 318 300 338zM512 86c236 0 426 190 426 426s-190 426-426 426-426-190-426-426 190-426 426-426z"
8
+        ],
9
+        "attrs": [],
10
+        "isMulticolor": false,
11
+        "isMulticolor2": false,
12
+        "tags": [
13
+          "public"
14
+        ],
15
+        "defaultCode": 59403,
16
+        "grid": 24
17
+      },
18
+      "attrs": [],
19
+      "properties": {
20
+        "ligatures": "public",
21
+        "id": 605,
22
+        "order": 920,
23
+        "prevSize": 24,
24
+        "code": 59403,
25
+        "name": "public"
26
+      },
27
+      "setIdx": 0,
28
+      "setId": 2,
29
+      "iconIdx": 605
30
+    },
31
+    {
32
+      "icon": {
33
+        "paths": [
34
+          "M598 598v84h-300v-84h300zM810 810v-468h-596v468h596zM810 128c46 0 86 40 86 86v596c0 46-40 86-86 86h-596c-48 0-86-40-86-86v-596c0-46 38-86 86-86h42v-86h86v86h340v-86h86v86h42zM726 426v86h-428v-86h428z"
35
+        ],
36
+        "attrs": [],
37
+        "isMulticolor": false,
38
+        "isMulticolor2": false,
39
+        "tags": [
40
+          "event_note"
41
+        ],
42
+        "defaultCode": 58902,
43
+        "grid": 24
44
+      },
45
+      "attrs": [],
46
+      "properties": {
47
+        "ligatures": "event_note",
48
+        "id": 252,
49
+        "order": 919,
50
+        "prevSize": 24,
51
+        "code": 58902,
52
+        "name": "event_note"
53
+      },
54
+      "setIdx": 1,
55
+      "setId": 1,
56
+      "iconIdx": 0
57
+    },
58
+    {
59
+      "icon": {
60
+        "paths": [
61
+          "M512 854c166 0 298-134 298-300s-132-298-298-298-298 132-298 298 132 300 298 300zM812 316c52 66 84 148 84 238 0 212-172 384-384 384s-384-172-384-384 172-384 384-384c90 0 174 34 240 86l60-62c22 18 42 38 60 60zM470 598v-256h84v256h-84zM640 42v86h-256v-86h256z"
62
+        ],
63
+        "attrs": [],
64
+        "isMulticolor": false,
65
+        "isMulticolor2": false,
66
+        "tags": [
67
+          "timer"
68
+        ],
69
+        "defaultCode": 58405,
70
+        "grid": 24
71
+      },
72
+      "attrs": [],
73
+      "properties": {
74
+        "ligatures": "timer",
75
+        "id": 760,
76
+        "order": 916,
77
+        "prevSize": 24,
78
+        "code": 58405,
79
+        "name": "timer"
80
+      },
81
+      "setIdx": 1,
82
+      "setId": 1,
83
+      "iconIdx": 1
84
+    },
4 85
     {
5 86
       "icon": {
6 87
         "paths": [
@@ -24,9 +105,9 @@
24 105
         "code": 57770,
25 106
         "name": "bluetooth"
26 107
       },
27
-      "setIdx": 0,
28
-      "setId": 2,
29
-      "iconIdx": 79
108
+      "setIdx": 1,
109
+      "setId": 1,
110
+      "iconIdx": 2
30 111
     },
31 112
     {
32 113
       "icon": {
@@ -51,9 +132,9 @@
51 132
         "code": 58128,
52 133
         "name": "headset"
53 134
       },
54
-      "setIdx": 0,
55
-      "setId": 2,
56
-      "iconIdx": 376
135
+      "setIdx": 1,
136
+      "setId": 1,
137
+      "iconIdx": 3
57 138
     },
58 139
     {
59 140
       "icon": {
@@ -78,9 +159,9 @@
78 159
         "code": 58909,
79 160
         "name": "phone-talk"
80 161
       },
81
-      "setIdx": 0,
82
-      "setId": 2,
83
-      "iconIdx": 566
162
+      "setIdx": 1,
163
+      "setId": 1,
164
+      "iconIdx": 4
84 165
     },
85 166
     {
86 167
       "icon": {
@@ -107,7 +188,7 @@
107 188
       },
108 189
       "setIdx": 1,
109 190
       "setId": 1,
110
-      "iconIdx": 40
191
+      "iconIdx": 5
111 192
     },
112 193
     {
113 194
       "icon": {
@@ -136,7 +217,7 @@
136 217
       },
137 218
       "setIdx": 1,
138 219
       "setId": 1,
139
-      "iconIdx": 41
220
+      "iconIdx": 6
140 221
     },
141 222
     {
142 223
       "icon": {
@@ -163,7 +244,7 @@
163 244
       },
164 245
       "setIdx": 1,
165 246
       "setId": 1,
166
-      "iconIdx": 42
247
+      "iconIdx": 7
167 248
     },
168 249
     {
169 250
       "icon": {
@@ -190,7 +271,7 @@
190 271
       },
191 272
       "setIdx": 1,
192 273
       "setId": 1,
193
-      "iconIdx": 43
274
+      "iconIdx": 8
194 275
     },
195 276
     {
196 277
       "icon": {
@@ -219,7 +300,7 @@
219 300
       },
220 301
       "setIdx": 1,
221 302
       "setId": 1,
222
-      "iconIdx": 0
303
+      "iconIdx": 9
223 304
     },
224 305
     {
225 306
       "icon": {
@@ -248,7 +329,7 @@
248 329
       },
249 330
       "setIdx": 1,
250 331
       "setId": 1,
251
-      "iconIdx": 1
332
+      "iconIdx": 10
252 333
     },
253 334
     {
254 335
       "icon": {
@@ -277,7 +358,7 @@
277 358
       },
278 359
       "setIdx": 1,
279 360
       "setId": 1,
280
-      "iconIdx": 2
361
+      "iconIdx": 11
281 362
     },
282 363
     {
283 364
       "icon": {
@@ -306,7 +387,7 @@
306 387
       },
307 388
       "setIdx": 1,
308 389
       "setId": 1,
309
-      "iconIdx": 3
390
+      "iconIdx": 12
310 391
     },
311 392
     {
312 393
       "icon": {
@@ -335,7 +416,7 @@
335 416
       },
336 417
       "setIdx": 1,
337 418
       "setId": 1,
338
-      "iconIdx": 4
419
+      "iconIdx": 13
339 420
     },
340 421
     {
341 422
       "icon": {
@@ -361,7 +442,7 @@
361 442
       },
362 443
       "setIdx": 1,
363 444
       "setId": 1,
364
-      "iconIdx": 5
445
+      "iconIdx": 14
365 446
     },
366 447
     {
367 448
       "icon": {
@@ -387,7 +468,7 @@
387 468
       },
388 469
       "setIdx": 1,
389 470
       "setId": 1,
390
-      "iconIdx": 6
471
+      "iconIdx": 15
391 472
     },
392 473
     {
393 474
       "icon": {
@@ -413,7 +494,7 @@
413 494
       },
414 495
       "setIdx": 1,
415 496
       "setId": 1,
416
-      "iconIdx": 7
497
+      "iconIdx": 16
417 498
     },
418 499
     {
419 500
       "icon": {
@@ -439,7 +520,7 @@
439 520
       },
440 521
       "setIdx": 1,
441 522
       "setId": 1,
442
-      "iconIdx": 8
523
+      "iconIdx": 17
443 524
     },
444 525
     {
445 526
       "icon": {
@@ -465,7 +546,7 @@
465 546
       },
466 547
       "setIdx": 1,
467 548
       "setId": 1,
468
-      "iconIdx": 9
549
+      "iconIdx": 18
469 550
     },
470 551
     {
471 552
       "icon": {
@@ -491,7 +572,7 @@
491 572
       },
492 573
       "setIdx": 1,
493 574
       "setId": 1,
494
-      "iconIdx": 10
575
+      "iconIdx": 19
495 576
     },
496 577
     {
497 578
       "icon": {
@@ -517,7 +598,7 @@
517 598
       },
518 599
       "setIdx": 1,
519 600
       "setId": 1,
520
-      "iconIdx": 11
601
+      "iconIdx": 20
521 602
     },
522 603
     {
523 604
       "icon": {
@@ -543,7 +624,7 @@
543 624
       },
544 625
       "setIdx": 1,
545 626
       "setId": 1,
546
-      "iconIdx": 12
627
+      "iconIdx": 21
547 628
     },
548 629
     {
549 630
       "icon": {
@@ -569,7 +650,7 @@
569 650
       },
570 651
       "setIdx": 1,
571 652
       "setId": 1,
572
-      "iconIdx": 13
653
+      "iconIdx": 22
573 654
     },
574 655
     {
575 656
       "icon": {
@@ -595,7 +676,7 @@
595 676
       },
596 677
       "setIdx": 1,
597 678
       "setId": 1,
598
-      "iconIdx": 14
679
+      "iconIdx": 23
599 680
     },
600 681
     {
601 682
       "icon": {
@@ -621,7 +702,7 @@
621 702
       },
622 703
       "setIdx": 1,
623 704
       "setId": 1,
624
-      "iconIdx": 15
705
+      "iconIdx": 24
625 706
     },
626 707
     {
627 708
       "icon": {
@@ -647,7 +728,7 @@
647 728
       },
648 729
       "setIdx": 1,
649 730
       "setId": 1,
650
-      "iconIdx": 16
731
+      "iconIdx": 25
651 732
     },
652 733
     {
653 734
       "icon": {
@@ -673,7 +754,7 @@
673 754
       },
674 755
       "setIdx": 1,
675 756
       "setId": 1,
676
-      "iconIdx": 17
757
+      "iconIdx": 26
677 758
     },
678 759
     {
679 760
       "icon": {
@@ -699,7 +780,7 @@
699 780
       },
700 781
       "setIdx": 1,
701 782
       "setId": 1,
702
-      "iconIdx": 18
783
+      "iconIdx": 27
703 784
     },
704 785
     {
705 786
       "icon": {
@@ -725,7 +806,7 @@
725 806
       },
726 807
       "setIdx": 1,
727 808
       "setId": 1,
728
-      "iconIdx": 19
809
+      "iconIdx": 28
729 810
     },
730 811
     {
731 812
       "icon": {
@@ -751,7 +832,7 @@
751 832
       },
752 833
       "setIdx": 1,
753 834
       "setId": 1,
754
-      "iconIdx": 20
835
+      "iconIdx": 29
755 836
     },
756 837
     {
757 838
       "icon": {
@@ -777,7 +858,7 @@
777 858
       },
778 859
       "setIdx": 1,
779 860
       "setId": 1,
780
-      "iconIdx": 21
861
+      "iconIdx": 30
781 862
     },
782 863
     {
783 864
       "icon": {
@@ -803,7 +884,7 @@
803 884
       },
804 885
       "setIdx": 1,
805 886
       "setId": 1,
806
-      "iconIdx": 22
887
+      "iconIdx": 31
807 888
     },
808 889
     {
809 890
       "icon": {
@@ -829,7 +910,7 @@
829 910
       },
830 911
       "setIdx": 1,
831 912
       "setId": 1,
832
-      "iconIdx": 23
913
+      "iconIdx": 32
833 914
     },
834 915
     {
835 916
       "icon": {
@@ -855,7 +936,7 @@
855 936
       },
856 937
       "setIdx": 1,
857 938
       "setId": 1,
858
-      "iconIdx": 24
939
+      "iconIdx": 33
859 940
     },
860 941
     {
861 942
       "icon": {
@@ -881,7 +962,7 @@
881 962
       },
882 963
       "setIdx": 1,
883 964
       "setId": 1,
884
-      "iconIdx": 25
965
+      "iconIdx": 34
885 966
     },
886 967
     {
887 968
       "icon": {
@@ -907,7 +988,7 @@
907 988
       },
908 989
       "setIdx": 1,
909 990
       "setId": 1,
910
-      "iconIdx": 26
991
+      "iconIdx": 35
911 992
     },
912 993
     {
913 994
       "icon": {
@@ -933,7 +1014,7 @@
933 1014
       },
934 1015
       "setIdx": 1,
935 1016
       "setId": 1,
936
-      "iconIdx": 27
1017
+      "iconIdx": 36
937 1018
     },
938 1019
     {
939 1020
       "icon": {
@@ -959,7 +1040,7 @@
959 1040
       },
960 1041
       "setIdx": 1,
961 1042
       "setId": 1,
962
-      "iconIdx": 28
1043
+      "iconIdx": 37
963 1044
     },
964 1045
     {
965 1046
       "icon": {
@@ -985,7 +1066,7 @@
985 1066
       },
986 1067
       "setIdx": 1,
987 1068
       "setId": 1,
988
-      "iconIdx": 29
1069
+      "iconIdx": 38
989 1070
     },
990 1071
     {
991 1072
       "icon": {
@@ -1011,7 +1092,7 @@
1011 1092
       },
1012 1093
       "setIdx": 1,
1013 1094
       "setId": 1,
1014
-      "iconIdx": 30
1095
+      "iconIdx": 39
1015 1096
     },
1016 1097
     {
1017 1098
       "icon": {
@@ -1037,7 +1118,7 @@
1037 1118
       },
1038 1119
       "setIdx": 1,
1039 1120
       "setId": 1,
1040
-      "iconIdx": 31
1121
+      "iconIdx": 40
1041 1122
     },
1042 1123
     {
1043 1124
       "icon": {
@@ -1063,7 +1144,7 @@
1063 1144
       },
1064 1145
       "setIdx": 1,
1065 1146
       "setId": 1,
1066
-      "iconIdx": 32
1147
+      "iconIdx": 41
1067 1148
     },
1068 1149
     {
1069 1150
       "icon": {
@@ -1089,7 +1170,7 @@
1089 1170
       },
1090 1171
       "setIdx": 1,
1091 1172
       "setId": 1,
1092
-      "iconIdx": 33
1173
+      "iconIdx": 42
1093 1174
     },
1094 1175
     {
1095 1176
       "icon": {
@@ -1118,7 +1199,7 @@
1118 1199
       },
1119 1200
       "setIdx": 1,
1120 1201
       "setId": 1,
1121
-      "iconIdx": 34
1202
+      "iconIdx": 43
1122 1203
     },
1123 1204
     {
1124 1205
       "icon": {
@@ -1148,7 +1229,7 @@
1148 1229
       },
1149 1230
       "setIdx": 1,
1150 1231
       "setId": 1,
1151
-      "iconIdx": 35
1232
+      "iconIdx": 44
1152 1233
     },
1153 1234
     {
1154 1235
       "icon": {
@@ -1178,7 +1259,7 @@
1178 1259
       },
1179 1260
       "setIdx": 1,
1180 1261
       "setId": 1,
1181
-      "iconIdx": 36
1262
+      "iconIdx": 45
1182 1263
     },
1183 1264
     {
1184 1265
       "icon": {
@@ -1204,7 +1285,7 @@
1204 1285
       },
1205 1286
       "setIdx": 1,
1206 1287
       "setId": 1,
1207
-      "iconIdx": 37
1288
+      "iconIdx": 46
1208 1289
     },
1209 1290
     {
1210 1291
       "icon": {
@@ -1230,7 +1311,7 @@
1230 1311
       },
1231 1312
       "setIdx": 1,
1232 1313
       "setId": 1,
1233
-      "iconIdx": 38
1314
+      "iconIdx": 47
1234 1315
     },
1235 1316
     {
1236 1317
       "icon": {
@@ -1256,7 +1337,7 @@
1256 1337
       },
1257 1338
       "setIdx": 1,
1258 1339
       "setId": 1,
1259
-      "iconIdx": 39
1340
+      "iconIdx": 48
1260 1341
     }
1261 1342
   ],
1262 1343
   "height": 1024,

+ 5
- 0
package-lock.json 파일 보기

@@ -7064,6 +7064,11 @@
7064 7064
         "minimist": "0.0.8"
7065 7065
       }
7066 7066
     },
7067
+    "moment": {
7068
+      "version": "2.19.4",
7069
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.4.tgz",
7070
+      "integrity": "sha512-1xFTAknSLfc47DIxHDUbnJWC+UwgWxATmymaxIPQpmMh7LBm7ZbwVEsuushqwL2GYZU0jie4xO+TK44hJPjNSQ=="
7071
+    },
7067 7072
     "morgan": {
7068 7073
       "version": "1.6.1",
7069 7074
       "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz",

+ 1
- 0
package.json 파일 보기

@@ -46,6 +46,7 @@
46 46
     "jwt-decode": "2.2.0",
47 47
     "lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#f71ff66fb26f9dd0b49baeeee239345ba268d46d",
48 48
     "lodash": "4.17.4",
49
+    "moment": "2.19.4",
49 50
     "nuclear-js": "1.4.0",
50 51
     "postis": "2.2.0",
51 52
     "prop-types": "15.6.0",

+ 134
- 53
react/features/base/font-icons/jitsi.json 파일 보기

@@ -1,6 +1,87 @@
1 1
 {
2 2
   "IcoMoonType": "selection",
3 3
   "icons": [
4
+    {
5
+      "icon": {
6
+        "paths": [
7
+          "M764 742c56-60 90-142 90-230 0-142-88-266-214-316v18c0 46-40 84-86 84h-84v86c0 24-20 42-44 42h-84v86h256c24 0 42 18 42 42v128h42c38 0 70 26 82 60zM470 850v-82c-46 0-86-40-86-86v-42l-204-204c-6 24-10 50-10 76 0 174 132 318 300 338zM512 86c236 0 426 190 426 426s-190 426-426 426-426-190-426-426 190-426 426-426z"
8
+        ],
9
+        "attrs": [],
10
+        "isMulticolor": false,
11
+        "isMulticolor2": false,
12
+        "tags": [
13
+          "public"
14
+        ],
15
+        "defaultCode": 59403,
16
+        "grid": 24
17
+      },
18
+      "attrs": [],
19
+      "properties": {
20
+        "ligatures": "public",
21
+        "id": 605,
22
+        "order": 920,
23
+        "prevSize": 24,
24
+        "code": 59403,
25
+        "name": "public"
26
+      },
27
+      "setIdx": 0,
28
+      "setId": 2,
29
+      "iconIdx": 605
30
+    },
31
+    {
32
+      "icon": {
33
+        "paths": [
34
+          "M598 598v84h-300v-84h300zM810 810v-468h-596v468h596zM810 128c46 0 86 40 86 86v596c0 46-40 86-86 86h-596c-48 0-86-40-86-86v-596c0-46 38-86 86-86h42v-86h86v86h340v-86h86v86h42zM726 426v86h-428v-86h428z"
35
+        ],
36
+        "attrs": [],
37
+        "isMulticolor": false,
38
+        "isMulticolor2": false,
39
+        "tags": [
40
+          "event_note"
41
+        ],
42
+        "defaultCode": 58902,
43
+        "grid": 24
44
+      },
45
+      "attrs": [],
46
+      "properties": {
47
+        "ligatures": "event_note",
48
+        "id": 252,
49
+        "order": 919,
50
+        "prevSize": 24,
51
+        "code": 58902,
52
+        "name": "event_note"
53
+      },
54
+      "setIdx": 1,
55
+      "setId": 1,
56
+      "iconIdx": 0
57
+    },
58
+    {
59
+      "icon": {
60
+        "paths": [
61
+          "M512 854c166 0 298-134 298-300s-132-298-298-298-298 132-298 298 132 300 298 300zM812 316c52 66 84 148 84 238 0 212-172 384-384 384s-384-172-384-384 172-384 384-384c90 0 174 34 240 86l60-62c22 18 42 38 60 60zM470 598v-256h84v256h-84zM640 42v86h-256v-86h256z"
62
+        ],
63
+        "attrs": [],
64
+        "isMulticolor": false,
65
+        "isMulticolor2": false,
66
+        "tags": [
67
+          "timer"
68
+        ],
69
+        "defaultCode": 58405,
70
+        "grid": 24
71
+      },
72
+      "attrs": [],
73
+      "properties": {
74
+        "ligatures": "timer",
75
+        "id": 760,
76
+        "order": 916,
77
+        "prevSize": 24,
78
+        "code": 58405,
79
+        "name": "timer"
80
+      },
81
+      "setIdx": 1,
82
+      "setId": 1,
83
+      "iconIdx": 1
84
+    },
4 85
     {
5 86
       "icon": {
6 87
         "paths": [
@@ -24,9 +105,9 @@
24 105
         "code": 57770,
25 106
         "name": "bluetooth"
26 107
       },
27
-      "setIdx": 0,
28
-      "setId": 2,
29
-      "iconIdx": 79
108
+      "setIdx": 1,
109
+      "setId": 1,
110
+      "iconIdx": 2
30 111
     },
31 112
     {
32 113
       "icon": {
@@ -51,9 +132,9 @@
51 132
         "code": 58128,
52 133
         "name": "headset"
53 134
       },
54
-      "setIdx": 0,
55
-      "setId": 2,
56
-      "iconIdx": 376
135
+      "setIdx": 1,
136
+      "setId": 1,
137
+      "iconIdx": 3
57 138
     },
58 139
     {
59 140
       "icon": {
@@ -78,9 +159,9 @@
78 159
         "code": 58909,
79 160
         "name": "phone-talk"
80 161
       },
81
-      "setIdx": 0,
82
-      "setId": 2,
83
-      "iconIdx": 566
162
+      "setIdx": 1,
163
+      "setId": 1,
164
+      "iconIdx": 4
84 165
     },
85 166
     {
86 167
       "icon": {
@@ -107,7 +188,7 @@
107 188
       },
108 189
       "setIdx": 1,
109 190
       "setId": 1,
110
-      "iconIdx": 40
191
+      "iconIdx": 5
111 192
     },
112 193
     {
113 194
       "icon": {
@@ -136,7 +217,7 @@
136 217
       },
137 218
       "setIdx": 1,
138 219
       "setId": 1,
139
-      "iconIdx": 41
220
+      "iconIdx": 6
140 221
     },
141 222
     {
142 223
       "icon": {
@@ -163,7 +244,7 @@
163 244
       },
164 245
       "setIdx": 1,
165 246
       "setId": 1,
166
-      "iconIdx": 42
247
+      "iconIdx": 7
167 248
     },
168 249
     {
169 250
       "icon": {
@@ -190,7 +271,7 @@
190 271
       },
191 272
       "setIdx": 1,
192 273
       "setId": 1,
193
-      "iconIdx": 43
274
+      "iconIdx": 8
194 275
     },
195 276
     {
196 277
       "icon": {
@@ -219,7 +300,7 @@
219 300
       },
220 301
       "setIdx": 1,
221 302
       "setId": 1,
222
-      "iconIdx": 0
303
+      "iconIdx": 9
223 304
     },
224 305
     {
225 306
       "icon": {
@@ -248,7 +329,7 @@
248 329
       },
249 330
       "setIdx": 1,
250 331
       "setId": 1,
251
-      "iconIdx": 1
332
+      "iconIdx": 10
252 333
     },
253 334
     {
254 335
       "icon": {
@@ -277,7 +358,7 @@
277 358
       },
278 359
       "setIdx": 1,
279 360
       "setId": 1,
280
-      "iconIdx": 2
361
+      "iconIdx": 11
281 362
     },
282 363
     {
283 364
       "icon": {
@@ -306,7 +387,7 @@
306 387
       },
307 388
       "setIdx": 1,
308 389
       "setId": 1,
309
-      "iconIdx": 3
390
+      "iconIdx": 12
310 391
     },
311 392
     {
312 393
       "icon": {
@@ -335,7 +416,7 @@
335 416
       },
336 417
       "setIdx": 1,
337 418
       "setId": 1,
338
-      "iconIdx": 4
419
+      "iconIdx": 13
339 420
     },
340 421
     {
341 422
       "icon": {
@@ -361,7 +442,7 @@
361 442
       },
362 443
       "setIdx": 1,
363 444
       "setId": 1,
364
-      "iconIdx": 5
445
+      "iconIdx": 14
365 446
     },
366 447
     {
367 448
       "icon": {
@@ -387,7 +468,7 @@
387 468
       },
388 469
       "setIdx": 1,
389 470
       "setId": 1,
390
-      "iconIdx": 6
471
+      "iconIdx": 15
391 472
     },
392 473
     {
393 474
       "icon": {
@@ -413,7 +494,7 @@
413 494
       },
414 495
       "setIdx": 1,
415 496
       "setId": 1,
416
-      "iconIdx": 7
497
+      "iconIdx": 16
417 498
     },
418 499
     {
419 500
       "icon": {
@@ -439,7 +520,7 @@
439 520
       },
440 521
       "setIdx": 1,
441 522
       "setId": 1,
442
-      "iconIdx": 8
523
+      "iconIdx": 17
443 524
     },
444 525
     {
445 526
       "icon": {
@@ -465,7 +546,7 @@
465 546
       },
466 547
       "setIdx": 1,
467 548
       "setId": 1,
468
-      "iconIdx": 9
549
+      "iconIdx": 18
469 550
     },
470 551
     {
471 552
       "icon": {
@@ -491,7 +572,7 @@
491 572
       },
492 573
       "setIdx": 1,
493 574
       "setId": 1,
494
-      "iconIdx": 10
575
+      "iconIdx": 19
495 576
     },
496 577
     {
497 578
       "icon": {
@@ -517,7 +598,7 @@
517 598
       },
518 599
       "setIdx": 1,
519 600
       "setId": 1,
520
-      "iconIdx": 11
601
+      "iconIdx": 20
521 602
     },
522 603
     {
523 604
       "icon": {
@@ -543,7 +624,7 @@
543 624
       },
544 625
       "setIdx": 1,
545 626
       "setId": 1,
546
-      "iconIdx": 12
627
+      "iconIdx": 21
547 628
     },
548 629
     {
549 630
       "icon": {
@@ -569,7 +650,7 @@
569 650
       },
570 651
       "setIdx": 1,
571 652
       "setId": 1,
572
-      "iconIdx": 13
653
+      "iconIdx": 22
573 654
     },
574 655
     {
575 656
       "icon": {
@@ -595,7 +676,7 @@
595 676
       },
596 677
       "setIdx": 1,
597 678
       "setId": 1,
598
-      "iconIdx": 14
679
+      "iconIdx": 23
599 680
     },
600 681
     {
601 682
       "icon": {
@@ -621,7 +702,7 @@
621 702
       },
622 703
       "setIdx": 1,
623 704
       "setId": 1,
624
-      "iconIdx": 15
705
+      "iconIdx": 24
625 706
     },
626 707
     {
627 708
       "icon": {
@@ -647,7 +728,7 @@
647 728
       },
648 729
       "setIdx": 1,
649 730
       "setId": 1,
650
-      "iconIdx": 16
731
+      "iconIdx": 25
651 732
     },
652 733
     {
653 734
       "icon": {
@@ -673,7 +754,7 @@
673 754
       },
674 755
       "setIdx": 1,
675 756
       "setId": 1,
676
-      "iconIdx": 17
757
+      "iconIdx": 26
677 758
     },
678 759
     {
679 760
       "icon": {
@@ -699,7 +780,7 @@
699 780
       },
700 781
       "setIdx": 1,
701 782
       "setId": 1,
702
-      "iconIdx": 18
783
+      "iconIdx": 27
703 784
     },
704 785
     {
705 786
       "icon": {
@@ -725,7 +806,7 @@
725 806
       },
726 807
       "setIdx": 1,
727 808
       "setId": 1,
728
-      "iconIdx": 19
809
+      "iconIdx": 28
729 810
     },
730 811
     {
731 812
       "icon": {
@@ -751,7 +832,7 @@
751 832
       },
752 833
       "setIdx": 1,
753 834
       "setId": 1,
754
-      "iconIdx": 20
835
+      "iconIdx": 29
755 836
     },
756 837
     {
757 838
       "icon": {
@@ -777,7 +858,7 @@
777 858
       },
778 859
       "setIdx": 1,
779 860
       "setId": 1,
780
-      "iconIdx": 21
861
+      "iconIdx": 30
781 862
     },
782 863
     {
783 864
       "icon": {
@@ -803,7 +884,7 @@
803 884
       },
804 885
       "setIdx": 1,
805 886
       "setId": 1,
806
-      "iconIdx": 22
887
+      "iconIdx": 31
807 888
     },
808 889
     {
809 890
       "icon": {
@@ -829,7 +910,7 @@
829 910
       },
830 911
       "setIdx": 1,
831 912
       "setId": 1,
832
-      "iconIdx": 23
913
+      "iconIdx": 32
833 914
     },
834 915
     {
835 916
       "icon": {
@@ -855,7 +936,7 @@
855 936
       },
856 937
       "setIdx": 1,
857 938
       "setId": 1,
858
-      "iconIdx": 24
939
+      "iconIdx": 33
859 940
     },
860 941
     {
861 942
       "icon": {
@@ -881,7 +962,7 @@
881 962
       },
882 963
       "setIdx": 1,
883 964
       "setId": 1,
884
-      "iconIdx": 25
965
+      "iconIdx": 34
885 966
     },
886 967
     {
887 968
       "icon": {
@@ -907,7 +988,7 @@
907 988
       },
908 989
       "setIdx": 1,
909 990
       "setId": 1,
910
-      "iconIdx": 26
991
+      "iconIdx": 35
911 992
     },
912 993
     {
913 994
       "icon": {
@@ -933,7 +1014,7 @@
933 1014
       },
934 1015
       "setIdx": 1,
935 1016
       "setId": 1,
936
-      "iconIdx": 27
1017
+      "iconIdx": 36
937 1018
     },
938 1019
     {
939 1020
       "icon": {
@@ -959,7 +1040,7 @@
959 1040
       },
960 1041
       "setIdx": 1,
961 1042
       "setId": 1,
962
-      "iconIdx": 28
1043
+      "iconIdx": 37
963 1044
     },
964 1045
     {
965 1046
       "icon": {
@@ -985,7 +1066,7 @@
985 1066
       },
986 1067
       "setIdx": 1,
987 1068
       "setId": 1,
988
-      "iconIdx": 29
1069
+      "iconIdx": 38
989 1070
     },
990 1071
     {
991 1072
       "icon": {
@@ -1011,7 +1092,7 @@
1011 1092
       },
1012 1093
       "setIdx": 1,
1013 1094
       "setId": 1,
1014
-      "iconIdx": 30
1095
+      "iconIdx": 39
1015 1096
     },
1016 1097
     {
1017 1098
       "icon": {
@@ -1037,7 +1118,7 @@
1037 1118
       },
1038 1119
       "setIdx": 1,
1039 1120
       "setId": 1,
1040
-      "iconIdx": 31
1121
+      "iconIdx": 40
1041 1122
     },
1042 1123
     {
1043 1124
       "icon": {
@@ -1063,7 +1144,7 @@
1063 1144
       },
1064 1145
       "setIdx": 1,
1065 1146
       "setId": 1,
1066
-      "iconIdx": 32
1147
+      "iconIdx": 41
1067 1148
     },
1068 1149
     {
1069 1150
       "icon": {
@@ -1089,7 +1170,7 @@
1089 1170
       },
1090 1171
       "setIdx": 1,
1091 1172
       "setId": 1,
1092
-      "iconIdx": 33
1173
+      "iconIdx": 42
1093 1174
     },
1094 1175
     {
1095 1176
       "icon": {
@@ -1118,7 +1199,7 @@
1118 1199
       },
1119 1200
       "setIdx": 1,
1120 1201
       "setId": 1,
1121
-      "iconIdx": 34
1202
+      "iconIdx": 43
1122 1203
     },
1123 1204
     {
1124 1205
       "icon": {
@@ -1148,7 +1229,7 @@
1148 1229
       },
1149 1230
       "setIdx": 1,
1150 1231
       "setId": 1,
1151
-      "iconIdx": 35
1232
+      "iconIdx": 44
1152 1233
     },
1153 1234
     {
1154 1235
       "icon": {
@@ -1178,7 +1259,7 @@
1178 1259
       },
1179 1260
       "setIdx": 1,
1180 1261
       "setId": 1,
1181
-      "iconIdx": 36
1262
+      "iconIdx": 45
1182 1263
     },
1183 1264
     {
1184 1265
       "icon": {
@@ -1204,7 +1285,7 @@
1204 1285
       },
1205 1286
       "setIdx": 1,
1206 1287
       "setId": 1,
1207
-      "iconIdx": 37
1288
+      "iconIdx": 46
1208 1289
     },
1209 1290
     {
1210 1291
       "icon": {
@@ -1230,7 +1311,7 @@
1230 1311
       },
1231 1312
       "setIdx": 1,
1232 1313
       "setId": 1,
1233
-      "iconIdx": 38
1314
+      "iconIdx": 47
1234 1315
     },
1235 1316
     {
1236 1317
       "icon": {
@@ -1256,7 +1337,7 @@
1256 1337
       },
1257 1338
       "setIdx": 1,
1258 1339
       "setId": 1,
1259
-      "iconIdx": 39
1340
+      "iconIdx": 48
1260 1341
     }
1261 1342
   ],
1262 1343
   "height": 1024,

+ 20
- 0
react/features/base/lib-jitsi-meet/native/Storage.js 파일 보기

@@ -88,6 +88,26 @@ export default class Storage {
88 88
         return this.hasOwnProperty(key) ? this[key] : null;
89 89
     }
90 90
 
91
+    /**
92
+     * Returns the value associated with a specific key in this storage in an
93
+     * async manner. This method is required for those cases where we need
94
+     * the stored data but we're not sure yet whether the {@code Storage}
95
+     * is already initialised or not - e.g. on app start.
96
+     *
97
+     * @private
98
+     * @param {string} key - The name of the key to retrieve the value of.
99
+     * @returns {Promise}
100
+     */
101
+    _getItemAsync(key) {
102
+        return new Promise(resolve => {
103
+            AsyncStorage.getItem(
104
+                `${String(this._keyPrefix)}${key}`,
105
+                (error, result) => {
106
+                    resolve(result ? result : null);
107
+                });
108
+        });
109
+    }
110
+
91 111
     /**
92 112
      * Returns the name of the nth key in this storage.
93 113
      *

+ 101
- 0
react/features/recent-list/components/AbstractRecentList.js 파일 보기

@@ -0,0 +1,101 @@
1
+// @flow
2
+
3
+import { Component } from 'react';
4
+import { ListView } from 'react-native';
5
+
6
+import { getRecentRooms } from '../functions';
7
+
8
+import { appNavigate } from '../../app';
9
+
10
+/**
11
+ * The type of the React {@code Component} state of {@link AbstractRecentList}.
12
+ */
13
+type State = {
14
+
15
+    /**
16
+     *  The {@code ListView.DataSource} to be used for the {@code ListView}.
17
+     *  Its content comes from the native implementation of
18
+     *  {@code window.localStorage}.
19
+     */
20
+    dataSource: Object
21
+}
22
+
23
+/**
24
+ * The type of the React {@code Component} props of {@link AbstractRecentList}
25
+ */
26
+type Props = {
27
+
28
+    /**
29
+     * Redux store dispatch function.
30
+     */
31
+    dispatch: Dispatch<*>,
32
+}
33
+
34
+/**
35
+ * Implements a React {@link Component} which represents the list of
36
+ * conferences recently joined, similar to how a list of last dialed
37
+ * numbers list would do on a mobile
38
+ *
39
+ * @extends Component
40
+ */
41
+export default class AbstractRecentList extends Component<Props, State> {
42
+
43
+    /**
44
+    * The datasource that backs the {@code ListView}
45
+    */
46
+    listDataSource = new ListView.DataSource({
47
+        rowHasChanged: (r1, r2) =>
48
+            r1.conference !== r2.conference
49
+                && r1.dateTimeStamp !== r2.dateTimeStamp
50
+    });;
51
+
52
+    /**
53
+     * Initializes a new {@code AbstractRecentList} instance.
54
+     */
55
+    constructor() {
56
+        super();
57
+
58
+        this.state = {
59
+            dataSource: this.listDataSource.cloneWithRows([])
60
+        };
61
+    }
62
+
63
+    /**
64
+     * Implements React's {@link Component#componentWillMount()}. Invoked
65
+     * immediately before mounting occurs.
66
+     *
67
+     * @inheritdoc
68
+     */
69
+    componentWillMount() {
70
+        // this must be done asynchronously because we don't have the storage
71
+        // initiated on app startup immediately.
72
+        getRecentRooms().then(rooms => {
73
+            this.setState({
74
+                dataSource: this.listDataSource.cloneWithRows(rooms)
75
+            });
76
+        });
77
+    }
78
+
79
+    /**
80
+    * Creates a bound onPress action for the list item.
81
+    *
82
+    * @param {string} room - The selected room.
83
+    * @returns {Function}
84
+    */
85
+    _onSelect(room) {
86
+        return this._onJoin.bind(this, room);
87
+    }
88
+
89
+    /**
90
+    * Joins the selected room.
91
+    *
92
+    * @param {string} room - The selected room.
93
+    * @returns {void}
94
+    */
95
+    _onJoin(room) {
96
+        if (room) {
97
+            this.props.dispatch(appNavigate(room));
98
+        }
99
+    }
100
+
101
+}

+ 208
- 0
react/features/recent-list/components/RecentList.native.js 파일 보기

@@ -0,0 +1,208 @@
1
+import React from 'react';
2
+import { ListView, Text, TouchableHighlight, View } from 'react-native';
3
+import { connect } from 'react-redux';
4
+
5
+import AbstractRecentList from './AbstractRecentList';
6
+import styles, { UNDERLAY_COLOR } from './styles';
7
+
8
+import { Icon } from '../../base/font-icons';
9
+
10
+/**
11
+ * The native container rendering the list of the recently joined rooms.
12
+ *
13
+ * @extends AbstractRecentList
14
+ */
15
+class RecentList extends AbstractRecentList {
16
+    /**
17
+     * Initializes a new {@code RecentList} instance.
18
+     *
19
+     */
20
+    constructor() {
21
+        super();
22
+
23
+        this._getAvatarStyle = this._getAvatarStyle.bind(this);
24
+        this._onSelect = this._onSelect.bind(this);
25
+        this._renderConfDuration = this._renderConfDuration.bind(this);
26
+        this._renderRow = this._renderRow.bind(this);
27
+        this._renderServerInfo = this._renderServerInfo.bind(this);
28
+    }
29
+
30
+    /**
31
+     * Implements React's {@link Component#render()}. Renders a list of
32
+     * recently joined rooms.
33
+     *
34
+     * @inheritdoc
35
+     * @returns {ReactElement}
36
+     */
37
+    render() {
38
+        if (!this.state.dataSource.getRowCount()) {
39
+            return null;
40
+        }
41
+
42
+        return (
43
+            <View style = { styles.container }>
44
+                <ListView
45
+                    dataSource = { this.state.dataSource }
46
+                    enableEmptySections = { true }
47
+                    renderRow = { this._renderRow } />
48
+            </View>
49
+        );
50
+    }
51
+
52
+    /**
53
+    * Renders the list of recently joined rooms.
54
+    *
55
+    * @private
56
+    * @param {Object} data - The row data to be rendered.
57
+    * @returns {ReactElement}
58
+    */
59
+    _renderRow(data) {
60
+        return (
61
+            <TouchableHighlight
62
+                onPress = { this._onSelect(data.conference) }
63
+                underlayColor = { UNDERLAY_COLOR } >
64
+                <View style = { styles.row } >
65
+                    <View style = { styles.avatarContainer } >
66
+                        <View style = { this._getAvatarStyle(data) } >
67
+                            <Text style = { styles.avatarContent }>
68
+                                { data.initials }
69
+                            </Text>
70
+                        </View>
71
+                    </View>
72
+                    <View style = { styles.detailsContainer } >
73
+                        <Text
74
+                            numberOfLines = { 1 }
75
+                            style = { styles.roomName }>
76
+                            { data.room }
77
+                        </Text>
78
+                        <View style = { styles.infoWithIcon } >
79
+                            <Icon
80
+                                name = 'event_note'
81
+                                style = { styles.inlineIcon } />
82
+                            <Text style = { styles.date }>
83
+                                { data.dateString }
84
+                            </Text>
85
+                        </View>
86
+                        {
87
+                            this._renderConfDuration(data)
88
+                        }
89
+                        {
90
+                            this._renderServerInfo(data)
91
+                        }
92
+                    </View>
93
+                </View>
94
+            </TouchableHighlight>
95
+        );
96
+    }
97
+
98
+    /**
99
+    * Assembles the style array of the avatar based on if the conference
100
+    * was a home or remote server conference (based on current app setting).
101
+    *
102
+    * @private
103
+    * @param {Object} recentListEntry - The recent list entry being rendered.
104
+    * @returns {Array<Object>}
105
+    */
106
+    _getAvatarStyle(recentListEntry) {
107
+        const avatarStyles = [ styles.avatar ];
108
+
109
+        if (recentListEntry.baseURL !== this.props._homeServer) {
110
+            avatarStyles.push(
111
+                this._getColorForServerName(recentListEntry.serverName)
112
+            );
113
+        }
114
+
115
+        return avatarStyles;
116
+    }
117
+
118
+    /**
119
+    * Returns a style (color) based on the server name, so then the
120
+    * same server will always be rendered with the same avatar color.
121
+    *
122
+    * @private
123
+    * @param {string} serverName - The recent list entry being rendered.
124
+    * @returns {Object}
125
+    */
126
+    _getColorForServerName(serverName) {
127
+        let nameHash = 0;
128
+
129
+        for (let i = 0; i < serverName.length; i++) {
130
+            nameHash += serverName.codePointAt(i);
131
+        }
132
+
133
+        return styles[`avatarRemoteServer${(nameHash % 5) + 1}`];
134
+    }
135
+
136
+    /**
137
+    * Renders the server info component based on if the entry was
138
+    * on a different server or not.
139
+    *
140
+    * @private
141
+    * @param {Object} recentListEntry - The recent list entry being rendered.
142
+    * @returns {ReactElement}
143
+    */
144
+    _renderServerInfo(recentListEntry) {
145
+        if (recentListEntry.baseURL !== this.props._homeServer) {
146
+            return (
147
+                <View style = { styles.infoWithIcon } >
148
+                    <Icon
149
+                        name = 'public'
150
+                        style = { styles.inlineIcon } />
151
+                    <Text style = { styles.serverName }>
152
+                        { recentListEntry.serverName }
153
+                    </Text>
154
+                </View>
155
+            );
156
+        }
157
+
158
+        return null;
159
+    }
160
+
161
+    /**
162
+    * Renders the conference duration if available.
163
+    *
164
+    * @private
165
+    * @param {Object} recentListEntry - The recent list entry being rendered.
166
+    * @returns {ReactElement}
167
+    */
168
+    _renderConfDuration(recentListEntry) {
169
+        if (recentListEntry.conferenceDurationString) {
170
+            return (
171
+                <View style = { styles.infoWithIcon } >
172
+                    <Icon
173
+                        name = 'timer'
174
+                        style = { styles.inlineIcon } />
175
+                    <Text style = { styles.confLength }>
176
+                        { recentListEntry.conferenceDurationString }
177
+                    </Text>
178
+                </View>
179
+            );
180
+        }
181
+
182
+        return null;
183
+    }
184
+}
185
+
186
+/**
187
+ * Maps (parts of) the Redux state to the associated RecentList's props.
188
+ *
189
+ * @param {Object} state - The Redux state.
190
+ * @private
191
+ * @returns {{
192
+ *     _homeServer: string
193
+ * }}
194
+ */
195
+function _mapStateToProps(state) {
196
+    return {
197
+        /**
198
+         * The default server name based on which we determine
199
+         * the render method.
200
+         *
201
+         * @private
202
+         * @type {string}
203
+         */
204
+        _homeServer: state['features/app'].app._getDefaultURL()
205
+    };
206
+}
207
+
208
+export default connect(_mapStateToProps)(RecentList);

+ 1
- 0
react/features/recent-list/components/index.js 파일 보기

@@ -0,0 +1 @@
1
+export { default as RecentList } from './RecentList';

+ 154
- 0
react/features/recent-list/components/styles.js 파일 보기

@@ -0,0 +1,154 @@
1
+import {
2
+    createStyleSheet,
3
+    BoxModel
4
+} from '../../base/styles';
5
+
6
+const AVATAR_OPACITY = 0.4;
7
+const AVATAR_SIZE = 65;
8
+const OVERLAY_FONT_COLOR = 'rgba(255, 255, 255, 0.6)';
9
+
10
+export const UNDERLAY_COLOR = 'rgba(255, 255, 255, 0.2)';
11
+
12
+/**
13
+ * The styles of the React {@code Components} of the feature: recent list
14
+ * {@code RecentList}.
15
+ */
16
+export default createStyleSheet({
17
+
18
+    /**
19
+    * The style of the actual avatar
20
+    */
21
+    avatar: {
22
+        width: AVATAR_SIZE,
23
+        height: AVATAR_SIZE,
24
+        alignItems: 'center',
25
+        backgroundColor: `rgba(23, 160, 219, ${AVATAR_OPACITY})`,
26
+        justifyContent: 'center',
27
+        borderRadius: AVATAR_SIZE
28
+    },
29
+
30
+    /**
31
+    * The style of the avatar container that makes the avatar rounded.
32
+    */
33
+    avatarContainer: {
34
+        flexDirection: 'row',
35
+        justifyContent: 'space-around',
36
+        alignItems: 'center',
37
+        paddingTop: 5
38
+    },
39
+
40
+    /**
41
+    * Simple {@code Text} content of the avatar (the actual initials)
42
+    */
43
+    avatarContent: {
44
+        color: OVERLAY_FONT_COLOR,
45
+        fontSize: 32,
46
+        fontWeight: '100',
47
+        backgroundColor: 'rgba(0, 0, 0, 0)',
48
+        textAlign: 'center'
49
+    },
50
+
51
+    /**
52
+    * List of styles of the avatar of a remote meeting
53
+    * (not the default server). The number of colors are limited
54
+    * because they should match nicely.
55
+    */
56
+    avatarRemoteServer1: {
57
+        backgroundColor: `rgba(232, 105, 156, ${AVATAR_OPACITY})`
58
+    },
59
+
60
+    avatarRemoteServer2: {
61
+        backgroundColor: `rgba(255, 198, 115, ${AVATAR_OPACITY})`
62
+    },
63
+
64
+    avatarRemoteServer3: {
65
+        backgroundColor: `rgba(128, 128, 255, ${AVATAR_OPACITY})`
66
+    },
67
+
68
+    avatarRemoteServer4: {
69
+        backgroundColor: `rgba(105, 232, 194, ${AVATAR_OPACITY})`
70
+    },
71
+
72
+    avatarRemoteServer5: {
73
+        backgroundColor: `rgba(234, 255, 128, ${AVATAR_OPACITY})`
74
+    },
75
+
76
+    /**
77
+    * Style of the conference length (if rendered)
78
+    */
79
+    confLength: {
80
+        color: OVERLAY_FONT_COLOR,
81
+        fontWeight: 'normal'
82
+    },
83
+
84
+    /**
85
+    * This is the top level container style of the list
86
+    */
87
+    container: {
88
+        flex: 1
89
+    },
90
+
91
+    /**
92
+    * Second line of the list (date).
93
+    * May be extended with server name later.
94
+    */
95
+    date: {
96
+        color: OVERLAY_FONT_COLOR
97
+    },
98
+
99
+    /**
100
+    * The style of the details container (right side) of the list
101
+    */
102
+    detailsContainer: {
103
+        flex: 1,
104
+        flexDirection: 'column',
105
+        justifyContent: 'center',
106
+        marginLeft: 2 * BoxModel.margin,
107
+        alignItems: 'flex-start'
108
+    },
109
+
110
+    /**
111
+    * The container for an info line with an inline icon.
112
+    */
113
+    infoWithIcon: {
114
+        flexDirection: 'row',
115
+        justifyContent: 'flex-start',
116
+        alignItems: 'center'
117
+    },
118
+
119
+    /**
120
+    * Style of an inline icon in an info line.
121
+    */
122
+    inlineIcon: {
123
+        color: OVERLAY_FONT_COLOR,
124
+        marginRight: 5
125
+    },
126
+
127
+    /**
128
+    * First line of the list (room name)
129
+    */
130
+    roomName: {
131
+        fontSize: 18,
132
+        fontWeight: 'bold',
133
+        color: OVERLAY_FONT_COLOR
134
+    },
135
+
136
+    /**
137
+    * The style of one single row in the list
138
+    */
139
+    row: {
140
+        padding: 8,
141
+        paddingBottom: 0,
142
+        flex: 1,
143
+        flexDirection: 'row',
144
+        alignItems: 'center'
145
+    },
146
+
147
+    /**
148
+    * Style of the server name component (if rendered)
149
+    */
150
+    serverName: {
151
+        color: OVERLAY_FONT_COLOR,
152
+        fontWeight: 'normal'
153
+    }
154
+});

+ 11
- 0
react/features/recent-list/constants.js 파일 보기

@@ -0,0 +1,11 @@
1
+/**
2
+ * The max size of the list.
3
+ */
4
+export const LIST_SIZE = 30;
5
+
6
+/**
7
+ * The name of the {@code localStorage} item where recent rooms are stored.
8
+ *
9
+ * @type {string}
10
+ */
11
+export const RECENT_URL_STORAGE = 'recentURLs';

+ 132
- 0
react/features/recent-list/functions.js 파일 보기

@@ -0,0 +1,132 @@
1
+// @flow
2
+
3
+import moment from 'moment';
4
+
5
+import { RECENT_URL_STORAGE } from './constants';
6
+
7
+import { i18next } from '../base/i18n';
8
+import { parseURIString } from '../base/util';
9
+
10
+/**
11
+* Retreives the recent room list and generates all the data needed
12
+* to be displayed.
13
+*
14
+* @returns {Promise} The {@code Promise} to be resolved when the list
15
+* is available.
16
+*/
17
+export function getRecentRooms(): Promise<Array<Object>> {
18
+    return new Promise(resolve => {
19
+        window.localStorage._getItemAsync(RECENT_URL_STORAGE)
20
+            .then(recentUrls => {
21
+                if (recentUrls) {
22
+                    const recentUrlsObj = JSON.parse(recentUrls);
23
+                    const recentRoomDS = [];
24
+
25
+                    for (const entry of recentUrlsObj) {
26
+                        const location = parseURIString(entry.conference);
27
+
28
+                        if (location && location.room && location.hostname) {
29
+                            recentRoomDS.push({
30
+                                baseURL:
31
+                                    `${location.protocol}//${location.host}`,
32
+                                conference: entry.conference,
33
+                                dateTimeStamp: entry.date,
34
+                                conferenceDuration: entry.conferenceDuration,
35
+                                dateString: _getDateString(
36
+                                    entry.date
37
+                                ),
38
+                                conferenceDurationString: _getLengthString(
39
+                                    entry.conferenceDuration
40
+                                ),
41
+                                initials: _getInitials(location.room),
42
+                                room: location.room,
43
+                                serverName: location.hostname
44
+                            });
45
+                        }
46
+                    }
47
+
48
+                    resolve(recentRoomDS.reverse());
49
+                } else {
50
+                    resolve([]);
51
+                }
52
+            });
53
+    });
54
+}
55
+
56
+/**
57
+* Retreives the recent URL list as a list of objects.
58
+*
59
+* @returns {Array} The list of already stored recent URLs.
60
+*/
61
+export function getRecentUrls() {
62
+    let recentUrls = window.localStorage.getItem(RECENT_URL_STORAGE);
63
+
64
+    if (recentUrls) {
65
+        recentUrls = JSON.parse(recentUrls);
66
+    } else {
67
+        recentUrls = [];
68
+    }
69
+
70
+    return recentUrls;
71
+}
72
+
73
+/**
74
+* Updates the recent URL list.
75
+*
76
+* @param {Array} recentUrls - The new URL list.
77
+* @returns {void}
78
+*/
79
+export function updaterecentUrls(recentUrls: Array<Object>) {
80
+    window.localStorage.setItem(
81
+        RECENT_URL_STORAGE,
82
+        JSON.stringify(recentUrls)
83
+    );
84
+}
85
+
86
+/**
87
+* Returns a well formatted date string to be displayed in the list.
88
+*
89
+* @private
90
+* @param {number} dateTimeStamp - The UTC timestamp to be converted to String.
91
+* @returns {string}
92
+*/
93
+function _getDateString(dateTimeStamp: number) {
94
+    const date = new Date(dateTimeStamp);
95
+
96
+    if (date.toDateString() === new Date().toDateString()) {
97
+        // the date is today, we use fromNow format
98
+
99
+        return moment(date)
100
+                .locale(i18next.language)
101
+                .fromNow();
102
+    }
103
+
104
+    return moment(date)
105
+            .locale(i18next.language)
106
+            .format('lll');
107
+}
108
+
109
+/**
110
+* Returns a well formatted duration string to be displayed
111
+* as the conference length.
112
+*
113
+* @private
114
+* @param {number} duration - The duration in MS.
115
+* @returns {string}
116
+*/
117
+function _getLengthString(duration: number) {
118
+    return moment.duration(duration)
119
+            .locale(i18next.language)
120
+            .humanize();
121
+}
122
+
123
+/**
124
+* Returns the initials supposed to be used based on the room name.
125
+*
126
+* @private
127
+* @param {string} room - The room name.
128
+* @returns {string}
129
+*/
130
+function _getInitials(room: string) {
131
+    return room && room.charAt(0) ? room.charAt(0).toUpperCase() : '?';
132
+}

+ 3
- 0
react/features/recent-list/index.js 파일 보기

@@ -0,0 +1,3 @@
1
+export * from './components';
2
+
3
+import './middleware';

+ 106
- 0
react/features/recent-list/middleware.js 파일 보기

@@ -0,0 +1,106 @@
1
+/* @flow */
2
+
3
+import { LIST_SIZE } from './constants';
4
+import { getRecentUrls, updaterecentUrls } from './functions';
5
+
6
+import { CONFERENCE_WILL_LEAVE, SET_ROOM } from '../base/conference';
7
+import { MiddlewareRegistry } from '../base/redux';
8
+
9
+/**
10
+ * Middleware that captures joined rooms so then it can be saved to
11
+ * {@code localStorage}
12
+ *
13
+ * @param {Store} store - Redux store.
14
+ * @returns {Function}
15
+ */
16
+MiddlewareRegistry.register(store => next => action => {
17
+    switch (action.type) {
18
+    case CONFERENCE_WILL_LEAVE:
19
+        return _updateConferenceDuration(store, next, action);
20
+
21
+    case SET_ROOM:
22
+        return _storeJoinedRoom(store, next, action);
23
+    }
24
+
25
+    return next(action);
26
+});
27
+
28
+/**
29
+* Stores the recently joined room in {@code localStorage}.
30
+*
31
+* @param {Store} store - The redux store in which the specified action is being
32
+* dispatched.
33
+* @param {Dispatch} next - The redux dispatch function to dispatch the
34
+* specified action to the specified store.
35
+* @param {Action} action - The redux action CONFERENCE_JOINED which is being
36
+* dispatched in the specified store.
37
+* @returns {Object} The new state that is the result of the reduction of the
38
+* specified action.
39
+*/
40
+function _storeJoinedRoom(store, next, action) {
41
+    const result = next(action);
42
+    const { room } = action;
43
+
44
+    if (room) {
45
+        const { locationURL } = store.getState()['features/base/connection'];
46
+        const conferenceLink = locationURL.href;
47
+
48
+        // if the current conference is already in the list,
49
+        // we remove it to add it
50
+        // to the top at the end
51
+        const recentUrls = getRecentUrls().filter(
52
+            entry => entry.conference !== conferenceLink
53
+        );
54
+
55
+        // please note, this is a reverse sorted array
56
+        // (newer elements at the end)
57
+        recentUrls.push({
58
+            conference: conferenceLink,
59
+            date: Date.now(),
60
+            conferenceDuration: 0
61
+        });
62
+
63
+        // maximising the size
64
+        recentUrls.splice(0, recentUrls.length - LIST_SIZE);
65
+
66
+        updaterecentUrls(recentUrls);
67
+    }
68
+
69
+    return result;
70
+}
71
+
72
+/**
73
+* Updates the conference length when left.
74
+*
75
+* @private
76
+* @param {Store} store - The redux store in which the specified action is being
77
+* dispatched.
78
+* @param {Dispatch} next - The redux dispatch function to dispatch the
79
+* specified action to the specified store.
80
+* @param {Action} action - The redux action CONFERENCE_JOINED which is being
81
+* dispatched in the specified store.
82
+* @returns {Object} The new state that is the result of the reduction of the
83
+* specified action.
84
+*/
85
+function _updateConferenceDuration(store, next, action) {
86
+    const result = next(action);
87
+    const { locationURL } = store.getState()['features/base/connection'];
88
+
89
+    if (locationURL && locationURL.href) {
90
+        const recentUrls = getRecentUrls();
91
+
92
+        if (recentUrls.length > 0
93
+            && recentUrls[recentUrls.length - 1].conference
94
+                === locationURL.href) {
95
+            // the last conference start was stored
96
+            // so we need to update the length
97
+
98
+            recentUrls[recentUrls.length - 1].conferenceDuration
99
+                = Date.now() - recentUrls[recentUrls.length - 1].date;
100
+
101
+            updaterecentUrls(recentUrls);
102
+        }
103
+    }
104
+
105
+    return result;
106
+}

+ 8
- 8
react/features/welcome/components/WelcomePage.native.js 파일 보기

@@ -2,15 +2,16 @@ import React from 'react';
2 2
 import { TextInput, TouchableHighlight, View } from 'react-native';
3 3
 import { connect } from 'react-redux';
4 4
 
5
+import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage';
6
+import LocalVideoTrackUnderlay from './LocalVideoTrackUnderlay';
7
+import styles, { PLACEHOLDER_TEXT_COLOR } from './styles';
8
+
5 9
 import { translate } from '../../base/i18n';
6 10
 import { MEDIA_TYPE } from '../../base/media';
7 11
 import { Link, LoadingIndicator, Text } from '../../base/react';
8 12
 import { ColorPalette } from '../../base/styles';
9 13
 import { createDesiredLocalTracks } from '../../base/tracks';
10
-
11
-import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage';
12
-import LocalVideoTrackUnderlay from './LocalVideoTrackUnderlay';
13
-import styles from './styles';
14
+import { RecentList } from '../../recent-list';
14 15
 
15 16
 /**
16 17
  * The URL at which the privacy policy is available to the user.
@@ -67,9 +68,6 @@ class WelcomePage extends AbstractWelcomePage {
67 68
         return (
68 69
             <LocalVideoTrackUnderlay style = { styles.welcomePage }>
69 70
                 <View style = { styles.roomContainer }>
70
-                    <Text style = { styles.title }>
71
-                        { t('welcomepage.roomname') }
72
-                    </Text>
73 71
                     <TextInput
74 72
                         accessibilityLabel = { 'Input room name.' }
75 73
                         autoCapitalize = 'none'
@@ -77,13 +75,15 @@ class WelcomePage extends AbstractWelcomePage {
77 75
                         autoCorrect = { false }
78 76
                         autoFocus = { false }
79 77
                         onChangeText = { this._onRoomChange }
80
-                        placeholder = { t('welcomepage.roomnamePlaceHolder') }
78
+                        placeholder = { t('welcomepage.roomname') }
79
+                        placeholderTextColor = { PLACEHOLDER_TEXT_COLOR }
81 80
                         style = { styles.textInput }
82 81
                         underlineColorAndroid = 'transparent'
83 82
                         value = { this.state.room } />
84 83
                     {
85 84
                         this._renderJoinButton()
86 85
                     }
86
+                    <RecentList />
87 87
                 </View>
88 88
                 {
89 89
                     this._renderLegalese()

+ 4
- 1
react/features/welcome/components/styles.js 파일 보기

@@ -10,6 +10,8 @@ import {
10 10
  */
11 11
 const TEXT_COLOR = ColorPalette.white;
12 12
 
13
+export const PLACEHOLDER_TEXT_COLOR = 'rgba(255, 255, 255, 0.3)';
14
+
13 15
 /**
14 16
  * The styles of the React {@code Components} of the feature welcome including
15 17
  * {@code WelcomePage} and {@code BlankPage}.
@@ -83,7 +85,8 @@ export default createStyleSheet({
83 85
         flex: 1,
84 86
         flexDirection: 'column',
85 87
         justifyContent: 'center',
86
-        margin: 3 * BoxModel.margin
88
+        margin: 3 * BoxModel.margin,
89
+        marginBottom: BoxModel.margin
87 90
     },
88 91
 
89 92
     /**

Loading…
취소
저장