Przeglądaj źródła

Facelift Welcome screen

j8
zbettenbuk 7 lat temu
rodzic
commit
04690dfc8f

+ 3
- 0
css/_font.scss Wyświetl plik

30
 .icon-event_note:before {
30
 .icon-event_note:before {
31
     content: "\e616";
31
     content: "\e616";
32
 }
32
 }
33
+.icon-menu:before {
34
+  content: "\e5d2";
35
+}
33
 .icon-navigate_before:before {
36
 .icon-navigate_before:before {
34
   content: "\e408";
37
   content: "\e408";
35
 }
38
 }

BIN
fonts/jitsi.eot Wyświetl plik


+ 1
- 0
fonts/jitsi.svg Wyświetl plik

14
 <glyph unicode="&#xe408;" glyph-name="navigate_before" d="M658 708l-196-196 196-196-60-60-256 256 256 256z" />
14
 <glyph unicode="&#xe408;" glyph-name="navigate_before" d="M658 708l-196-196 196-196-60-60-256 256 256 256z" />
15
 <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" />
15
 <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" />
16
 <glyph unicode="&#xe5c4;" glyph-name="arrow_back" d="M854 554v-84h-520l238-240-60-60-342 342 342 342 60-60-238-240h520z" />
16
 <glyph unicode="&#xe5c4;" glyph-name="arrow_back" d="M854 554v-84h-520l238-240-60-60-342 342 342 342 60-60-238-240h520z" />
17
+<glyph unicode="&#xe5d2;" glyph-name="menu" d="M128 768h768v-86h-768v86zM128 470v84h768v-84h-768zM128 256v86h768v-86h-768z" />
17
 <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" />
18
 <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" />
18
 <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" />
19
 <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" />
19
 <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" />
20
 <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" />

BIN
fonts/jitsi.ttf Wyświetl plik


BIN
fonts/jitsi.woff Wyświetl plik


+ 83
- 56
fonts/selection.json Wyświetl plik

