[RN] Add recent-list feature

This commit is contained in:
Zoltan Bettenbuk 2017-12-13 11:35:42 +01:00 committed by Lyubo Marinov
parent 3aedce11f2
commit 45c405de0e
21 changed files with 1041 additions and 121 deletions

View File

@ -25,6 +25,15 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-public:before {
content: "\e80b";
}
.icon-event_note:before {
content: "\e616";
}
.icon-timer:before {
content: "\e425";
}
.icon-thumb-menu:before {
content: "\e5d4";
}

View File

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

Binary file not shown.

View File

@ -11,11 +11,14 @@
<glyph unicode="&#xe145;" glyph-name="add" d="M810 470h-256v-256h-84v256h-256v84h256v256h84v-256h256v-84z" />
<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" />
<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" />
<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" />
<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" />
<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" />
<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" />
<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" />
<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" />
<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" />
<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" />
<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" />
<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" />
<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" />

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Binary file not shown.

View File

@ -1,6 +1,87 @@
{
"IcoMoonType": "selection",
"icons": [
{
"icon": {
"paths": [
"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"
],
"attrs": [],
"isMulticolor": false,
"isMulticolor2": false,
"tags": [
"public"
],
"defaultCode": 59403,
"grid": 24
},
"attrs": [],
"properties": {
"ligatures": "public",
"id": 605,
"order": 920,
"prevSize": 24,
"code": 59403,
"name": "public"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 605
},
{
"icon": {
"paths": [
"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"
],
"attrs": [],
"isMulticolor": false,
"isMulticolor2": false,
"tags": [
"event_note"
],
"defaultCode": 58902,
"grid": 24
},
"attrs": [],
"properties": {
"ligatures": "event_note",
"id": 252,
"order": 919,
"prevSize": 24,
"code": 58902,
"name": "event_note"
},
"setIdx": 1,
"setId": 1,
"iconIdx": 0
},
{
"icon": {
"paths": [
"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"
],
"attrs": [],
"isMulticolor": false,
"isMulticolor2": false,
"tags": [
"timer"
],
"defaultCode": 58405,
"grid": 24
},
"attrs": [],
"properties": {
"ligatures": "timer",
"id": 760,
"order": 916,
"prevSize": 24,
"code": 58405,
"name": "timer"
},
"setIdx": 1,
"setId": 1,
"iconIdx": 1
},
{
"icon": {
"paths": [
@ -24,9 +105,9 @@
"code": 57770,
"name": "bluetooth"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 79
"setIdx": 1,
"setId": 1,
"iconIdx": 2
},
{
"icon": {
@ -51,9 +132,9 @@
"code": 58128,
"name": "headset"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 376
"setIdx": 1,
"setId": 1,
"iconIdx": 3
},
{
"icon": {
@ -78,9 +159,9 @@
"code": 58909,
"name": "phone-talk"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 566
"setIdx": 1,
"setId": 1,
"iconIdx": 4
},
{
"icon": {
@ -107,7 +188,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 40
"iconIdx": 5
},
{
"icon": {
@ -136,7 +217,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 41
"iconIdx": 6
},
{
"icon": {
@ -163,7 +244,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 42
"iconIdx": 7
},
{
"icon": {
@ -190,7 +271,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 43
"iconIdx": 8
},
{
"icon": {
@ -219,7 +300,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 0
"iconIdx": 9
},
{
"icon": {
@ -248,7 +329,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 1
"iconIdx": 10
},
{
"icon": {
@ -277,7 +358,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 2
"iconIdx": 11
},
{
"icon": {
@ -306,7 +387,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 3
"iconIdx": 12
},
{
"icon": {
@ -335,7 +416,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 4
"iconIdx": 13
},
{
"icon": {
@ -361,7 +442,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 5
"iconIdx": 14
},
{
"icon": {
@ -387,7 +468,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 6
"iconIdx": 15
},
{
"icon": {
@ -413,7 +494,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 7
"iconIdx": 16
},
{
"icon": {
@ -439,7 +520,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 8
"iconIdx": 17
},
{
"icon": {
@ -465,7 +546,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 9
"iconIdx": 18
},
{
"icon": {
@ -491,7 +572,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 10
"iconIdx": 19
},
{
"icon": {
@ -517,7 +598,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 11
"iconIdx": 20
},
{
"icon": {
@ -543,7 +624,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 12
"iconIdx": 21
},
{
"icon": {
@ -569,7 +650,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 13
"iconIdx": 22
},
{
"icon": {
@ -595,7 +676,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 14
"iconIdx": 23
},
{
"icon": {
@ -621,7 +702,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 15
"iconIdx": 24
},
{
"icon": {
@ -647,7 +728,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 16
"iconIdx": 25
},
{
"icon": {
@ -673,7 +754,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 17
"iconIdx": 26
},
{
"icon": {
@ -699,7 +780,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 18
"iconIdx": 27
},
{
"icon": {
@ -725,7 +806,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 19
"iconIdx": 28
},
{
"icon": {
@ -751,7 +832,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 20
"iconIdx": 29
},
{
"icon": {
@ -777,7 +858,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 21
"iconIdx": 30
},
{
"icon": {
@ -803,7 +884,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 22
"iconIdx": 31
},
{
"icon": {
@ -829,7 +910,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 23
"iconIdx": 32
},
{
"icon": {
@ -855,7 +936,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 24
"iconIdx": 33
},
{
"icon": {
@ -881,7 +962,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 25
"iconIdx": 34
},
{
"icon": {
@ -907,7 +988,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 26
"iconIdx": 35
},
{
"icon": {
@ -933,7 +1014,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 27
"iconIdx": 36
},
{
"icon": {
@ -959,7 +1040,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 28
"iconIdx": 37
},
{
"icon": {
@ -985,7 +1066,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 29
"iconIdx": 38
},
{
"icon": {
@ -1011,7 +1092,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 30
"iconIdx": 39
},
{
"icon": {
@ -1037,7 +1118,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 31
"iconIdx": 40
},
{
"icon": {
@ -1063,7 +1144,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 32
"iconIdx": 41
},
{
"icon": {
@ -1089,7 +1170,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 33
"iconIdx": 42
},
{
"icon": {
@ -1118,7 +1199,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 34
"iconIdx": 43
},
{
"icon": {
@ -1148,7 +1229,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 35
"iconIdx": 44
},
{
"icon": {
@ -1178,7 +1259,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 36
"iconIdx": 45
},
{
"icon": {
@ -1204,7 +1285,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 37
"iconIdx": 46
},
{
"icon": {
@ -1230,7 +1311,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 38
"iconIdx": 47
},
{
"icon": {
@ -1256,7 +1337,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 39
"iconIdx": 48
}
],
"height": 1024,

5
package-lock.json generated
View File

@ -7064,6 +7064,11 @@
"minimist": "0.0.8"
}
},
"moment": {
"version": "2.19.4",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.19.4.tgz",
"integrity": "sha512-1xFTAknSLfc47DIxHDUbnJWC+UwgWxATmymaxIPQpmMh7LBm7ZbwVEsuushqwL2GYZU0jie4xO+TK44hJPjNSQ=="
},
"morgan": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz",

View File

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

187
react/features/base/font-icons/jitsi.json Normal file → Executable file
View File

@ -1,6 +1,87 @@
{
"IcoMoonType": "selection",
"icons": [
{
"icon": {
"paths": [
"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"
],
"attrs": [],
"isMulticolor": false,
"isMulticolor2": false,
"tags": [
"public"
],
"defaultCode": 59403,
"grid": 24
},
"attrs": [],
"properties": {
"ligatures": "public",
"id": 605,
"order": 920,
"prevSize": 24,
"code": 59403,
"name": "public"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 605
},
{
"icon": {
"paths": [
"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"
],
"attrs": [],
"isMulticolor": false,
"isMulticolor2": false,
"tags": [
"event_note"
],
"defaultCode": 58902,
"grid": 24
},
"attrs": [],
"properties": {
"ligatures": "event_note",
"id": 252,
"order": 919,
"prevSize": 24,
"code": 58902,
"name": "event_note"
},
"setIdx": 1,
"setId": 1,
"iconIdx": 0
},
{
"icon": {
"paths": [
"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"
],
"attrs": [],
"isMulticolor": false,
"isMulticolor2": false,
"tags": [
"timer"
],
"defaultCode": 58405,
"grid": 24
},
"attrs": [],
"properties": {
"ligatures": "timer",
"id": 760,
"order": 916,
"prevSize": 24,
"code": 58405,
"name": "timer"
},
"setIdx": 1,
"setId": 1,
"iconIdx": 1
},
{
"icon": {
"paths": [
@ -24,9 +105,9 @@
"code": 57770,
"name": "bluetooth"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 79
"setIdx": 1,
"setId": 1,
"iconIdx": 2
},
{
"icon": {
@ -51,9 +132,9 @@
"code": 58128,
"name": "headset"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 376
"setIdx": 1,
"setId": 1,
"iconIdx": 3
},
{
"icon": {
@ -78,9 +159,9 @@
"code": 58909,
"name": "phone-talk"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 566
"setIdx": 1,
"setId": 1,
"iconIdx": 4
},
{
"icon": {
@ -107,7 +188,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 40
"iconIdx": 5
},
{
"icon": {
@ -136,7 +217,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 41
"iconIdx": 6
},
{
"icon": {
@ -163,7 +244,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 42
"iconIdx": 7
},
{
"icon": {
@ -190,7 +271,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 43
"iconIdx": 8
},
{
"icon": {
@ -219,7 +300,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 0
"iconIdx": 9
},
{
"icon": {
@ -248,7 +329,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 1
"iconIdx": 10
},
{
"icon": {
@ -277,7 +358,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 2
"iconIdx": 11
},
{
"icon": {
@ -306,7 +387,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 3
"iconIdx": 12
},
{
"icon": {
@ -335,7 +416,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 4
"iconIdx": 13
},
{
"icon": {
@ -361,7 +442,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 5
"iconIdx": 14
},
{
"icon": {
@ -387,7 +468,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 6
"iconIdx": 15
},
{
"icon": {
@ -413,7 +494,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 7
"iconIdx": 16
},
{
"icon": {
@ -439,7 +520,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 8
"iconIdx": 17
},
{
"icon": {
@ -465,7 +546,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 9
"iconIdx": 18
},
{
"icon": {
@ -491,7 +572,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 10
"iconIdx": 19
},
{
"icon": {
@ -517,7 +598,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 11
"iconIdx": 20
},
{
"icon": {
@ -543,7 +624,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 12
"iconIdx": 21
},
{
"icon": {
@ -569,7 +650,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 13
"iconIdx": 22
},
{
"icon": {
@ -595,7 +676,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 14
"iconIdx": 23
},
{
"icon": {
@ -621,7 +702,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 15
"iconIdx": 24
},
{
"icon": {
@ -647,7 +728,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 16
"iconIdx": 25
},
{
"icon": {
@ -673,7 +754,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 17
"iconIdx": 26
},
{
"icon": {
@ -699,7 +780,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 18
"iconIdx": 27
},
{
"icon": {
@ -725,7 +806,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 19
"iconIdx": 28
},
{
"icon": {
@ -751,7 +832,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 20
"iconIdx": 29
},
{
"icon": {
@ -777,7 +858,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 21
"iconIdx": 30
},
{
"icon": {
@ -803,7 +884,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 22
"iconIdx": 31
},
{
"icon": {
@ -829,7 +910,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 23
"iconIdx": 32
},
{
"icon": {
@ -855,7 +936,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 24
"iconIdx": 33
},
{
"icon": {
@ -881,7 +962,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 25
"iconIdx": 34
},
{
"icon": {
@ -907,7 +988,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 26
"iconIdx": 35
},
{
"icon": {
@ -933,7 +1014,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 27
"iconIdx": 36
},
{
"icon": {
@ -959,7 +1040,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 28
"iconIdx": 37
},
{
"icon": {
@ -985,7 +1066,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 29
"iconIdx": 38
},
{
"icon": {
@ -1011,7 +1092,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 30
"iconIdx": 39
},
{
"icon": {
@ -1037,7 +1118,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 31
"iconIdx": 40
},
{
"icon": {
@ -1063,7 +1144,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 32
"iconIdx": 41
},
{
"icon": {
@ -1089,7 +1170,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 33
"iconIdx": 42
},
{
"icon": {
@ -1118,7 +1199,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 34
"iconIdx": 43
},
{
"icon": {
@ -1148,7 +1229,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 35
"iconIdx": 44
},
{
"icon": {
@ -1178,7 +1259,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 36
"iconIdx": 45
},
{
"icon": {
@ -1204,7 +1285,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 37
"iconIdx": 46
},
{
"icon": {
@ -1230,7 +1311,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 38
"iconIdx": 47
},
{
"icon": {
@ -1256,7 +1337,7 @@
},
"setIdx": 1,
"setId": 1,
"iconIdx": 39
"iconIdx": 48
}
],
"height": 1024,

View File

@ -88,6 +88,26 @@ export default class Storage {
return this.hasOwnProperty(key) ? this[key] : null;
}
/**
* Returns the value associated with a specific key in this storage in an
* async manner. This method is required for those cases where we need
* the stored data but we're not sure yet whether the {@code Storage}
* is already initialised or not - e.g. on app start.
*
* @private
* @param {string} key - The name of the key to retrieve the value of.
* @returns {Promise}
*/
_getItemAsync(key) {
return new Promise(resolve => {
AsyncStorage.getItem(
`${String(this._keyPrefix)}${key}`,
(error, result) => {
resolve(result ? result : null);
});
});
}
/**
* Returns the name of the nth key in this storage.
*

View File

@ -0,0 +1,101 @@
// @flow
import { Component } from 'react';
import { ListView } from 'react-native';
import { getRecentRooms } from '../functions';
import { appNavigate } from '../../app';
/**
* The type of the React {@code Component} state of {@link AbstractRecentList}.
*/
type State = {
/**
* The {@code ListView.DataSource} to be used for the {@code ListView}.
* Its content comes from the native implementation of
* {@code window.localStorage}.
*/
dataSource: Object
}
/**
* The type of the React {@code Component} props of {@link AbstractRecentList}
*/
type Props = {
/**
* Redux store dispatch function.
*/
dispatch: Dispatch<*>,
}
/**
* Implements a React {@link Component} which represents the list of
* conferences recently joined, similar to how a list of last dialed
* numbers list would do on a mobile
*
* @extends Component
*/
export default class AbstractRecentList extends Component<Props, State> {
/**
* The datasource that backs the {@code ListView}
*/
listDataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) =>
r1.conference !== r2.conference
&& r1.dateTimeStamp !== r2.dateTimeStamp
});;
/**
* Initializes a new {@code AbstractRecentList} instance.
*/
constructor() {
super();
this.state = {
dataSource: this.listDataSource.cloneWithRows([])
};
}
/**
* Implements React's {@link Component#componentWillMount()}. Invoked
* immediately before mounting occurs.
*
* @inheritdoc
*/
componentWillMount() {
// this must be done asynchronously because we don't have the storage
// initiated on app startup immediately.
getRecentRooms().then(rooms => {
this.setState({
dataSource: this.listDataSource.cloneWithRows(rooms)
});
});
}
/**
* Creates a bound onPress action for the list item.
*
* @param {string} room - The selected room.
* @returns {Function}
*/
_onSelect(room) {
return this._onJoin.bind(this, room);
}
/**
* Joins the selected room.
*
* @param {string} room - The selected room.
* @returns {void}
*/
_onJoin(room) {
if (room) {
this.props.dispatch(appNavigate(room));
}
}
}

View File

@ -0,0 +1,208 @@
import React from 'react';
import { ListView, Text, TouchableHighlight, View } from 'react-native';
import { connect } from 'react-redux';
import AbstractRecentList from './AbstractRecentList';
import styles, { UNDERLAY_COLOR } from './styles';
import { Icon } from '../../base/font-icons';
/**
* The native container rendering the list of the recently joined rooms.
*
* @extends AbstractRecentList
*/
class RecentList extends AbstractRecentList {
/**
* Initializes a new {@code RecentList} instance.
*
*/
constructor() {
super();
this._getAvatarStyle = this._getAvatarStyle.bind(this);
this._onSelect = this._onSelect.bind(this);
this._renderConfDuration = this._renderConfDuration.bind(this);
this._renderRow = this._renderRow.bind(this);
this._renderServerInfo = this._renderServerInfo.bind(this);
}
/**
* Implements React's {@link Component#render()}. Renders a list of
* recently joined rooms.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
if (!this.state.dataSource.getRowCount()) {
return null;
}
return (
<View style = { styles.container }>
<ListView
dataSource = { this.state.dataSource }
enableEmptySections = { true }
renderRow = { this._renderRow } />
</View>
);
}
/**
* Renders the list of recently joined rooms.
*
* @private
* @param {Object} data - The row data to be rendered.
* @returns {ReactElement}
*/
_renderRow(data) {
return (
<TouchableHighlight
onPress = { this._onSelect(data.conference) }
underlayColor = { UNDERLAY_COLOR } >
<View style = { styles.row } >
<View style = { styles.avatarContainer } >
<View style = { this._getAvatarStyle(data) } >
<Text style = { styles.avatarContent }>
{ data.initials }
</Text>
</View>
</View>
<View style = { styles.detailsContainer } >
<Text
numberOfLines = { 1 }
style = { styles.roomName }>
{ data.room }
</Text>
<View style = { styles.infoWithIcon } >
<Icon
name = 'event_note'
style = { styles.inlineIcon } />
<Text style = { styles.date }>
{ data.dateString }
</Text>
</View>
{
this._renderConfDuration(data)
}
{
this._renderServerInfo(data)
}
</View>
</View>
</TouchableHighlight>
);
}
/**
* Assembles the style array of the avatar based on if the conference
* was a home or remote server conference (based on current app setting).
*
* @private
* @param {Object} recentListEntry - The recent list entry being rendered.
* @returns {Array<Object>}
*/
_getAvatarStyle(recentListEntry) {
const avatarStyles = [ styles.avatar ];
if (recentListEntry.baseURL !== this.props._homeServer) {
avatarStyles.push(
this._getColorForServerName(recentListEntry.serverName)
);
}
return avatarStyles;
}
/**
* Returns a style (color) based on the server name, so then the
* same server will always be rendered with the same avatar color.
*
* @private
* @param {string} serverName - The recent list entry being rendered.
* @returns {Object}
*/
_getColorForServerName(serverName) {
let nameHash = 0;
for (let i = 0; i < serverName.length; i++) {
nameHash += serverName.codePointAt(i);
}
return styles[`avatarRemoteServer${(nameHash % 5) + 1}`];
}
/**
* Renders the server info component based on if the entry was
* on a different server or not.
*
* @private
* @param {Object} recentListEntry - The recent list entry being rendered.
* @returns {ReactElement}
*/
_renderServerInfo(recentListEntry) {
if (recentListEntry.baseURL !== this.props._homeServer) {
return (
<View style = { styles.infoWithIcon } >
<Icon
name = 'public'
style = { styles.inlineIcon } />
<Text style = { styles.serverName }>
{ recentListEntry.serverName }
</Text>
</View>
);
}
return null;
}
/**
* Renders the conference duration if available.
*
* @private
* @param {Object} recentListEntry - The recent list entry being rendered.
* @returns {ReactElement}
*/
_renderConfDuration(recentListEntry) {
if (recentListEntry.conferenceDurationString) {
return (
<View style = { styles.infoWithIcon } >
<Icon
name = 'timer'
style = { styles.inlineIcon } />
<Text style = { styles.confLength }>
{ recentListEntry.conferenceDurationString }
</Text>
</View>
);
}
return null;
}
}
/**
* Maps (parts of) the Redux state to the associated RecentList's props.
*
* @param {Object} state - The Redux state.
* @private
* @returns {{
* _homeServer: string
* }}
*/
function _mapStateToProps(state) {
return {
/**
* The default server name based on which we determine
* the render method.
*
* @private
* @type {string}
*/
_homeServer: state['features/app'].app._getDefaultURL()
};
}
export default connect(_mapStateToProps)(RecentList);

View File

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

View File

@ -0,0 +1,154 @@
import {
createStyleSheet,
BoxModel
} from '../../base/styles';
const AVATAR_OPACITY = 0.4;
const AVATAR_SIZE = 65;
const OVERLAY_FONT_COLOR = 'rgba(255, 255, 255, 0.6)';
export const UNDERLAY_COLOR = 'rgba(255, 255, 255, 0.2)';
/**
* The styles of the React {@code Components} of the feature: recent list
* {@code RecentList}.
*/
export default createStyleSheet({
/**
* The style of the actual avatar
*/
avatar: {
width: AVATAR_SIZE,
height: AVATAR_SIZE,
alignItems: 'center',
backgroundColor: `rgba(23, 160, 219, ${AVATAR_OPACITY})`,
justifyContent: 'center',
borderRadius: AVATAR_SIZE
},
/**
* The style of the avatar container that makes the avatar rounded.
*/
avatarContainer: {
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
paddingTop: 5
},
/**
* Simple {@code Text} content of the avatar (the actual initials)
*/
avatarContent: {
color: OVERLAY_FONT_COLOR,
fontSize: 32,
fontWeight: '100',
backgroundColor: 'rgba(0, 0, 0, 0)',
textAlign: 'center'
},
/**
* List of styles of the avatar of a remote meeting
* (not the default server). The number of colors are limited
* because they should match nicely.
*/
avatarRemoteServer1: {
backgroundColor: `rgba(232, 105, 156, ${AVATAR_OPACITY})`
},
avatarRemoteServer2: {
backgroundColor: `rgba(255, 198, 115, ${AVATAR_OPACITY})`
},
avatarRemoteServer3: {
backgroundColor: `rgba(128, 128, 255, ${AVATAR_OPACITY})`
},
avatarRemoteServer4: {
backgroundColor: `rgba(105, 232, 194, ${AVATAR_OPACITY})`
},
avatarRemoteServer5: {
backgroundColor: `rgba(234, 255, 128, ${AVATAR_OPACITY})`
},
/**
* Style of the conference length (if rendered)
*/
confLength: {
color: OVERLAY_FONT_COLOR,
fontWeight: 'normal'
},
/**
* This is the top level container style of the list
*/
container: {
flex: 1
},
/**
* Second line of the list (date).
* May be extended with server name later.
*/
date: {
color: OVERLAY_FONT_COLOR
},
/**
* The style of the details container (right side) of the list
*/
detailsContainer: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
marginLeft: 2 * BoxModel.margin,
alignItems: 'flex-start'
},
/**
* The container for an info line with an inline icon.
*/
infoWithIcon: {
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center'
},
/**
* Style of an inline icon in an info line.
*/
inlineIcon: {
color: OVERLAY_FONT_COLOR,
marginRight: 5
},
/**
* First line of the list (room name)
*/
roomName: {
fontSize: 18,
fontWeight: 'bold',
color: OVERLAY_FONT_COLOR
},
/**
* The style of one single row in the list
*/
row: {
padding: 8,
paddingBottom: 0,
flex: 1,
flexDirection: 'row',
alignItems: 'center'
},
/**
* Style of the server name component (if rendered)
*/
serverName: {
color: OVERLAY_FONT_COLOR,
fontWeight: 'normal'
}
});

View File

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

View File

@ -0,0 +1,132 @@
// @flow
import moment from 'moment';
import { RECENT_URL_STORAGE } from './constants';
import { i18next } from '../base/i18n';
import { parseURIString } from '../base/util';
/**
* Retreives the recent room list and generates all the data needed
* to be displayed.
*
* @returns {Promise} The {@code Promise} to be resolved when the list
* is available.
*/
export function getRecentRooms(): Promise<Array<Object>> {
return new Promise(resolve => {
window.localStorage._getItemAsync(RECENT_URL_STORAGE)
.then(recentUrls => {
if (recentUrls) {
const recentUrlsObj = JSON.parse(recentUrls);
const recentRoomDS = [];
for (const entry of recentUrlsObj) {
const location = parseURIString(entry.conference);
if (location && location.room && location.hostname) {
recentRoomDS.push({
baseURL:
`${location.protocol}//${location.host}`,
conference: entry.conference,
dateTimeStamp: entry.date,
conferenceDuration: entry.conferenceDuration,
dateString: _getDateString(
entry.date
),
conferenceDurationString: _getLengthString(
entry.conferenceDuration
),
initials: _getInitials(location.room),
room: location.room,
serverName: location.hostname
});
}
}
resolve(recentRoomDS.reverse());
} else {
resolve([]);
}
});
});
}
/**
* Retreives the recent URL list as a list of objects.
*
* @returns {Array} The list of already stored recent URLs.
*/
export function getRecentUrls() {
let recentUrls = window.localStorage.getItem(RECENT_URL_STORAGE);
if (recentUrls) {
recentUrls = JSON.parse(recentUrls);
} else {
recentUrls = [];
}
return recentUrls;
}
/**
* Updates the recent URL list.
*
* @param {Array} recentUrls - The new URL list.
* @returns {void}
*/
export function updaterecentUrls(recentUrls: Array<Object>) {
window.localStorage.setItem(
RECENT_URL_STORAGE,
JSON.stringify(recentUrls)
);
}
/**
* Returns a well formatted date string to be displayed in the list.
*
* @private
* @param {number} dateTimeStamp - The UTC timestamp to be converted to String.
* @returns {string}
*/
function _getDateString(dateTimeStamp: number) {
const date = new Date(dateTimeStamp);
if (date.toDateString() === new Date().toDateString()) {
// the date is today, we use fromNow format
return moment(date)
.locale(i18next.language)
.fromNow();
}
return moment(date)
.locale(i18next.language)
.format('lll');
}
/**
* Returns a well formatted duration string to be displayed
* as the conference length.
*
* @private
* @param {number} duration - The duration in MS.
* @returns {string}
*/
function _getLengthString(duration: number) {
return moment.duration(duration)
.locale(i18next.language)
.humanize();
}
/**
* Returns the initials supposed to be used based on the room name.
*
* @private
* @param {string} room - The room name.
* @returns {string}
*/
function _getInitials(room: string) {
return room && room.charAt(0) ? room.charAt(0).toUpperCase() : '?';
}

View File

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

View File

@ -0,0 +1,106 @@
/* @flow */
import { LIST_SIZE } from './constants';
import { getRecentUrls, updaterecentUrls } from './functions';
import { CONFERENCE_WILL_LEAVE, SET_ROOM } from '../base/conference';
import { MiddlewareRegistry } from '../base/redux';
/**
* Middleware that captures joined rooms so then it can be saved to
* {@code localStorage}
*
* @param {Store} store - Redux store.
* @returns {Function}
*/
MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
case CONFERENCE_WILL_LEAVE:
return _updateConferenceDuration(store, next, action);
case SET_ROOM:
return _storeJoinedRoom(store, next, action);
}
return next(action);
});
/**
* Stores the recently joined room in {@code localStorage}.
*
* @param {Store} store - The redux store in which the specified action is being
* dispatched.
* @param {Dispatch} next - The redux dispatch function to dispatch the
* specified action to the specified store.
* @param {Action} action - The redux action CONFERENCE_JOINED which is being
* dispatched in the specified store.
* @returns {Object} The new state that is the result of the reduction of the
* specified action.
*/
function _storeJoinedRoom(store, next, action) {
const result = next(action);
const { room } = action;
if (room) {
const { locationURL } = store.getState()['features/base/connection'];
const conferenceLink = locationURL.href;
// if the current conference is already in the list,
// we remove it to add it
// to the top at the end
const recentUrls = getRecentUrls().filter(
entry => entry.conference !== conferenceLink
);
// please note, this is a reverse sorted array
// (newer elements at the end)
recentUrls.push({
conference: conferenceLink,
date: Date.now(),
conferenceDuration: 0
});
// maximising the size
recentUrls.splice(0, recentUrls.length - LIST_SIZE);
updaterecentUrls(recentUrls);
}
return result;
}
/**
* Updates the conference length when left.
*
* @private
* @param {Store} store - The redux store in which the specified action is being
* dispatched.
* @param {Dispatch} next - The redux dispatch function to dispatch the
* specified action to the specified store.
* @param {Action} action - The redux action CONFERENCE_JOINED which is being
* dispatched in the specified store.
* @returns {Object} The new state that is the result of the reduction of the
* specified action.
*/
function _updateConferenceDuration(store, next, action) {
const result = next(action);
const { locationURL } = store.getState()['features/base/connection'];
if (locationURL && locationURL.href) {
const recentUrls = getRecentUrls();
if (recentUrls.length > 0
&& recentUrls[recentUrls.length - 1].conference
=== locationURL.href) {
// the last conference start was stored
// so we need to update the length
recentUrls[recentUrls.length - 1].conferenceDuration
= Date.now() - recentUrls[recentUrls.length - 1].date;
updaterecentUrls(recentUrls);
}
}
return result;
}

View File

@ -2,15 +2,16 @@ import React from 'react';
import { TextInput, TouchableHighlight, View } from 'react-native';
import { connect } from 'react-redux';
import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage';
import LocalVideoTrackUnderlay from './LocalVideoTrackUnderlay';
import styles, { PLACEHOLDER_TEXT_COLOR } from './styles';
import { translate } from '../../base/i18n';
import { MEDIA_TYPE } from '../../base/media';
import { Link, LoadingIndicator, Text } from '../../base/react';
import { ColorPalette } from '../../base/styles';
import { createDesiredLocalTracks } from '../../base/tracks';
import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage';
import LocalVideoTrackUnderlay from './LocalVideoTrackUnderlay';
import styles from './styles';
import { RecentList } from '../../recent-list';
/**
* The URL at which the privacy policy is available to the user.
@ -67,9 +68,6 @@ class WelcomePage extends AbstractWelcomePage {
return (
<LocalVideoTrackUnderlay style = { styles.welcomePage }>
<View style = { styles.roomContainer }>
<Text style = { styles.title }>
{ t('welcomepage.roomname') }
</Text>
<TextInput
accessibilityLabel = { 'Input room name.' }
autoCapitalize = 'none'
@ -77,13 +75,15 @@ class WelcomePage extends AbstractWelcomePage {
autoCorrect = { false }
autoFocus = { false }
onChangeText = { this._onRoomChange }
placeholder = { t('welcomepage.roomnamePlaceHolder') }
placeholder = { t('welcomepage.roomname') }
placeholderTextColor = { PLACEHOLDER_TEXT_COLOR }
style = { styles.textInput }
underlineColorAndroid = 'transparent'
value = { this.state.room } />
{
this._renderJoinButton()
}
<RecentList />
</View>
{
this._renderLegalese()

View File

@ -10,6 +10,8 @@ import {
*/
const TEXT_COLOR = ColorPalette.white;
export const PLACEHOLDER_TEXT_COLOR = 'rgba(255, 255, 255, 0.3)';
/**
* The styles of the React {@code Components} of the feature welcome including
* {@code WelcomePage} and {@code BlankPage}.
@ -83,7 +85,8 @@ export default createStyleSheet({
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
margin: 3 * BoxModel.margin
margin: 3 * BoxModel.margin,
marginBottom: BoxModel.margin
},
/**