1
 {
1
 {
2
   "IcoMoonType": "selection",
2
   "IcoMoonType": "selection",
3
   "icons": [
3
   "icons": [
4
+    {
5
+      "icon": {
6
+        "paths": [
7
+          "M128 256h768v86h-768v-86zM128 554v-84h768v84h-768zM128 768v-86h768v86h-768z"
8
+        ],
9
+        "attrs": [],
10
+        "isMulticolor": false,
11
+        "isMulticolor2": false,
12
+        "tags": [
13
+          "menu"
14
+        ],
15
+        "defaultCode": 58834,
16
+        "grid": 24
17
+      },
18
+      "attrs": [],
19
+      "properties": {
20
+        "ligatures": "menu",
21
+        "id": 489,
22
+        "order": 926,
23
+        "prevSize": 24,
24
+        "code": 58834,
25
+        "name": "menu"
26
+      },
27
+      "setIdx": 0,
28
+      "setId": 2,
29
+      "iconIdx": 489
30
+    },
4
     {
31
     {
5
       "icon": {
32
       "icon": {
6
         "paths": [
33
         "paths": [
24
         "code": 58820,
51
         "code": 58820,
25
         "name": "arrow_back"
52
         "name": "arrow_back"
26
       },
53
       },
27
-      "setIdx": 0,
28
-      "setId": 2,
29
-      "iconIdx": 45
54
+      "setIdx": 1,
55
+      "setId": 1,
56
+      "iconIdx": 0
30
     },
57
     },
31
     {
58
     {
32
       "icon": {
59
       "icon": {
51
         "code": 58376,
78
         "code": 58376,
52
         "name": "navigate_before"
79
         "name": "navigate_before"
53
       },
80
       },
54
-      "setIdx": 0,
55
-      "setId": 2,
56
-      "iconIdx": 152
81
+      "setIdx": 1,
82
+      "setId": 1,
83
+      "iconIdx": 1
57
     },
84
     },
58
     {
85
     {
59
       "icon": {
86
       "icon": {
80
       },
107
       },
81
       "setIdx": 1,
108
       "setIdx": 1,
82
       "setId": 1,
109
       "setId": 1,
83
-      "iconIdx": 0
110
+      "iconIdx": 2
84
     },
111
     },
85
     {
112
     {
86
       "icon": {
113
       "icon": {
107
       },
134
       },
108
       "setIdx": 1,
135
       "setIdx": 1,
109
       "setId": 1,
136
       "setId": 1,
110
-      "iconIdx": 1
137
+      "iconIdx": 3
111
     },
138
     },
112
     {
139
     {
113
       "icon": {
140
       "icon": {
134
       },
161
       },
135
       "setIdx": 1,
162
       "setIdx": 1,
136
       "setId": 1,
163
       "setId": 1,
137
-      "iconIdx": 2
164
+      "iconIdx": 4
138
     },
165
     },
139
     {
166
     {
140
       "icon": {
167
       "icon": {
161
       },
188
       },
162
       "setIdx": 1,
189
       "setIdx": 1,
163
       "setId": 1,
190
       "setId": 1,
164
-      "iconIdx": 3
191
+      "iconIdx": 5
165
     },
192
     },
166
     {
193
     {
167
       "icon": {
194
       "icon": {
188
       },
215
       },
189
       "setIdx": 1,
216
       "setIdx": 1,
190
       "setId": 1,
217
       "setId": 1,
191
-      "iconIdx": 4
218
+      "iconIdx": 6
192
     },
219
     },
193
     {
220
     {
194
       "icon": {
221
       "icon": {
215
       },
242
       },
216
       "setIdx": 1,
243
       "setIdx": 1,
217
       "setId": 1,
244
       "setId": 1,
218
-      "iconIdx": 5
245
+      "iconIdx": 7
219
     },
246
     },
220
     {
247
     {
221
       "icon": {
248
       "icon": {
242
       },
269
       },
243
       "setIdx": 1,
270
       "setIdx": 1,
244
       "setId": 1,
271
       "setId": 1,
245
-      "iconIdx": 6
272
+      "iconIdx": 8
246
     },
273
     },
247
     {
274
     {
248
       "icon": {
275
       "icon": {
271
       },
298
       },
272
       "setIdx": 1,
299
       "setIdx": 1,
273
       "setId": 1,
300
       "setId": 1,
274
-      "iconIdx": 7
301
+      "iconIdx": 9
275
     },
302
     },
276
     {
303
     {
277
       "icon": {
304
       "icon": {
298
       },
325
       },
299
       "setIdx": 1,
326
       "setIdx": 1,
300
       "setId": 1,
327
       "setId": 1,
301
-      "iconIdx": 8
328
+      "iconIdx": 10
302
     },
329
     },
303
     {
330
     {
304
       "icon": {
331
       "icon": {
325
       },
352
       },
326
       "setIdx": 1,
353
       "setIdx": 1,
327
       "setId": 1,
354
       "setId": 1,
328
-      "iconIdx": 9
355
+      "iconIdx": 11
329
     },
356
     },
330
     {
357
     {
331
       "icon": {
358
       "icon": {
354
       },
381
       },
355
       "setIdx": 1,
382
       "setIdx": 1,
356
       "setId": 1,
383
       "setId": 1,
357
-      "iconIdx": 10
384
+      "iconIdx": 12
358
     },
385
     },
359
     {
386
     {
360
       "icon": {
387
       "icon": {
383
       },
410
       },
384
       "setIdx": 1,
411
       "setIdx": 1,
385
       "setId": 1,
412
       "setId": 1,
386
-      "iconIdx": 11
413
+      "iconIdx": 13
387
     },
414
     },
388
     {
415
     {
389
       "icon": {
416
       "icon": {
412
       },
439
       },
413
       "setIdx": 1,
440
       "setIdx": 1,
414
       "setId": 1,
441
       "setId": 1,
415
-      "iconIdx": 12
442
+      "iconIdx": 14
416
     },
443
     },
417
     {
444
     {
418
       "icon": {
445
       "icon": {
441
       },
468
       },
442
       "setIdx": 1,
469
       "setIdx": 1,
443
       "setId": 1,
470
       "setId": 1,
444
-      "iconIdx": 13
471
+      "iconIdx": 15
445
     },
472
     },
446
     {
473
     {
447
       "icon": {
474
       "icon": {
470
       },
497
       },
471
       "setIdx": 1,
498
       "setIdx": 1,
472
       "setId": 1,
499
       "setId": 1,
473
-      "iconIdx": 14
500
+      "iconIdx": 16
474
     },
501
     },
475
     {
502
     {
476
       "icon": {
503
       "icon": {
496
       },
523
       },
497
       "setIdx": 1,
524
       "setIdx": 1,
498
       "setId": 1,
525
       "setId": 1,
499
-      "iconIdx": 15
526
+      "iconIdx": 17
500
     },
527
     },
501
     {
528
     {
502
       "icon": {
529
       "icon": {
522
       },
549
       },
523
       "setIdx": 1,
550
       "setIdx": 1,
524
       "setId": 1,
551
       "setId": 1,
525
-      "iconIdx": 16
552
+      "iconIdx": 18
526
     },
553
     },
527
     {
554
     {
528
       "icon": {
555
       "icon": {
548
       },
575
       },
549
       "setIdx": 1,
576
       "setIdx": 1,
550
       "setId": 1,
577
       "setId": 1,
551
-      "iconIdx": 17
578
+      "iconIdx": 19
552
     },
579
     },
553
     {
580
     {
554
       "icon": {
581
       "icon": {
574
       },
601
       },
575
       "setIdx": 1,
602
       "setIdx": 1,
576
       "setId": 1,
603
       "setId": 1,
577
-      "iconIdx": 18
604
+      "iconIdx": 20
578
     },
605
     },
579
     {
606
     {
580
       "icon": {
607
       "icon": {
600
       },
627
       },
601
       "setIdx": 1,
628
       "setIdx": 1,
602
       "setId": 1,
629
       "setId": 1,
603
-      "iconIdx": 19
630
+      "iconIdx": 21
604
     },
631
     },
605
     {
632
     {
606
       "icon": {
633
       "icon": {
626
       },
653
       },
627
       "setIdx": 1,
654
       "setIdx": 1,
628
       "setId": 1,
655
       "setId": 1,
629
-      "iconIdx": 20
656
+      "iconIdx": 22
630
     },
657
     },
631
     {
658
     {
632
       "icon": {
659
       "icon": {
652
       },
679
       },
653
       "setIdx": 1,
680
       "setIdx": 1,
654
       "setId": 1,
681
       "setId": 1,
655
-      "iconIdx": 21
682
+      "iconIdx": 23
656
     },
683
     },
657
     {
684
     {
658
       "icon": {
685
       "icon": {
678
       },
705
       },
679
       "setIdx": 1,
706
       "setIdx": 1,
680
       "setId": 1,
707
       "setId": 1,
681
-      "iconIdx": 22
708
+      "iconIdx": 24
682
     },
709
     },
683
     {
710
     {
684
       "icon": {
711
       "icon": {
704
       },
731
       },
705
       "setIdx": 1,
732
       "setIdx": 1,
706
       "setId": 1,
733
       "setId": 1,
707
-      "iconIdx": 23
734
+      "iconIdx": 25
708
     },
735
     },
709
     {
736
     {
710
       "icon": {
737
       "icon": {
730
       },
757
       },
731
       "setIdx": 1,
758
       "setIdx": 1,
732
       "setId": 1,
759
       "setId": 1,
733
-      "iconIdx": 24
760
+      "iconIdx": 26
734
     },
761
     },
735
     {
762
     {
736
       "icon": {
763
       "icon": {
756
       },
783
       },
757
       "setIdx": 1,
784
       "setIdx": 1,
758
       "setId": 1,
785
       "setId": 1,
759
-      "iconIdx": 25
786
+      "iconIdx": 27
760
     },
787
     },
761
     {
788
     {
762
       "icon": {
789
       "icon": {
782
       },
809
       },
783
       "setIdx": 1,
810
       "setIdx": 1,
784
       "setId": 1,
811
       "setId": 1,
785
-      "iconIdx": 26
812
+      "iconIdx": 28
786
     },
813
     },
787
     {
814
     {
788
       "icon": {
815
       "icon": {
808
       },
835
       },
809
       "setIdx": 1,
836
       "setIdx": 1,
810
       "setId": 1,
837
       "setId": 1,
811
-      "iconIdx": 27
838
+      "iconIdx": 29
812
     },
839
     },
813
     {
840
     {
814
       "icon": {
841
       "icon": {
834
       },
861
       },
835
       "setIdx": 1,
862
       "setIdx": 1,
836
       "setId": 1,
863
       "setId": 1,
837
-      "iconIdx": 28
864
+      "iconIdx": 30
838
     },
865
     },
839
     {
866
     {
840
       "icon": {
867
       "icon": {
860
       },
887
       },
861
       "setIdx": 1,
888
       "setIdx": 1,
862
       "setId": 1,
889
       "setId": 1,
863
-      "iconIdx": 29
890
+      "iconIdx": 31
864
     },
891
     },
865
     {
892
     {
866
       "icon": {
893
       "icon": {
886
       },
913
       },
887
       "setIdx": 1,
914
       "setIdx": 1,
888
       "setId": 1,
915
       "setId": 1,
889
-      "iconIdx": 30
916
+      "iconIdx": 32
890
     },
917
     },
891
     {
918
     {
892
       "icon": {
919
       "icon": {
912
       },
939
       },
913
       "setIdx": 1,
940
       "setIdx": 1,
914
       "setId": 1,
941
       "setId": 1,
915
-      "iconIdx": 31
942
+      "iconIdx": 33
916
     },
943
     },
917
     {
944
     {
918
       "icon": {
945
       "icon": {
938
       },
965
       },
939
       "setIdx": 1,
966
       "setIdx": 1,
940
       "setId": 1,
967
       "setId": 1,
941
-      "iconIdx": 32
968
+      "iconIdx": 34
942
     },
969
     },
943
     {
970
     {
944
       "icon": {
971
       "icon": {
964
       },
991
       },
965
       "setIdx": 1,
992
       "setIdx": 1,
966
       "setId": 1,
993
       "setId": 1,
967
-      "iconIdx": 33
994
+      "iconIdx": 35
968
     },
995
     },
969
     {
996
     {
970
       "icon": {
997
       "icon": {
990
       },
1017
       },
991
       "setIdx": 1,
1018
       "setIdx": 1,
992
       "setId": 1,
1019
       "setId": 1,
993
-      "iconIdx": 34
1020
+      "iconIdx": 36
994
     },
1021
     },
995
     {
1022
     {
996
       "icon": {
1023
       "icon": {
1016
       },
1043
       },
1017
       "setIdx": 1,
1044
       "setIdx": 1,
1018
       "setId": 1,
1045
       "setId": 1,
1019
-      "iconIdx": 35
1046
+      "iconIdx": 37
1020
     },
1047
     },
1021
     {
1048
     {
1022
       "icon": {
1049
       "icon": {
1042
       },
1069
       },
1043
       "setIdx": 1,
1070
       "setIdx": 1,
1044
       "setId": 1,
1071
       "setId": 1,
1045
-      "iconIdx": 36
1072
+      "iconIdx": 38
1046
     },
1073
     },
1047
     {
1074
     {
1048
       "icon": {
1075
       "icon": {
1068
       },
1095
       },
1069
       "setIdx": 1,
1096
       "setIdx": 1,
1070
       "setId": 1,
1097
       "setId": 1,
1071
-      "iconIdx": 37
1098
+      "iconIdx": 39
1072
     },
1099
     },
1073
     {
1100
     {
1074
       "icon": {
1101
       "icon": {
1094
       },
1121
       },
1095
       "setIdx": 1,
1122
       "setIdx": 1,
1096
       "setId": 1,
1123
       "setId": 1,
1097
-      "iconIdx": 38
1124
+      "iconIdx": 40
1098
     },
1125
     },
1099
     {
1126
     {
1100
       "icon": {
1127
       "icon": {
1120
       },
1147
       },
1121
       "setIdx": 1,
1148
       "setIdx": 1,
1122
       "setId": 1,
1149
       "setId": 1,
1123
-      "iconIdx": 39
1150
+      "iconIdx": 41
1124
     },
1151
     },
1125
     {
1152
     {
1126
       "icon": {
1153
       "icon": {
1146
       },
1173
       },
1147
       "setIdx": 1,
1174
       "setIdx": 1,
1148
       "setId": 1,
1175
       "setId": 1,
1149
-      "iconIdx": 40
1176
+      "iconIdx": 42
1150
     },
1177
     },
1151
     {
1178
     {
1152
       "icon": {
1179
       "icon": {
1172
       },
1199
       },
1173
       "setIdx": 1,
1200
       "setIdx": 1,
1174
       "setId": 1,
1201
       "setId": 1,
1175
-      "iconIdx": 41
1202
+      "iconIdx": 43
1176
     },
1203
     },
1177
     {
1204
     {
1178
       "icon": {
1205
       "icon": {
1198
       },
1225
       },
1199
       "setIdx": 1,
1226
       "setIdx": 1,
1200
       "setId": 1,
1227
       "setId": 1,
1201
-      "iconIdx": 42
1228
+      "iconIdx": 44
1202
     },
1229
     },
1203
     {
1230
     {
1204
       "icon": {
1231
       "icon": {
1224
       },
1251
       },
1225
       "setIdx": 1,
1252
       "setIdx": 1,
1226
       "setId": 1,
1253
       "setId": 1,
1227
-      "iconIdx": 43
1254
+      "iconIdx": 45
1228
     },
1255
     },
1229
     {
1256
     {
1230
       "icon": {
1257
       "icon": {
1253
       },
1280
       },
1254
       "setIdx": 1,
1281
       "setIdx": 1,
1255
       "setId": 1,
1282
       "setId": 1,
1256
-      "iconIdx": 44
1283
+      "iconIdx": 46
1257
     },
1284
     },
1258
     {
1285
     {
1259
       "icon": {
1286
       "icon": {
1283
       },
1310
       },
1284
       "setIdx": 1,
1311
       "setIdx": 1,
1285
       "setId": 1,
1312
       "setId": 1,
1286
-      "iconIdx": 45
1313
+      "iconIdx": 47
1287
     },
1314
     },
1288
     {
1315
     {
1289
       "icon": {
1316
       "icon": {
1313
       },
1340
       },
1314
       "setIdx": 1,
1341
       "setIdx": 1,
1315
       "setId": 1,
1342
       "setId": 1,
1316
-      "iconIdx": 46
1343
+      "iconIdx": 48
1317
     },
1344
     },
1318
     {
1345
     {
1319
       "icon": {
1346
       "icon": {
1339
       },
1366
       },
1340
       "setIdx": 1,
1367
       "setIdx": 1,
1341
       "setId": 1,
1368
       "setId": 1,
1342
-      "iconIdx": 47
1369
+      "iconIdx": 49
1343
     },
1370
     },
1344
     {
1371
     {
1345
       "icon": {
1372
       "icon": {
1365
       },
1392
       },
1366
       "setIdx": 1,
1393
       "setIdx": 1,
1367
       "setId": 1,
1394
       "setId": 1,
1368
-      "iconIdx": 48
1395
+      "iconIdx": 50
1369
     },
1396
     },
1370
     {
1397
     {
1371
       "icon": {
1398
       "icon": {
1391
       },
1418
       },
1392
       "setIdx": 1,
1419
       "setIdx": 1,
1393
       "setId": 1,
1420
       "setId": 1,
1394
-      "iconIdx": 49
1421
+      "iconIdx": 51
1395
     }
1422
     }
1396
   ],
1423
   ],
1397
   "height": 1024,
1424
   "height": 1024,

+ 3
- 0
lang/main.json Wyświetl plik

514
         "serverURL": "Server URL",
514
         "serverURL": "Server URL",
515
         "startWithAudioMuted": "Start with audio muted",
515
         "startWithAudioMuted": "Start with audio muted",
516
         "startWithVideoMuted": "Start with video muted"
516
         "startWithVideoMuted": "Start with video muted"
517
+    },
518
+    "sideBar": {
519
+        "settings": "Settings"
517
     }
520
     }
518
 }
521
 }

+ 4
- 4
react/features/analytics/AnalyticsEvents.js Wyświetl plik

85
 };
85
 };
86
 
86
 
87
 /**
87
 /**
88
- * Creates an event which indicates that the audio-only mode has been turned
89
- * off.
88
+ * Creates an event which indicates that the audio-only mode has been changed.
90
  *
89
  *
90
+ * @param {boolean} enabled - True if audio-only is enabled, false otherwise.
91
  * @returns {Object} The event in a format suitable for sending via
91
  * @returns {Object} The event in a format suitable for sending via
92
  * sendAnalytics.
92
  * sendAnalytics.
93
  */
93
  */
94
-export const createAudioOnlyDisableEvent = function() {
94
+export const createAudioOnlyChangedEvent = function(enabled) {
95
     return {
95
     return {
96
-        action: 'audio.only.disabled'
96
+        action: `audio.only.${enabled ? 'enabled' : 'disabled'}`
97
     };
97
     };
98
 };
98
 };
99
 
99
 

+ 12
- 3
react/features/base/conference/middleware.js Wyświetl plik

3
 import {
3
 import {
4
     ACTION_PINNED,
4
     ACTION_PINNED,
5
     ACTION_UNPINNED,
5
     ACTION_UNPINNED,
6
-    createAudioOnlyDisableEvent,
6
+    createAudioOnlyChangedEvent,
7
     createPinnedEvent,
7
     createPinnedEvent,
8
     sendAnalytics
8
     sendAnalytics
9
 } from '../../analytics';
9
 } from '../../analytics';
125
  */
125
  */
126
 function _conferenceFailedOrLeft({ dispatch, getState }, next, action) {
126
 function _conferenceFailedOrLeft({ dispatch, getState }, next, action) {
127
     const result = next(action);
127
     const result = next(action);
128
+    const state = getState();
129
+    const { audioOnly } = state['features/base/conference'];
130
+    const { startAudioOnly } = state['features/base/profile'].profile;
128
 
131
 
129
-    if (getState()['features/base/conference'].audioOnly) {
130
-        sendAnalytics(createAudioOnlyDisableEvent());
132
+    // FIXME: Consider implementing a standalone audio-only feature
133
+    // that handles all these state changes.
134
+    if (audioOnly && !startAudioOnly) {
135
+        sendAnalytics(createAudioOnlyChangedEvent(false));
131
         logger.log('Audio only disabled');
136
         logger.log('Audio only disabled');
132
         dispatch(setAudioOnly(false));
137
         dispatch(setAudioOnly(false));
138
+    } else if (!audioOnly && startAudioOnly) {
139
+        sendAnalytics(createAudioOnlyChangedEvent(true));
140
+        logger.log('Audio only enabled');
141
+        dispatch(setAudioOnly(true));
133
     }
142
     }
134
 
143
 
135
     return result;
144
     return result;

+ 83
- 56
react/features/base/font-icons/jitsi.json Wyświetl plik

1
 {
1
 {
2
   "IcoMoonType": "selection",
2
   "IcoMoonType": "selection",
3
   "icons": [
3
   "icons": [
4
+    {
5
+      "icon": {
6
+        "paths": [
7
+          "M128 256h768v86h-768v-86zM128 554v-84h768v84h-768zM128 768v-86h768v86h-768z"
8
+        ],
9
+        "attrs": [],
10
+        "isMulticolor": false,
11
+        "isMulticolor2": false,
12
+        "tags": [
13
+          "menu"
14
+        ],
15
+        "defaultCode": 58834,
16
+        "grid": 24
17
+      },
18
+      "attrs": [],
19
+      "properties": {
20
+        "ligatures": "menu",
21
+        "id": 489,
22
+        "order": 926,
23
+        "prevSize": 24,
24
+        "code": 58834,
25
+        "name": "menu"
26
+      },
27
+      "setIdx": 0,
28
+      "setId": 2,
29
+      "iconIdx": 489
30
+    },
4
     {
31
     {
5
       "icon": {
32
       "icon": {
6
         "paths": [
33
         "paths": [
24
         "code": 58820,
51
         "code": 58820,
25
         "name": "arrow_back"
52
         "name": "arrow_back"
26
       },
53
       },
27
-      "setIdx": 0,
28
-      "setId": 2,
29
-      "iconIdx": 45
54
+      "setIdx": 1,
55
+      "setId": 1,
56
+      "iconIdx": 0
30
     },
57
     },
31
     {
58
     {
32
       "icon": {
59
       "icon": {
51
         "code": 58376,
78
         "code": 58376,
52
         "name": "navigate_before"
79
         "name": "navigate_before"
53
       },
80
       },
54
-      "setIdx": 0,
55
-      "setId": 2,
56
-      "iconIdx": 152
81
+      "setIdx": 1,
82
+      "setId": 1,
83
+      "iconIdx": 1
57
     },
84
     },
58
     {
85
     {
59
       "icon": {
86
       "icon": {
80
       },
107
       },
81
       "setIdx": 1,
108
       "setIdx": 1,
82
       "setId": 1,
109
       "setId": 1,
83
-      "iconIdx": 0
110
+      "iconIdx": 2
84
     },
111
     },
85
     {
112
     {
86
       "icon": {
113
       "icon": {
107
       },
134
       },
108
       "setIdx": 1,
135
       "setIdx": 1,
109
       "setId": 1,
136
       "setId": 1,
110
-      "iconIdx": 1
137
+      "iconIdx": 3
111
     },
138
     },
112
     {
139
     {
113
       "icon": {
140
       "icon": {
134
       },
161
       },
135
       "setIdx": 1,
162
       "setIdx": 1,
136
       "setId": 1,
163
       "setId": 1,
137
-      "iconIdx": 2
164
+      "iconIdx": 4
138
     },
165
     },
139
     {
166
     {
140
       "icon": {
167
       "icon": {
161
       },
188
       },
162
       "setIdx": 1,
189
       "setIdx": 1,
163
       "setId": 1,
190
       "setId": 1,
164
-      "iconIdx": 3
191
+      "iconIdx": 5
165
     },
192
     },
166
     {
193
     {
167
       "icon": {
194
       "icon": {
188
       },
215
       },
189
       "setIdx": 1,
216
       "setIdx": 1,
190
       "setId": 1,
217
       "setId": 1,
191
-      "iconIdx": 4
218
+      "iconIdx": 6
192
     },
219
     },
193
     {
220
     {
194
       "icon": {
221
       "icon": {
215
       },
242
       },
216
       "setIdx": 1,
243
       "setIdx": 1,
217
       "setId": 1,
244
       "setId": 1,
218
-      "iconIdx": 5
245
+      "iconIdx": 7
219
     },
246
     },
220
     {
247
     {
221
       "icon": {
248
       "icon": {
242
       },
269
       },
243
       "setIdx": 1,
270
       "setIdx": 1,
244
       "setId": 1,
271
       "setId": 1,
245
-      "iconIdx": 6
272
+      "iconIdx": 8
246
     },
273
     },
247
     {
274
     {
248
       "icon": {
275
       "icon": {
271
       },
298
       },
272
       "setIdx": 1,
299
       "setIdx": 1,
273
       "setId": 1,
300
       "setId": 1,
274
-      "iconIdx": 7
301
+      "iconIdx": 9
275
     },
302
     },
276
     {
303
     {
277
       "icon": {
304
       "icon": {
298
       },
325
       },
299
       "setIdx": 1,
326
       "setIdx": 1,
300
       "setId": 1,
327
       "setId": 1,
301
-      "iconIdx": 8
328
+      "iconIdx": 10
302
     },
329
     },
303
     {
330
     {
304
       "icon": {
331
       "icon": {
325
       },
352
       },
326
       "setIdx": 1,
353
       "setIdx": 1,
327
       "setId": 1,
354
       "setId": 1,
328
-      "iconIdx": 9
355
+      "iconIdx": 11
329
     },
356
     },
330
     {
357
     {
331
       "icon": {
358
       "icon": {
354
       },
381
       },
355
       "setIdx": 1,
382
       "setIdx": 1,
356
       "setId": 1,
383
       "setId": 1,
357
-      "iconIdx": 10
384
+      "iconIdx": 12
358
     },
385
     },
359
     {
386
     {
360
       "icon": {
387
       "icon": {
383
       },
410
       },
384
       "setIdx": 1,
411
       "setIdx": 1,
385
       "setId": 1,
412
       "setId": 1,
386
-      "iconIdx": 11
413
+      "iconIdx": 13
387
     },
414
     },
388
     {
415
     {
389
       "icon": {
416
       "icon": {
412
       },
439
       },
413
       "setIdx": 1,
440
       "setIdx": 1,
414
       "setId": 1,
441
       "setId": 1,
415
-      "iconIdx": 12
442
+      "iconIdx": 14
416
     },
443
     },
417
     {
444
     {
418
       "icon": {
445
       "icon": {
441
       },
468
       },
442
       "setIdx": 1,
469
       "setIdx": 1,
443
       "setId": 1,
470
       "setId": 1,
444
-      "iconIdx": 13
471
+      "iconIdx": 15
445
     },
472
     },
446
     {
473
     {
447
       "icon": {
474
       "icon": {
470
       },
497
       },
471
       "setIdx": 1,
498
       "setIdx": 1,
472
       "setId": 1,
499
       "setId": 1,
473
-      "iconIdx": 14
500
+      "iconIdx": 16
474
     },
501
     },
475
     {
502
     {
476
       "icon": {
503
       "icon": {
496
       },
523
       },
497
       "setIdx": 1,
524
       "setIdx": 1,
498
       "setId": 1,
525
       "setId": 1,
499
-      "iconIdx": 15
526
+      "iconIdx": 17
500
     },
527
     },
501
     {
528
     {
502
       "icon": {
529
       "icon": {
522
       },
549
       },
523
       "setIdx": 1,
550
       "setIdx": 1,
524
       "setId": 1,
551
       "setId": 1,
525
-      "iconIdx": 16
552
+      "iconIdx": 18
526
     },
553
     },
527
     {
554
     {
528
       "icon": {
555
       "icon": {
548
       },
575
       },
549
       "setIdx": 1,
576
       "setIdx": 1,
550
       "setId": 1,
577
       "setId": 1,
551
-      "iconIdx": 17
578
+      "iconIdx": 19
552
     },
579
     },
553
     {
580
     {
554
       "icon": {
581
       "icon": {
574
       },
601
       },
575
       "setIdx": 1,
602
       "setIdx": 1,
576
       "setId": 1,
603
       "setId": 1,
577
-      "iconIdx": 18
604
+      "iconIdx": 20
578
     },
605
     },
579
     {
606
     {
580
       "icon": {
607
       "icon": {
600
       },
627
       },
601
       "setIdx": 1,
628
       "setIdx": 1,
602
       "setId": 1,
629
       "setId": 1,
603
-      "iconIdx": 19
630
+      "iconIdx": 21
604
     },
631
     },
605
     {
632
     {
606
       "icon": {
633
       "icon": {
626
       },
653
       },
627
       "setIdx": 1,
654
       "setIdx": 1,
628
       "setId": 1,
655
       "setId": 1,
629
-      "iconIdx": 20
656
+      "iconIdx": 22
630
     },
657
     },
631
     {
658
     {
632
       "icon": {
659
       "icon": {
652
       },
679
       },
653
       "setIdx": 1,
680
       "setIdx": 1,
654
       "setId": 1,
681
       "setId": 1,
655
-      "iconIdx": 21
682
+      "iconIdx": 23
656
     },
683
     },
657
     {
684
     {
658
       "icon": {
685
       "icon": {
678
       },
705
       },
679
       "setIdx": 1,
706
       "setIdx": 1,
680
       "setId": 1,
707
       "setId": 1,
681
-      "iconIdx": 22
708
+      "iconIdx": 24
682
     },
709
     },
683
     {
710
     {
684
       "icon": {
711
       "icon": {
704
       },
731
       },
705
       "setIdx": 1,
732
       "setIdx": 1,
706
       "setId": 1,
733
       "setId": 1,
707
-      "iconIdx": 23
734
+      "iconIdx": 25
708
     },
735
     },
709
     {
736
     {
710
       "icon": {
737
       "icon": {
730
       },
757
       },
731
       "setIdx": 1,
758
       "setIdx": 1,
732
       "setId": 1,
759
       "setId": 1,
733
-      "iconIdx": 24
760
+      "iconIdx": 26
734
     },
761
     },
735
     {
762
     {
736
       "icon": {
763
       "icon": {
756
       },
783
       },
757
       "setIdx": 1,
784
       "setIdx": 1,
758
       "setId": 1,
785
       "setId": 1,
759
-      "iconIdx": 25
786
+      "iconIdx": 27
760
     },
787
     },
761
     {
788
     {
762
       "icon": {
789
       "icon": {
782
       },
809
       },
783
       "setIdx": 1,
810
       "setIdx": 1,
784
       "setId": 1,
811
       "setId": 1,
785
-      "iconIdx": 26
812
+      "iconIdx": 28
786
     },
813
     },
787
     {
814
     {
788
       "icon": {
815
       "icon": {
808
       },
835
       },
809
       "setIdx": 1,
836
       "setIdx": 1,
810
       "setId": 1,
837
       "setId": 1,
811
-      "iconIdx": 27
838
+      "iconIdx": 29
812
     },
839
     },
813
     {
840
     {
814
       "icon": {
841
       "icon": {
834
       },
861
       },
835
       "setIdx": 1,
862
       "setIdx": 1,
836
       "setId": 1,
863
       "setId": 1,
837
-      "iconIdx": 28
864
+      "iconIdx": 30
838
     },
865
     },
839
     {
866
     {
840
       "icon": {
867
       "icon": {
860
       },
887
       },
861
       "setIdx": 1,
888
       "setIdx": 1,
862
       "setId": 1,
889
       "setId": 1,
863
-      "iconIdx": 29
890
+      "iconIdx": 31
864
     },
891
     },
865
     {
892
     {
866
       "icon": {
893
       "icon": {
886
       },
913
       },
887
       "setIdx": 1,
914
       "setIdx": 1,
888
       "setId": 1,
915
       "setId": 1,
889
-      "iconIdx": 30
916
+      "iconIdx": 32
890
     },
917
     },
891
     {
918
     {
892
       "icon": {
919
       "icon": {
912
       },
939
       },
913
       "setIdx": 1,
940
       "setIdx": 1,
914
       "setId": 1,
941
       "setId": 1,
915
-      "iconIdx": 31
942
+      "iconIdx": 33
916
     },
943
     },
917
     {
944
     {
918
       "icon": {
945
       "icon": {
938
       },
965
       },
939
       "setIdx": 1,
966
       "setIdx": 1,
940
       "setId": 1,
967
       "setId": 1,
941
-      "iconIdx": 32
968
+      "iconIdx": 34
942
     },
969
     },
943
     {
970
     {
944
       "icon": {
971
       "icon": {
964
       },
991
       },
965
       "setIdx": 1,
992
       "setIdx": 1,
966
       "setId": 1,
993
       "setId": 1,
967
-      "iconIdx": 33
994
+      "iconIdx": 35
968
     },
995
     },
969
     {
996
     {
970
       "icon": {
997
       "icon": {
990
       },
1017
       },
991
       "setIdx": 1,
1018
       "setIdx": 1,
992
       "setId": 1,
1019
       "setId": 1,
993
-      "iconIdx": 34
1020
+      "iconIdx": 36
994
     },
1021
     },
995
     {
1022
     {
996
       "icon": {
1023
       "icon": {
1016
       },
1043
       },
1017
       "setIdx": 1,
1044
       "setIdx": 1,
1018
       "setId": 1,
1045
       "setId": 1,
1019
-      "iconIdx": 35
1046
+      "iconIdx": 37
1020
     },
1047
     },
1021
     {
1048
     {
1022
       "icon": {
1049
       "icon": {
1042
       },
1069
       },
1043
       "setIdx": 1,
1070
       "setIdx": 1,
1044
       "setId": 1,
1071
       "setId": 1,
1045
-      "iconIdx": 36
1072
+      "iconIdx": 38
1046
     },
1073
     },
1047
     {
1074
     {
1048
       "icon": {
1075
       "icon": {
1068
       },
1095
       },
1069
       "setIdx": 1,
1096
       "setIdx": 1,
1070
       "setId": 1,
1097
       "setId": 1,
1071
-      "iconIdx": 37
1098
+      "iconIdx": 39
1072
     },
1099
     },
1073
     {
1100
     {
1074
       "icon": {
1101
       "icon": {
1094
       },
1121
       },
1095
       "setIdx": 1,
1122
       "setIdx": 1,
1096
       "setId": 1,
1123
       "setId": 1,
1097
-      "iconIdx": 38
1124
+      "iconIdx": 40
1098
     },
1125
     },
1099
     {
1126
     {
1100
       "icon": {
1127
       "icon": {
1120
       },
1147
       },
1121
       "setIdx": 1,
1148
       "setIdx": 1,
1122
       "setId": 1,
1149
       "setId": 1,
1123
-      "iconIdx": 39
1150
+      "iconIdx": 41
1124
     },
1151
     },
1125
     {
1152
     {
1126
       "icon": {
1153
       "icon": {
1146
       },
1173
       },
1147
       "setIdx": 1,
1174
       "setIdx": 1,
1148
       "setId": 1,
1175
       "setId": 1,
1149
-      "iconIdx": 40
1176
+      "iconIdx": 42
1150
     },
1177
     },
1151
     {
1178
     {
1152
       "icon": {
1179
       "icon": {
1172
       },
1199
       },
1173
       "setIdx": 1,
1200
       "setIdx": 1,
1174
       "setId": 1,
1201
       "setId": 1,
1175
-      "iconIdx": 41
1202
+      "iconIdx": 43
1176
     },
1203
     },
1177
     {
1204
     {
1178
       "icon": {
1205
       "icon": {
1198
       },
1225
       },
1199
       "setIdx": 1,
1226
       "setIdx": 1,
1200
       "setId": 1,
1227
       "setId": 1,
1201
-      "iconIdx": 42
1228
+      "iconIdx": 44
1202
     },
1229
     },
1203
     {
1230
     {
1204
       "icon": {
1231
       "icon": {
1224
       },
1251
       },
1225
       "setIdx": 1,
1252
       "setIdx": 1,
1226
       "setId": 1,
1253
       "setId": 1,
1227
-      "iconIdx": 43
1254
+      "iconIdx": 45
1228
     },
1255
     },
1229
     {
1256
     {
1230
       "icon": {
1257
       "icon": {
1253
       },
1280
       },
1254
       "setIdx": 1,
1281
       "setIdx": 1,
1255
       "setId": 1,
1282
       "setId": 1,
1256
-      "iconIdx": 44
1283
+      "iconIdx": 46
1257
     },
1284
     },
1258
     {
1285
     {
1259
       "icon": {
1286
       "icon": {
1283
       },
1310
       },
1284
       "setIdx": 1,
1311
       "setIdx": 1,
1285
       "setId": 1,
1312
       "setId": 1,
1286
-      "iconIdx": 45
1313
+      "iconIdx": 47
1287
     },
1314
     },
1288
     {
1315
     {
1289
       "icon": {
1316
       "icon": {
1313
       },
1340
       },
1314
       "setIdx": 1,
1341
       "setIdx": 1,
1315
       "setId": 1,
1342
       "setId": 1,
1316
-      "iconIdx": 46
1343
+      "iconIdx": 48
1317
     },
1344
     },
1318
     {
1345
     {
1319
       "icon": {
1346
       "icon": {
1339
       },
1366
       },
1340
       "setIdx": 1,
1367
       "setIdx": 1,
1341
       "setId": 1,
1368
       "setId": 1,
1342
-      "iconIdx": 47
1369
+      "iconIdx": 49
1343
     },
1370
     },
1344
     {
1371
     {
1345
       "icon": {
1372
       "icon": {
1365
       },
1392
       },
1366
       "setIdx": 1,
1393
       "setIdx": 1,
1367
       "setId": 1,
1394
       "setId": 1,
1368
-      "iconIdx": 48
1395
+      "iconIdx": 50
1369
     },
1396
     },
1370
     {
1397
     {
1371
       "icon": {
1398
       "icon": {
1391
       },
1418
       },
1392
       "setIdx": 1,
1419
       "setIdx": 1,
1393
       "setId": 1,
1420
       "setId": 1,
1394
-      "iconIdx": 49
1421
+      "iconIdx": 51
1395
     }
1422
     }
1396
   ],
1423
   ],
1397
   "height": 1024,
1424
   "height": 1024,

+ 3
- 3
react/features/base/media/components/native/styles.js Wyświetl plik

19
      */
19
      */
20
     videoCover: {
20
     videoCover: {
21
         backgroundColor: ColorPalette.black,
21
         backgroundColor: ColorPalette.black,
22
-        height: '100%',
22
+        bottom: 0,
23
         left: 0,
23
         left: 0,
24
         position: 'absolute',
24
         position: 'absolute',
25
-        top: 0,
26
-        width: '100%'
25
+        right: 0,
26
+        top: 0
27
     }
27
     }
28
 });
28
 });

+ 18
- 0
react/features/base/profile/middleware.js Wyświetl plik

1
 // @flow
1
 // @flow
2
 
2
 
3
+import { setAudioOnly } from '../conference';
3
 import { getLocalParticipant, participantUpdated } from '../participants';
4
 import { getLocalParticipant, participantUpdated } from '../participants';
4
 import { getProfile } from '../profile';
5
 import { getProfile } from '../profile';
5
 import { MiddlewareRegistry, toState } from '../redux';
6
 import { MiddlewareRegistry, toState } from '../redux';
18
     switch (action.type) {
19
     switch (action.type) {
19
     case PROFILE_UPDATED:
20
     case PROFILE_UPDATED:
20
         _updateLocalParticipant(store);
21
         _updateLocalParticipant(store);
22
+        _maybeUpdateStartAudioOnly(store, action);
21
     }
23
     }
22
 
24
 
23
     return result;
25
     return result;
24
 });
26
 });
25
 
27
 
28
+/**
29
+ * Updates startAudioOnly flag if it's updated in the profile.
30
+ *
31
+ * @private
32
+ * @param {Store} store - The redux store.
33
+ * @param {Object} action - The redux action.
34
+ * @returns {void}
35
+ */
36
+function _maybeUpdateStartAudioOnly(store, action) {
37
+    const { profile } = action;
38
+
39
+    if (typeof profile.startAudioOnly === 'boolean') {
40
+        store.dispatch(setAudioOnly(profile.startAudioOnly));
41
+    }
42
+}
43
+
26
 /**
44
 /**
27
  * Updates the local participant according to profile changes.
45
  * Updates the local participant according to profile changes.
28
  *
46
  *

+ 204
- 0
react/features/base/react/components/native/SideBar.js Wyświetl plik

1
+/* @flow */
2
+
3
+import React, { Component } from 'react';
4
+import {
5
+    Animated,
6
+    Dimensions,
7
+    TouchableWithoutFeedback,
8
+    View
9
+} from 'react-native';
10
+
11
+import styles, { SIDEBAR_WIDTH } from './styles';
12
+
13
+
14
+/**
15
+ * The type of the React {@code Component} props of {@link SideBar}
16
+ */
17
+type Props = {
18
+
19
+    /**
20
+     * The local participant's avatar
21
+     */
22
+    _avatar: string,
23
+
24
+    /**
25
+     * The children of the Component
26
+     */
27
+    children: React$Node,
28
+
29
+    /**
30
+     * Callback to notify the containing Component that the sidebar is
31
+     * closing.
32
+     */
33
+    onHide: Function,
34
+
35
+    /**
36
+     * Sets the menu displayed or hidden.
37
+     */
38
+    show: boolean
39
+}
40
+
41
+type State = {
42
+
43
+    /**
44
+     * Indicates whether the side bar is visible or not.
45
+     */
46
+    showSideBar: boolean,
47
+
48
+    /**
49
+     * Indicates whether the side overlay should be rendered or not.
50
+     */
51
+    showOverlay: boolean,
52
+
53
+    /**
54
+     * The native animation object.
55
+     */
56
+    sliderAnimation: Object
57
+}
58
+
59
+/**
60
+ * A generic animated side bar to be used for left side menus
61
+ */
62
+export default class SideBar extends Component<Props, State> {
63
+    _mounted: boolean;
64
+
65
+    /**
66
+     * Component's contructor.
67
+     *
68
+     * @inheritdoc
69
+     */
70
+    constructor(props: Props) {
71
+        super(props);
72
+
73
+        this.state = {
74
+            showSideBar: false,
75
+            showOverlay: false,
76
+            sliderAnimation: new Animated.Value(-SIDEBAR_WIDTH)
77
+        };
78
+
79
+        this._setShow = this._setShow.bind(this);
80
+
81
+        this._getContainerStyle = this._getContainerStyle.bind(this);
82
+        this._onHideMenu = this._onHideMenu.bind(this);
83
+        this._setShow(props.show);
84
+    }
85
+
86
+    /**
87
+     * Implements the Component's componentDidMount method.
88
+     *
89
+     * @inheritdoc
90
+     */
91
+    componentDidMount() {
92
+        this._mounted = true;
93
+    }
94
+
95
+    /**
96
+     * Implements the Component's componentWillReceiveProps method.
97
+     *
98
+     * @inheritdoc
99
+     */
100
+    componentWillReceiveProps(newProps: Props) {
101
+        if (newProps.show !== this.props.show) {
102
+            this._setShow(newProps.show);
103
+        }
104
+    }
105
+
106
+    /**
107
+     * Implements React's {@link Component#render()}.
108
+     *
109
+     * @inheritdoc
110
+     */
111
+    render() {
112
+        return (
113
+            <Animated.View
114
+                style = { this._getContainerStyle() } >
115
+                <View style = { styles.sideMenuContent }>
116
+                    {
117
+                        this.props.children
118
+                    }
119
+                </View>
120
+                <TouchableWithoutFeedback
121
+                    onPress = { this._onHideMenu }
122
+                    style = { styles.sideMenuShadowTouchable } >
123
+                    <View style = { styles.sideMenuShadow } />
124
+                </TouchableWithoutFeedback>
125
+            </Animated.View>
126
+        );
127
+    }
128
+
129
+    _getContainerStyle: () => Array<Object>
130
+
131
+    /**
132
+     * Assembles a style array for the container.
133
+     *
134
+     * @private
135
+     * @returns {Array<Object>}
136
+     */
137
+    _getContainerStyle() {
138
+        const { sliderAnimation } = this.state;
139
+        const { height, width } = Dimensions.get('window');
140
+
141
+        return [
142
+            styles.sideMenuContainer,
143
+            {
144
+                left: sliderAnimation,
145
+                width: this.state.showOverlay
146
+                    ? Math.max(height, width) + SIDEBAR_WIDTH : SIDEBAR_WIDTH
147
+            }
148
+        ];
149
+    }
150
+
151
+    _onHideMenu: () => void;
152
+
153
+    /**
154
+     * Hides the menu.
155
+     *
156
+     * @private
157
+     * @returns {void}
158
+     */
159
+    _onHideMenu() {
160
+        this._setShow(false);
161
+
162
+        const { onHide } = this.props;
163
+
164
+        if (typeof onHide === 'function') {
165
+            onHide();
166
+        }
167
+    }
168
+
169
+    _setShow: (boolean) => void;
170
+
171
+    /**
172
+     * Sets the side menu visible or hidden.
173
+     *
174
+     * @private
175
+     * @param {boolean} show - The new expected visibility value.
176
+     * @returns {void}
177
+     */
178
+    _setShow(show) {
179
+        if (this.state.showSideBar !== show) {
180
+            if (show) {
181
+                this.setState({
182
+                    showOverlay: true
183
+                });
184
+            }
185
+
186
+            Animated.timing(this.state.sliderAnimation, {
187
+                toValue: show ? 0 : -SIDEBAR_WIDTH
188
+            }).start(animationState => {
189
+                if (animationState.finished && !show) {
190
+                    this.setState({
191
+                        showOverlay: false
192
+                    });
193
+                }
194
+            });
195
+        }
196
+
197
+        if (this._mounted) {
198
+            this.setState({
199
+                showSideBar: show
200
+            });
201
+        }
202
+    }
203
+
204
+}

+ 1
- 0
react/features/base/react/components/native/index.js Wyświetl plik

2
 export { default as Link } from './Link';
2
 export { default as Link } from './Link';
3
 export { default as LoadingIndicator } from './LoadingIndicator';
3
 export { default as LoadingIndicator } from './LoadingIndicator';
4
 export { default as Header } from './Header';
4
 export { default as Header } from './Header';
5
+export { default as SideBar } from './SideBar';
5
 export * from './styles';
6
 export * from './styles';
6
 export { default as TintedView } from './TintedView';
7
 export { default as TintedView } from './TintedView';
7
 export { default as Text } from './Text';
8
 export { default as Text } from './Text';

+ 37
- 0
react/features/base/react/components/native/styles.js Wyświetl plik

11
 const HEADER_PADDING = BoxModel.padding;
11
 const HEADER_PADDING = BoxModel.padding;
12
 
12
 
13
 export const STATUSBAR_COLOR = ColorPalette.blueHighlight;
13
 export const STATUSBAR_COLOR = ColorPalette.blueHighlight;
14
+export const SIDEBAR_WIDTH = 250;
14
 
15
 
15
 /**
16
 /**
16
  * The styles of the React {@code Components} of the generic components
17
  * The styles of the React {@code Components} of the generic components
35
         height: HEADER_HEIGHT,
36
         height: HEADER_HEIGHT,
36
         justifyContent: 'flex-start',
37
         justifyContent: 'flex-start',
37
         padding: HEADER_PADDING
38
         padding: HEADER_PADDING
39
+    },
40
+
41
+    /**
42
+     * The topmost container of the side bar.
43
+     */
44
+    sideMenuContainer: {
45
+        bottom: 0,
46
+        flexDirection: 'row',
47
+        left: -SIDEBAR_WIDTH,
48
+        position: 'absolute',
49
+        top: 0,
50
+        width: SIDEBAR_WIDTH
51
+    },
52
+
53
+    /**
54
+     * The container of the actual content of the side menu.
55
+     */
56
+    sideMenuContent: {
57
+        width: SIDEBAR_WIDTH
58
+    },
59
+
60
+    /**
61
+     * The opaque area that covers the rest of the scren, when
62
+     * the side bar is open.
63
+     */
64
+    sideMenuShadow: {
65
+        backgroundColor: 'rgba(0, 0, 0, 0.5)',
66
+        flex: 1
67
+    },
68
+
69
+    /**
70
+     * The touchable area of the rest of the screen that closes the side bar
71
+     * when tapped.
72
+     */
73
+    sideMenuShadowTouchable: {
74
+        flex: 1
38
     }
75
     }
39
 });
76
 });

+ 1
- 2
react/features/base/styles/components/styles/PlatformElements.native.js Wyświetl plik

13
         alignSelf: 'center',
13
         alignSelf: 'center',
14
         color: ColorPalette.white,
14
         color: ColorPalette.white,
15
         fontSize: 26,
15
         fontSize: 26,
16
-        paddingRight: 22,
17
-        zIndex: 9999
16
+        paddingRight: 22
18
     },
17
     },
19
 
18
 
20
     /**
19
     /**

+ 3
- 1
react/features/conference/components/Conference.native.js Wyświetl plik

192
                 onClick = { this._onClick }
192
                 onClick = { this._onClick }
193
                 style = { styles.conference }
193
                 style = { styles.conference }
194
                 touchFeedback = { false }>
194
                 touchFeedback = { false }>
195
-                <StatusBar translucent = { true } />
195
+                <StatusBar
196
+                    hidden = { true }
197
+                    translucent = { true } />
196
 
198
 
197
                 {/*
199
                 {/*
198
                   * The LargeVideo is the lowermost stacking layer.
200
                   * The LargeVideo is the lowermost stacking layer.

+ 4
- 0
react/features/welcome/actionTypes.js Wyświetl plik

1
+/**
2
+ * Action type to signal the need to hide or show the side bar.
3
+ */
4
+export const SET_SIDEBAR_VISIBILITY = Symbol('SET_SIDEBAR_VISIBILITY');

+ 19
- 0
react/features/welcome/actions.js Wyświetl plik

1
+// @flow
2
+
3
+import { SET_SIDEBAR_VISIBILITY } from './actionTypes';
4
+
5
+/**
6
+ * Redux action to hide or show the status bar.
7
+ *
8
+ * @param {boolean} visible - The new value of the visibility.
9
+ * @returns {{
10
+ *     type: SET_SIDEBAR_VISIBILITY,
11
+ *     sideBarVisible: boolean
12
+ * }}
13
+ */
14
+export function setSideBarVisibility(visible: boolean) {
15
+    return {
16
+        type: SET_SIDEBAR_VISIBILITY,
17
+        sideBarVisible: visible
18
+    };
19
+}

+ 7
- 15
react/features/welcome/components/AbstractWelcomePage.js Wyświetl plik

3
 import PropTypes from 'prop-types';
3
 import PropTypes from 'prop-types';
4
 import { Component } from 'react';
4
 import { Component } from 'react';
5
 
5
 
6
-import { appNavigate } from '../../app';
7
-import { showAppSettings } from '../../app-settings';
8
 import { createWelcomePageEvent, sendAnalytics } from '../../analytics';
6
 import { createWelcomePageEvent, sendAnalytics } from '../../analytics';
7
+import { appNavigate } from '../../app';
9
 import { isRoomValid } from '../../base/conference';
8
 import { isRoomValid } from '../../base/conference';
10
 
9
 
11
 import { generateRoomWithoutSeparator } from '../functions';
10
 import { generateRoomWithoutSeparator } from '../functions';
14
  * {@code AbstractWelcomePage}'s React {@code Component} prop types.
13
  * {@code AbstractWelcomePage}'s React {@code Component} prop types.
15
  */
14
  */
16
 type Props = {
15
 type Props = {
16
+
17
+    /**
18
+     * The user's profile.
19
+     */
20
+    _profile: Object,
17
     _room: string,
21
     _room: string,
18
     dispatch: Dispatch<*>
22
     dispatch: Dispatch<*>
19
 };
23
 };
72
             = this._animateRoomnameChanging.bind(this);
76
             = this._animateRoomnameChanging.bind(this);
73
         this._onJoin = this._onJoin.bind(this);
77
         this._onJoin = this._onJoin.bind(this);
74
         this._onRoomChange = this._onRoomChange.bind(this);
78
         this._onRoomChange = this._onRoomChange.bind(this);
75
-        this._onSettingsOpen = this._onSettingsOpen.bind(this);
76
         this._updateRoomname = this._updateRoomname.bind(this);
79
         this._updateRoomname = this._updateRoomname.bind(this);
77
     }
80
     }
78
 
81
 
205
         this.setState({ room: value });
208
         this.setState({ room: value });
206
     }
209
     }
207
 
210
 
208
-    _onSettingsOpen: () => void;
209
-
210
-    /**
211
-     * Sets the app settings modal visible.
212
-     *
213
-     * @protected
214
-     * @returns {void}
215
-     */
216
-    _onSettingsOpen() {
217
-        this.props.dispatch(showAppSettings());
218
-    }
219
-
220
     _updateRoomname: () => void;
211
     _updateRoomname: () => void;
221
 
212
 
222
     /**
213
     /**
254
  */
245
  */
255
 export function _mapStateToProps(state: Object) {
246
 export function _mapStateToProps(state: Object) {
256
     return {
247
     return {
248
+        _profile: state['features/base/profile'].profile,
257
         _room: state['features/base/conference'].room
249
         _room: state['features/base/conference'].room
258
     };
250
     };
259
 }
251
 }

+ 1
- 2
react/features/welcome/components/BlankPage.native.js Wyświetl plik

9
 
9
 
10
 import { isWelcomePageAppEnabled } from '../functions';
10
 import { isWelcomePageAppEnabled } from '../functions';
11
 import LocalVideoTrackUnderlay from './LocalVideoTrackUnderlay';
11
 import LocalVideoTrackUnderlay from './LocalVideoTrackUnderlay';
12
-import styles from './styles';
13
 
12
 
14
 /**
13
 /**
15
  * The React {@code Component} displayed by {@code AbstractApp} when it has no
14
  * The React {@code Component} displayed by {@code AbstractApp} when it has no
54
      */
53
      */
55
     render() {
54
     render() {
56
         return (
55
         return (
57
-            <LocalVideoTrackUnderlay style = { styles.blankPage }>
56
+            <LocalVideoTrackUnderlay>
58
                 <NetworkActivityIndicator />
57
                 <NetworkActivityIndicator />
59
             </LocalVideoTrackUnderlay>
58
             </LocalVideoTrackUnderlay>
60
         );
59
         );

+ 100
- 0
react/features/welcome/components/SideBarItem.js Wyświetl plik

1
+// @flow
2
+
3
+import React, { Component } from 'react';
4
+import { Linking, Text, TouchableOpacity, View } from 'react-native';
5
+
6
+import styles from './styles';
7
+
8
+import { Icon } from '../../base/font-icons';
9
+import { translate } from '../../base/i18n';
10
+
11
+type Props = {
12
+
13
+    /**
14
+     * The i18n label of the item.
15
+     */
16
+    i18Label: string,
17
+
18
+    /**
19
+     * The icon of the item.
20
+     */
21
+    icon: string,
22
+
23
+    /**
24
+     * The function to be invoked when the item is pressed
25
+     * if the item is a button.
26
+     */
27
+    onPress: Function,
28
+
29
+    /**
30
+     * The translate function.
31
+     */
32
+    t: Function,
33
+
34
+    /**
35
+     * The URL of the link, if this item is a link.
36
+     */
37
+    url: string
38
+};
39
+
40
+/**
41
+ * A component rendering an item in the system sidebar.
42
+ */
43
+class SideBarItem extends Component<Props> {
44
+
45
+    /**
46
+     * Contructor of the SideBarItem Component.
47
+     *
48
+     * @inheritdoc
49
+     */
50
+    constructor(props: Props) {
51
+        super(props);
52
+
53
+        this._onOpenURL = this._onOpenURL.bind(this);
54
+    }
55
+
56
+    /**
57
+     * Implements React's {@link Component#render()}, renders the sidebar item.
58
+     *
59
+     * @inheritdoc
60
+     * @returns {ReactElement}
61
+     */
62
+    render() {
63
+        const { onPress, t } = this.props;
64
+        const onPressCalculated
65
+            = typeof onPress === 'function' ? onPress : this._onOpenURL;
66
+
67
+        return (
68
+            <TouchableOpacity
69
+                onPress = { onPressCalculated }
70
+                style = { styles.sideBarItem }>
71
+                <View style = { styles.sideBarItemButtonContainer }>
72
+                    <Icon
73
+                        name = { this.props.icon }
74
+                        style = { styles.sideBarItemIcon } />
75
+                    <Text style = { styles.sideBarItemText }>
76
+                        { t(this.props.i18Label) }
77
+                    </Text>
78
+                </View>
79
+            </TouchableOpacity>
80
+        );
81
+    }
82
+
83
+    _onOpenURL: () => void;
84
+
85
+    /**
86
+     * Opens the URL if one is provided.
87
+     *
88
+     * @private
89
+     * @returns {void}
90
+     */
91
+    _onOpenURL() {
92
+        const { url } = this.props;
93
+
94
+        if (typeof url === 'string') {
95
+            Linking.openURL(url);
96
+        }
97
+    }
98
+}
99
+
100
+export default translate(SideBarItem);

+ 115
- 85
react/features/welcome/components/WelcomePage.native.js Wyświetl plik

1
 import React from 'react';
1
 import React from 'react';
2
-import { TextInput, TouchableHighlight, View } from 'react-native';
2
+import {
3
+    SafeAreaView,
4
+    Switch,
5
+    TextInput,
6
+    TouchableHighlight,
7
+    TouchableOpacity,
8
+    View
9
+} from 'react-native';
3
 import { connect } from 'react-redux';
10
 import { connect } from 'react-redux';
4
 
11
 
5
 import { AppSettings } from '../../app-settings';
12
 import { AppSettings } from '../../app-settings';
6
-import { Icon } from '../../base/font-icons';
7
 import { translate } from '../../base/i18n';
13
 import { translate } from '../../base/i18n';
14
+import { Icon } from '../../base/font-icons';
8
 import { MEDIA_TYPE } from '../../base/media';
15
 import { MEDIA_TYPE } from '../../base/media';
9
-import { Link, LoadingIndicator, Text } from '../../base/react';
10
-import { ColorPalette } from '../../base/styles';
11
-import { createDesiredLocalTracks } from '../../base/tracks';
16
+import { updateProfile } from '../../base/profile';
17
+import {
18
+    LoadingIndicator,
19
+    Header,
20
+    Text
21
+} from '../../base/react';
22
+import { ColorPalette, PlatformElements } from '../../base/styles';
23
+import {
24
+    createDesiredLocalTracks,
25
+    destroyLocalTracks
26
+} from '../../base/tracks';
12
 import { RecentList } from '../../recent-list';
27
 import { RecentList } from '../../recent-list';
13
 
28
 
29
+import { setSideBarVisibility } from '../actions';
30
+
14
 import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage';
31
 import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage';
15
 import LocalVideoTrackUnderlay from './LocalVideoTrackUnderlay';
32
 import LocalVideoTrackUnderlay from './LocalVideoTrackUnderlay';
16
-import styles, { PLACEHOLDER_TEXT_COLOR } from './styles';
17
-
18
-/**
19
- * The URL at which the privacy policy is available to the user.
20
- */
21
-const PRIVACY_URL = 'https://jitsi.org/meet/privacy';
22
-
23
-/**
24
- * The URL at which the user may send feedback.
25
- */
26
-const SEND_FEEDBACK_URL = 'mailto:support@jitsi.org';
27
-
28
-/**
29
- * The URL at which the terms (of service/use) are available to the user.
30
- */
31
-const TERMS_URL = 'https://jitsi.org/meet/terms';
33
+import styles, {
34
+    PLACEHOLDER_TEXT_COLOR,
35
+    SWITCH_THUMB_COLOR,
36
+    SWITCH_UNDER_COLOR
37
+} from './styles';
38
+import WelcomePageSideBar from './WelcomePageSideBar';
32
 
39
 
33
 /**
40
 /**
34
  * The native container rendering the welcome page.
41
  * The native container rendering the welcome page.
43
      */
50
      */
44
     static propTypes = AbstractWelcomePage.propTypes;
51
     static propTypes = AbstractWelcomePage.propTypes;
45
 
52
 
53
+    /**
54
+     * Constructor of the Component.
55
+     *
56
+     * @inheritdoc
57
+     */
58
+    constructor(props) {
59
+        super(props);
60
+
61
+        this._onShowSideBar = this._onShowSideBar.bind(this);
62
+        this._onStartAudioOnlyChange = this._onStartAudioOnlyChange.bind(this);
63
+    }
64
+
46
     /**
65
     /**
47
      * Implements React's {@link Component#componentWillMount()}. Invoked
66
      * Implements React's {@link Component#componentWillMount()}. Invoked
48
      * immediately before mounting occurs. Creates a local video track if none
67
      * immediately before mounting occurs. Creates a local video track if none
54
     componentWillMount() {
73
     componentWillMount() {
55
         super.componentWillMount();
74
         super.componentWillMount();
56
 
75
 
57
-        this.props.dispatch(createDesiredLocalTracks(MEDIA_TYPE.VIDEO));
76
+        const { dispatch } = this.props;
77
+
78
+        if (this.props._profile.startAudioOnly) {
79
+            dispatch(destroyLocalTracks());
80
+        } else {
81
+            dispatch(createDesiredLocalTracks(MEDIA_TYPE.VIDEO));
82
+        }
58
     }
83
     }
59
 
84
 
60
     /**
85
     /**
65
      * @returns {ReactElement}
90
      * @returns {ReactElement}
66
      */
91
      */
67
     render() {
92
     render() {
68
-        const { t } = this.props;
93
+        const { t, _profile } = this.props;
69
 
94
 
70
         return (
95
         return (
71
             <LocalVideoTrackUnderlay style = { styles.welcomePage }>
96
             <LocalVideoTrackUnderlay style = { styles.welcomePage }>
72
-                <View style = { styles.roomContainer }>
73
-                    <TextInput
74
-                        accessibilityLabel = { 'Input room name.' }
75
-                        autoCapitalize = 'none'
76
-                        autoComplete = { false }
77
-                        autoCorrect = { false }
78
-                        autoFocus = { false }
79
-                        onChangeText = { this._onRoomChange }
80
-                        onSubmitEditing = { this._onJoin }
81
-                        placeholder = { t('welcomepage.roomname') }
82
-                        placeholderTextColor = { PLACEHOLDER_TEXT_COLOR }
83
-                        returnKeyType = { 'go' }
84
-                        style = { styles.textInput }
85
-                        underlineColorAndroid = 'transparent'
86
-                        value = { this.state.room } />
87
-                    <View style = { styles.buttonRow }>
88
-                        <TouchableHighlight
89
-                            accessibilityLabel = { 'Tap for Settings.' }
90
-                            onPress = { this._onSettingsOpen }
91
-                            style = { [ styles.button, styles.settingsButton ] }
92
-                            underlayColor = { ColorPalette.white }>
97
+                <View style = { PlatformElements.page }>
98
+                    <Header style = { styles.header }>
99
+                        <TouchableOpacity onPress = { this._onShowSideBar } >
93
                             <Icon
100
                             <Icon
94
-                                name = 'settings'
95
-                                style = { styles.settingsIcon } />
96
-                        </TouchableHighlight>
101
+                                name = 'menu'
102
+                                style = { PlatformElements.headerButton } />
103
+                        </TouchableOpacity>
104
+                        <View style = { styles.audioVideoSwitchContainer }>
105
+                            <Text style = { PlatformElements.headerText } >
106
+                                { t('welcomepage.videoEnabledLabel') }
107
+                            </Text>
108
+                            <Switch
109
+                                onTintColor = { SWITCH_UNDER_COLOR }
110
+                                onValueChange = { this._onStartAudioOnlyChange }
111
+                                style = { styles.audioVideoSwitch }
112
+                                thumbTintColor = { SWITCH_THUMB_COLOR }
113
+                                value = { _profile.startAudioOnly } />
114
+                            <Text style = { PlatformElements.headerText } >
115
+                                { t('welcomepage.audioOnlyLabel') }
116
+                            </Text>
117
+                        </View>
118
+                    </Header>
119
+                    <SafeAreaView style = { styles.roomContainer } >
120
+                        <TextInput
121
+                            accessibilityLabel = { 'Input room name.' }
122
+                            autoCapitalize = 'none'
123
+                            autoComplete = { false }
124
+                            autoCorrect = { false }
125
+                            autoFocus = { false }
126
+                            onChangeText = { this._onRoomChange }
127
+                            onSubmitEditing = { this._onJoin }
128
+                            placeholder = { t('welcomepage.roomname') }
129
+                            placeholderTextColor = { PLACEHOLDER_TEXT_COLOR }
130
+                            returnKeyType = { 'go' }
131
+                            style = { styles.textInput }
132
+                            underlineColorAndroid = 'transparent'
133
+                            value = { this.state.room } />
97
                         {
134
                         {
98
                             this._renderJoinButton()
135
                             this._renderJoinButton()
99
                         }
136
                         }
100
-                    </View>
101
-                    <RecentList />
137
+                        <RecentList />
138
+                    </SafeAreaView>
139
+                    <AppSettings />
102
                 </View>
140
                 </View>
103
-                <AppSettings />
104
-                {
105
-                    this._renderLegalese()
106
-                }
141
+                <WelcomePageSideBar />
107
             </LocalVideoTrackUnderlay>
142
             </LocalVideoTrackUnderlay>
108
         );
143
         );
109
     }
144
     }
110
 
145
 
146
+    /**
147
+     * Toggles the side bar.
148
+     *
149
+     * @private
150
+     * @returns {void}
151
+     */
152
+    _onShowSideBar() {
153
+        this.props.dispatch(setSideBarVisibility(true));
154
+    }
155
+
156
+    /**
157
+     * Handles the audio-video switch changes.
158
+     *
159
+     * @private
160
+     * @param {boolean} startAudioOnly - The new startAudioOnly value.
161
+     * @returns {void}
162
+     */
163
+    _onStartAudioOnlyChange(startAudioOnly) {
164
+        const { dispatch } = this.props;
165
+
166
+        dispatch(updateProfile({
167
+            ...this.props._profile,
168
+            startAudioOnly
169
+        }));
170
+    }
171
+
111
     /**
172
     /**
112
      * Renders the join button.
173
      * Renders the join button.
113
      *
174
      *
143
                 accessibilityLabel = { 'Tap to Join.' }
204
                 accessibilityLabel = { 'Tap to Join.' }
144
                 disabled = { this._isJoinDisabled() }
205
                 disabled = { this._isJoinDisabled() }
145
                 onPress = { this._onJoin }
206
                 onPress = { this._onJoin }
146
-                style = { [ styles.button, styles.joinButton ] }
207
+                style = { styles.button }
147
                 underlayColor = { ColorPalette.white }>
208
                 underlayColor = { ColorPalette.white }>
148
                 {
209
                 {
149
                     children
210
                     children
151
             </TouchableHighlight>
212
             </TouchableHighlight>
152
         );
213
         );
153
     }
214
     }
154
-
155
-    /**
156
-     * Renders legal-related content such as Terms of service/use, Privacy
157
-     * policy, etc.
158
-     *
159
-     * @private
160
-     * @returns {ReactElement}
161
-     */
162
-    _renderLegalese() {
163
-        const { t } = this.props;
164
-
165
-        return (
166
-            <View style = { styles.legaleseContainer }>
167
-                <Link
168
-                    style = { styles.legaleseItem }
169
-                    url = { TERMS_URL }>
170
-                    { t('welcomepage.terms') }
171
-                </Link>
172
-                <Link
173
-                    style = { styles.legaleseItem }
174
-                    url = { PRIVACY_URL }>
175
-                    { t('welcomepage.privacy') }
176
-                </Link>
177
-                <Link
178
-                    style = { styles.legaleseItem }
179
-                    url = { SEND_FEEDBACK_URL }>
180
-                    { t('welcomepage.sendFeedback') }
181
-                </Link>
182
-            </View>
183
-        );
184
-    }
185
 }
215
 }
186
 
216
 
187
 export default translate(connect(_mapStateToProps)(WelcomePage));
217
 export default translate(connect(_mapStateToProps)(WelcomePage));

+ 167
- 0
react/features/welcome/components/WelcomePageSideBar.native.js Wyświetl plik

1
+// @flow
2
+
3
+import React, { Component } from 'react';
4
+import { SafeAreaView, ScrollView, Text } from 'react-native';
5
+import { connect } from 'react-redux';
6
+
7
+import SideBarItem from './SideBarItem';
8
+import styles from './styles';
9
+
10
+import { setSideBarVisibility } from '../actions';
11
+
12
+import { showAppSettings } from '../../app-settings';
13
+import {
14
+    Avatar,
15
+    getAvatarURL,
16
+    getLocalParticipant,
17
+    getParticipantDisplayName
18
+} from '../../base/participants';
19
+import {
20
+    Header,
21
+    SideBar
22
+} from '../../base/react';
23
+
24
+/**
25
+ * The URL at which the privacy policy is available to the user.
26
+ */
27
+const PRIVACY_URL = 'https://jitsi.org/meet/privacy';
28
+
29
+/**
30
+ * The URL at which the user may send feedback.
31
+ */
32
+const SEND_FEEDBACK_URL = 'mailto:support@jitsi.org';
33
+
34
+/**
35
+ * The URL at which the terms (of service/use) are available to the user.
36
+ */
37
+const TERMS_URL = 'https://jitsi.org/meet/terms';
38
+
39
+type Props = {
40
+
41
+    /**
42
+     * Redux dispatch action
43
+     */
44
+    dispatch: Function,
45
+
46
+    /**
47
+     * The avatar URL to be rendered.
48
+     */
49
+    _avatar: string,
50
+
51
+    /**
52
+     * Display name of the local participant.
53
+     */
54
+    _displayName: string,
55
+
56
+    /**
57
+     * Sets the side bar visible or hidden.
58
+     */
59
+    _visible: boolean
60
+};
61
+
62
+/**
63
+ * A component rendering a welcome page sidebar.
64
+ */
65
+class WelcomePageSideBar extends Component<Props> {
66
+    /**
67
+     * Constructs a new SideBar instance.
68
+     *
69
+     * @inheritdoc
70
+     */
71
+    constructor(props) {
72
+        super(props);
73
+
74
+        this._onHideSideBar = this._onHideSideBar.bind(this);
75
+        this._onOpenSettings = this._onOpenSettings.bind(this);
76
+    }
77
+
78
+    /**
79
+     * Implements React's {@link Component#render()}, renders the sidebar.
80
+     *
81
+     * @inheritdoc
82
+     * @returns {ReactElement}
83
+     */
84
+    render() {
85
+        return (
86
+            <SideBar
87
+                onHide = { this._onHideSideBar }
88
+                show = { this.props._visible }>
89
+                <Header style = { styles.sideBarHeader }>
90
+                    <Avatar
91
+                        style = { styles.avatar }
92
+                        uri = { this.props._avatar } />
93
+                    <Text style = { styles.displayName }>
94
+                        { this.props._displayName }
95
+                    </Text>
96
+                </Header>
97
+                <SafeAreaView style = { styles.sideBarBody }>
98
+                    <ScrollView
99
+                        style = { styles.itemContainer }>
100
+                        <SideBarItem
101
+                            i18Label = 'settings.title'
102
+                            icon = 'settings'
103
+                            onPress = { this._onOpenSettings } />
104
+                        <SideBarItem
105
+                            i18Label = 'welcomepage.terms'
106
+                            icon = 'info'
107
+                            url = { TERMS_URL } />
108
+                        <SideBarItem
109
+                            i18Label = 'welcomepage.privacy'
110
+                            icon = 'info'
111
+                            url = { PRIVACY_URL } />
112
+                        <SideBarItem
113
+                            i18Label = 'welcomepage.sendFeedback'
114
+                            icon = 'info'
115
+                            url = { SEND_FEEDBACK_URL } />
116
+                    </ScrollView>
117
+                </SafeAreaView>
118
+            </SideBar>
119
+        );
120
+    }
121
+
122
+    _onHideSideBar: () => void;
123
+
124
+    /**
125
+     * Invoked when the sidebar has closed itslef (e.g. overlay pressed).
126
+     *
127
+     * @private
128
+     * @returns {void}
129
+     */
130
+    _onHideSideBar() {
131
+        this.props.dispatch(setSideBarVisibility(false));
132
+    }
133
+
134
+    _onOpenSettings: () => void;
135
+
136
+    /**
137
+     * Opens the settings screen.
138
+     *
139
+     * @private
140
+     * @returns {void}
141
+     */
142
+    _onOpenSettings() {
143
+        const { dispatch } = this.props;
144
+
145
+        dispatch(setSideBarVisibility(false));
146
+        dispatch(showAppSettings());
147
+    }
148
+}
149
+
150
+/**
151
+ * Maps (parts of) the redux state to the React {@code Component} props.
152
+ *
153
+ * @param {Object} state - The redux state.
154
+ * @protected
155
+ * @returns {Object}
156
+ */
157
+function _mapStateToProps(state: Object) {
158
+    const _localParticipant = getLocalParticipant(state);
159
+
160
+    return {
161
+        _avatar: getAvatarURL(_localParticipant),
162
+        _displayName: getParticipantDisplayName(state, _localParticipant.id),
163
+        _visible: state['features/welcome'].sideBarVisible
164
+    };
165
+}
166
+
167
+export default connect(_mapStateToProps)(WelcomePageSideBar);

+ 96
- 62
react/features/welcome/components/styles.js Wyświetl plik

5
     fixAndroidViewClipping
5
     fixAndroidViewClipping
6
 } from '../../base/styles';
6
 } from '../../base/styles';
7
 
7
 
8
+const SIDEBAR_HEADER_HEIGHT = 150;
9
+
8
 export const PLACEHOLDER_TEXT_COLOR = 'rgba(255, 255, 255, 0.3)';
10
 export const PLACEHOLDER_TEXT_COLOR = 'rgba(255, 255, 255, 0.3)';
11
+export const SWITCH_THUMB_COLOR = ColorPalette.blueHighlight;
12
+export const SWITCH_UNDER_COLOR = 'rgba(0, 0, 0, 0.4)';
9
 
13
 
10
 /**
14
 /**
11
  * The default color of text on the WelcomePage.
15
  * The default color of text on the WelcomePage.
17
  * {@code WelcomePage} and {@code BlankPage}.
21
  * {@code WelcomePage} and {@code BlankPage}.
18
  */
22
  */
19
 export default createStyleSheet({
23
 export default createStyleSheet({
24
+
25
+    /**
26
+     * The audio-video switch itself.
27
+     */
28
+    audioVideoSwitch: {
29
+        marginHorizontal: 5
30
+    },
31
+
32
+    /**
33
+     * View that contains the audio-video switch and the labels.
34
+     */
35
+    audioVideoSwitchContainer: {
36
+        flexDirection: 'row'
37
+    },
38
+
20
     /**
39
     /**
21
-     * The style of the top-level container of {@code BlankPage}.
40
+     * Style of the avatar in te side bar.
22
      */
41
      */
23
-    blankPage: {
42
+    avatar: {
43
+        alignSelf: 'center',
44
+        borderRadius: 50,
45
+        flex: 0,
46
+        height: 100,
47
+        width: 100
24
     },
48
     },
25
 
49
 
26
     /**
50
     /**
27
      * Join button style.
51
      * Join button style.
28
      */
52
      */
29
     button: {
53
     button: {
30
-        backgroundColor: ColorPalette.white,
31
-        borderColor: ColorPalette.white,
32
-        borderRadius: 8,
54
+        backgroundColor: ColorPalette.blue,
55
+        borderColor: ColorPalette.blue,
56
+        borderRadius: 4,
33
         borderWidth: 1,
57
         borderWidth: 1,
34
-        height: 45,
58
+        height: 40,
35
         justifyContent: 'center',
59
         justifyContent: 'center',
36
         marginBottom: BoxModel.margin,
60
         marginBottom: BoxModel.margin,
37
         marginTop: BoxModel.margin
61
         marginTop: BoxModel.margin
38
     },
62
     },
39
 
63
 
40
-    /**
41
-     * Layout of the button container.
42
-     */
43
-    buttonRow: {
44
-        flexDirection: 'row'
45
-    },
46
-
47
     /**
64
     /**
48
      * Join button text style.
65
      * Join button text style.
49
      */
66
      */
50
     buttonText: {
67
     buttonText: {
51
         alignSelf: 'center',
68
         alignSelf: 'center',
52
-        color: ColorPalette.blue,
69
+        color: ColorPalette.white,
53
         fontSize: 18
70
         fontSize: 18
54
     },
71
     },
55
 
72
 
56
     /**
73
     /**
57
-     * Style of the join button.
74
+     * The style of the display name label in the side bar.
58
      */
75
      */
59
-    joinButton: {
60
-        flex: 1
76
+    displayName: {
77
+        color: ColorPalette.white,
78
+        fontSize: 16,
79
+        margin: BoxModel.margin,
80
+        textAlign: 'center'
61
     },
81
     },
62
 
82
 
63
     /**
83
     /**
64
-     * The style of the legal-related content such as (hyper)links to Privacy
65
-     * Policy and Terms of Service displayed on the WelcomePage.
84
+     * The welcome screen header style.
66
      */
85
      */
67
-    legaleseContainer: {
68
-        alignItems: 'center',
69
-        flex: 0,
70
-        flexDirection: 'row',
71
-        justifyContent: 'center',
72
-
73
-        // XXX Lift the legaleseContainer up above the iPhone X home indicator;
74
-        // otherwise, the former is partially underneath the latter.
75
-        marginBottom: BoxModel.margin
86
+    header: {
87
+        justifyContent: 'space-between'
76
     },
88
     },
77
 
89
 
78
     /**
90
     /**
79
-     * The style of a piece of legal-related content such as a (hyper)link to
80
-     * Privacy Policy or Terms of Service displayed on the WelcomePage.
91
+     * Container for the items in the side bar.
81
      */
92
      */
82
-    legaleseItem: {
83
-        // XXX The backgroundColor must be transparent; otherwise, the
84
-        // backgroundColor of a parent may show through. Moreover, the
85
-        // legaleseItem is not really expected to have a background of its own.
86
-        backgroundColor: 'transparent',
87
-        color: TEXT_COLOR,
88
-        fontSize: 12,
89
-        margin: BoxModel.margin
93
+    itemContainer: {
94
+        flexDirection: 'column',
95
+        paddingTop: 10
90
     },
96
     },
91
 
97
 
92
     /**
98
     /**
99
         flex: 1
105
         flex: 1
100
     }),
106
     }),
101
 
107
 
108
+    /**
109
+     * Top level screen style
110
+     */
111
+    page: {
112
+        flex: 1,
113
+        flexDirection: 'column'
114
+    },
115
+
102
     /**
116
     /**
103
      * Container for room name input box and 'join' button.
117
      * Container for room name input box and 'join' button.
104
      */
118
      */
106
         alignSelf: 'stretch',
120
         alignSelf: 'stretch',
107
         flex: 1,
121
         flex: 1,
108
         flexDirection: 'column',
122
         flexDirection: 'column',
123
+        margin: BoxModel.margin,
124
+        marginTop: BoxModel.margin * 2
125
+    },
109
 
126
 
110
-        // XXX RecentList will eventually push the room name TextInput and the
111
-        // Join button up from the center. I don't like that movement from
112
-        // center to top, especially without an animation. Just start with the
113
-        // room name TextInput and the Join button at the top.
114
-        justifyContent: 'flex-start',
115
-        margin: 3 * BoxModel.margin,
127
+    /**
128
+     * The body of the side bar where the items are.
129
+     */
130
+    sideBarBody: {
131
+        backgroundColor: ColorPalette.white,
132
+        flex: 1
133
+    },
116
 
134
 
117
-        // XXX Be consistent with the marginBottom of legaleseContainer!
118
-        marginBottom: BoxModel.margin,
135
+    /**
136
+     * The style of the side bar header.
137
+     */
138
+    sideBarHeader: {
139
+        flexDirection: 'column',
140
+        height: SIDEBAR_HEADER_HEIGHT,
141
+        justifyContent: 'center'
142
+    },
119
 
143
 
120
-        // XXX Push the roomContainer down bellow the iPhone X notchl otherwise,
121
-        // the former seems glued to the latter. THe amount of visual margin at
122
-        // the top is pretty much as the visual margin at the bottom (if you sum
123
-        // all bottom and top margins and account for legaleseItem) which brings
124
-        // symmetry as well.
125
-        marginTop: 5 * BoxModel.margin
144
+    /**
145
+     * Style of the menu items in the side bar.
146
+     */
147
+    sideBarItem: {
148
+        padding: 13
149
+    },
150
+
151
+    /**
152
+     * The View inside the side bar buttons (icon + text).
153
+     */
154
+    sideBarItemButtonContainer: {
155
+        alignItems: 'center',
156
+        flexDirection: 'row',
157
+        justifyContent: 'flex-start'
126
     },
158
     },
127
 
159
 
128
     /**
160
     /**
129
-     * Style of the settings button.
161
+     * The icon in the side bar item touchables.
130
      */
162
      */
131
-    settingsButton: {
132
-        width: 65,
133
-        marginRight: BoxModel.margin
163
+    sideBarItemIcon: {
164
+        color: ColorPalette.blueHighlight,
165
+        fontSize: 20,
166
+        marginRight: 15
134
     },
167
     },
135
 
168
 
136
     /**
169
     /**
137
-     * Style of the settings icon on the settings button.
170
+     * The label of the side bar item touchables.
138
      */
171
      */
139
-    settingsIcon: {
140
-        fontSize: 24,
141
-        alignSelf: 'center'
172
+    sideBarItemText: {
173
+        color: ColorPalette.black,
174
+        fontWeight: 'bold'
142
     },
175
     },
143
 
176
 
144
     /**
177
     /**
147
     textInput: {
180
     textInput: {
148
         backgroundColor: 'transparent',
181
         backgroundColor: 'transparent',
149
         borderColor: ColorPalette.white,
182
         borderColor: ColorPalette.white,
150
-        borderRadius: 8,
183
+        borderRadius: 4,
151
         borderWidth: 1,
184
         borderWidth: 1,
152
         color: TEXT_COLOR,
185
         color: TEXT_COLOR,
153
         fontSize: 23,
186
         fontSize: 23,
170
      * The style of the top-level container of {@code WelcomePage}.
203
      * The style of the top-level container of {@code WelcomePage}.
171
      */
204
      */
172
     welcomePage: {
205
     welcomePage: {
173
-        backgroundColor: ColorPalette.blue
206
+        backgroundColor: ColorPalette.blue,
207
+        overflow: 'hidden'
174
     }
208
     }
175
 });
209
 });

+ 1
- 0
react/features/welcome/index.js Wyświetl plik

1
+import './reducer';
1
 import './route';
2
 import './route';
2
 
3
 
3
 export * from './components';
4
 export * from './components';

+ 23
- 0
react/features/welcome/reducer.js Wyświetl plik

1
+import { ReducerRegistry } from '../base/redux';
2
+import { SET_SIDEBAR_VISIBILITY } from './actionTypes';
3
+
4
+const DEFAULT_STATE = {
5
+    sideBarVisible: false
6
+};
7
+
8
+/**
9
+ * Reduces the Redux actions of the feature features/recording.
10
+ */
11
+ReducerRegistry.register('features/welcome',
12
+    (state = DEFAULT_STATE, action) => {
13
+        switch (action.type) {
14
+        case SET_SIDEBAR_VISIBILITY:
15
+            return {
16
+                ...state,
17
+                sideBarVisible: action.sideBarVisible
18
+            };
19
+
20
+        default:
21
+            return state;
22
+        }
23
+    });

Ładowanie…
Anuluj
Zapisz