浏览代码

User Picker Implementation

j8
yanas 7 年前
父节点
当前提交
f5d443d194

+ 0
- 4
css/_base.scss 查看文件

47
 
47
 
48
 button, select, input[type="button"],
48
 button, select, input[type="button"],
49
 input[type="reset"], input[type="submit"] {
49
 input[type="reset"], input[type="submit"] {
50
-    height: 32px;
51
-    line-height: 32px;
52
-    padding-left: 4px;
53
-    padding-right: 4px;
54
     cursor: pointer;
50
     cursor: pointer;
55
 }
51
 }
56
 
52
 

+ 3
- 0
css/_font.scss 查看文件

151
 .icon-telephone:before {
151
 .icon-telephone:before {
152
     content: "\e0cd";
152
     content: "\e0cd";
153
 }
153
 }
154
+.icon-add:before {
155
+    content: "\e145";
156
+}

+ 1
- 0
css/main.scss 查看文件

73
 @import 'policy';
73
 @import 'policy';
74
 @import 'filmstrip';
74
 @import 'filmstrip';
75
 @import 'unsupported-browser/main';
75
 @import 'unsupported-browser/main';
76
+@import 'modals/invite/add-people';
76
 @import 'vertical_filmstrip_overrides';
77
 @import 'vertical_filmstrip_overrides';
77
 
78
 
78
 /* Modules END */
79
 /* Modules END */

+ 19
- 0
css/modals/_dialog.scss 查看文件

79
 
79
 
80
 .modal-dialog-form {
80
 .modal-dialog-form {
81
     color: $modalTextColor;
81
     color: $modalTextColor;
82
+    margin-top: 5px !important;
82
 
83
 
83
     .input-control {
84
     .input-control {
84
         background: $modalMockAKInputBackground;
85
         background: $modalMockAKInputBackground;
89
 .modal-dialog-footer {
90
 .modal-dialog-footer {
90
     font-size: $modalButtonFontSize;
91
     font-size: $modalButtonFontSize;
91
 }
92
 }
93
+
94
+/**
95
+ * Styling inline dialog errors.
96
+ */
97
+.inline-dialog-error {
98
+    margin-top: 16px;
99
+
100
+    &-text {
101
+        color: $dialogErrorText;
102
+        margin-bottom: 8px;
103
+        text-align: center;
104
+    }
105
+
106
+    &-button {
107
+        display: block;
108
+        margin: 16px auto 0 auto;
109
+    }
110
+}

+ 32
- 0
css/modals/invite/_add-people.scss 查看文件

1
+/**
2
+ * Styles errors and links in the AddPeopleDialog.
3
+ */
4
+.modal-dialog-form {
5
+    .add-people-form-wrap {
6
+
7
+        .error {
8
+            padding-left: 5px;
9
+
10
+            a {
11
+                padding-left: 5px;
12
+            }
13
+        }
14
+    }
15
+}
16
+
17
+/**
18
+ * Styles the loading element in the MultiSelectAutocomplete.
19
+ */
20
+.autocomplete-loading {
21
+    justify-content: center;
22
+    display: flex;
23
+    min-width: 260px;
24
+    padding: 20px;
25
+}
26
+
27
+/**
28
+ * Styles errors in the MultiSelectAutocomplete.
29
+ */
30
+.autocomplete-error {
31
+    min-width: 260px;
32
+}

+ 1
- 0
css/themes/_light.scss 查看文件

58
 $auiDialogContentBg: $baseLight;
58
 $auiDialogContentBg: $baseLight;
59
 $auiBorderColor: #ccc;
59
 $auiBorderColor: #ccc;
60
 $dialogTitleFontWeight: 400;
60
 $dialogTitleFontWeight: 400;
61
+$dialogErrorText: #344563;
61
 
62
 
62
 /**
63
 /**
63
 * Inlay colors
64
 * Inlay colors

二进制
fonts/jitsi.eot 查看文件


+ 1
- 0
fonts/jitsi.svg 查看文件

8
 <missing-glyph horiz-adv-x="1024" />
8
 <missing-glyph horiz-adv-x="1024" />
9
 <glyph unicode="&#x20;" d="" />
9
 <glyph unicode="&#x20;" d="" />
10
 <glyph unicode="&#xe0cd;" glyph-name="phone" d="M282 564c62-120 162-220 282-282l94 94c12 12 30 16 44 10 48-16 100-24 152-24 24 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-44z" />
10
 <glyph unicode="&#xe0cd;" glyph-name="phone" d="M282 564c62-120 162-220 282-282l94 94c12 12 30 16 44 10 48-16 100-24 152-24 24 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-44z" />
11
+<glyph unicode="&#xe145;" glyph-name="add" d="M810 470h-256v-256h-84v256h-256v84h256v256h84v-256h256v-84z" />
11
 <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" />
12
 <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" />
12
 <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" />
13
 <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" />
13
 <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" />
14
 <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" />

二进制
fonts/jitsi.ttf 查看文件


二进制
fonts/jitsi.woff 查看文件


+ 234
- 207
fonts/selection.json 查看文件

1
 {
1
 {
2
   "IcoMoonType": "selection",
2
   "IcoMoonType": "selection",
3
   "icons": [
3
   "icons": [
4
-    {
5
-      "icon": {
6
-        "paths": [
7
-          "M330.667 554.667c-0.427-14.933 6.4-29.44 17.92-39.253 32 6.827 61.867 20.053 88.747 39.253 0 29.013-23.893 52.907-53.333 52.907s-52.907-23.467-53.333-52.907zM586.667 554.667c26.88-18.773 56.747-32 88.747-38.827 11.52 9.813 18.347 24.32 17.92 38.827 0 29.867-23.893 53.76-53.333 53.76s-53.333-23.893-53.333-53.76v0zM512 384c-118.187-1.707-234.667 27.733-338.347 85.333l-2.987 42.667c0 52.48 12.373 104.107 35.84 151.040 101.12-15.36 203.093-23.040 305.493-23.040s204.373 7.68 305.493 23.040c23.467-46.933 35.84-98.56 35.84-151.040l-2.987-42.667c-103.68-57.6-220.16-87.040-338.347-85.333zM512 85.333c235.641 0 426.667 191.025 426.667 426.667s-191.025 426.667-426.667 426.667c-235.641 0-426.667-191.025-426.667-426.667s191.025-426.667 426.667-426.667z"
8
-        ],
9
-        "attrs": [
10
-          {}
11
-        ],
12
-        "isMulticolor": false,
13
-        "isMulticolor2": false,
14
-        "grid": 24,
15
-        "tags": [
16
-          "ninja"
17
-        ]
18
-      },
19
-      "attrs": [
20
-        {}
21
-      ],
22
-      "properties": {
23
-        "order": 851,
24
-        "id": 121,
25
-        "name": "ninja",
26
-        "prevSize": 32,
27
-        "code": 59657
28
-      },
29
-      "setIdx": 0,
30
-      "setId": 1,
31
-      "iconIdx": 0
32
-    },
33
-    {
34
-      "icon": {
35
-        "paths": [
36
-          "M282 460c62 120 162 220 282 282l94-94c12-12 30-16 44-10 48 16 100 24 152 24 24 0 42 18 42 42v150c0 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 44z"
37
-        ],
38
-        "attrs": [],
39
-        "isMulticolor": false,
40
-        "isMulticolor2": false,
41
-        "tags": [
42
-          "phone"
43
-        ],
44
-        "defaultCode": 57549,
45
-        "grid": 24
46
-      },
47
-      "attrs": [],
48
-      "properties": {
49
-        "ligatures": "call, local_phone, phone",
50
-        "id": 120,
51
-        "order": 848,
52
-        "prevSize": 32,
53
-        "code": 57549,
54
-        "name": "phone"
55
-      },
56
-      "setIdx": 0,
57
-      "setId": 1,
58
-      "iconIdx": 41
59
-    },
60
     {
4
     {
61
       "icon": {
5
       "icon": {
62
         "paths": [
6
         "paths": [
76
         {}
20
         {}
77
       ],
21
       ],
78
       "properties": {
22
       "properties": {
79
-        "order": 109,
23
+        "order": 856,
80
         "id": 0,
24
         "id": 0,
81
         "name": "mic-camera-combined",
25
         "name": "mic-camera-combined",
82
         "prevSize": 32,
26
         "prevSize": 32,
83
         "code": 59651
27
         "code": 59651
84
       },
28
       },
85
       "setIdx": 0,
29
       "setIdx": 0,
86
-      "setId": 1,
87
-      "iconIdx": 1
30
+      "setId": 5,
31
+      "iconIdx": 0
88
     },
32
     },
89
     {
33
     {
90
       "icon": {
34
       "icon": {
105
         {}
49
         {}
106
       ],
50
       ],
107
       "properties": {
51
       "properties": {
108
-        "order": 104,
52
+        "order": 857,
109
         "id": 1,
53
         "id": 1,
110
         "name": "feedback",
54
         "name": "feedback",
111
         "prevSize": 32,
55
         "prevSize": 32,
112
         "code": 59677
56
         "code": 59677
113
       },
57
       },
114
       "setIdx": 0,
58
       "setIdx": 0,
115
-      "setId": 1,
116
-      "iconIdx": 2
59
+      "setId": 5,
60
+      "iconIdx": 1
117
     },
61
     },
118
     {
62
     {
119
       "icon": {
63
       "icon": {
134
         {}
78
         {}
135
       ],
79
       ],
136
       "properties": {
80
       "properties": {
137
-        "order": 103,
81
+        "order": 858,
138
         "id": 2,
82
         "id": 2,
139
         "name": "toggle-filmstrip",
83
         "name": "toggle-filmstrip",
140
         "prevSize": 32,
84
         "prevSize": 32,
141
         "code": 59676
85
         "code": 59676
142
       },
86
       },
143
       "setIdx": 0,
87
       "setIdx": 0,
144
-      "setId": 1,
145
-      "iconIdx": 3
88
+      "setId": 5,
89
+      "iconIdx": 2
146
     },
90
     },
147
     {
91
     {
148
       "icon": {
92
       "icon": {
160
       "attrs": [],
104
       "attrs": [],
161
       "properties": {
105
       "properties": {
162
         "id": 3,
106
         "id": 3,
163
-        "order": 60,
107
+        "order": 859,
164
         "ligatures": "account_circle",
108
         "ligatures": "account_circle",
165
         "prevSize": 32,
109
         "prevSize": 32,
166
         "code": 59649,
110
         "code": 59649,
167
         "name": "avatar"
111
         "name": "avatar"
168
       },
112
       },
169
       "setIdx": 0,
113
       "setIdx": 0,
170
-      "setId": 1,
171
-      "iconIdx": 4
114
+      "setId": 5,
115
+      "iconIdx": 3
172
     },
116
     },
173
     {
117
     {
174
       "icon": {
118
       "icon": {
186
       "attrs": [],
130
       "attrs": [],
187
       "properties": {
131
       "properties": {
188
         "id": 4,
132
         "id": 4,
189
-        "order": 849,
133
+        "order": 860,
190
         "ligatures": "call_end",
134
         "ligatures": "call_end",
191
         "prevSize": 32,
135
         "prevSize": 32,
192
         "code": 59653,
136
         "code": 59653,
193
         "name": "hangup"
137
         "name": "hangup"
194
       },
138
       },
195
       "setIdx": 0,
139
       "setIdx": 0,
196
-      "setId": 1,
197
-      "iconIdx": 5
140
+      "setId": 5,
141
+      "iconIdx": 4
198
     },
142
     },
199
     {
143
     {
200
       "icon": {
144
       "icon": {
212
       "attrs": [],
156
       "attrs": [],
213
       "properties": {
157
       "properties": {
214
         "id": 5,
158
         "id": 5,
215
-        "order": 61,
159
+        "order": 861,
216
         "ligatures": "chat_bubble_outline",
160
         "ligatures": "chat_bubble_outline",
217
         "prevSize": 32,
161
         "prevSize": 32,
218
         "code": 59654,
162
         "code": 59654,
219
         "name": "chat"
163
         "name": "chat"
220
       },
164
       },
221
       "setIdx": 0,
165
       "setIdx": 0,
222
-      "setId": 1,
223
-      "iconIdx": 6
166
+      "setId": 5,
167
+      "iconIdx": 5
224
     },
168
     },
225
     {
169
     {
226
       "icon": {
170
       "icon": {
238
       "attrs": [],
182
       "attrs": [],
239
       "properties": {
183
       "properties": {
240
         "id": 6,
184
         "id": 6,
241
-        "order": 99,
185
+        "order": 862,
242
         "ligatures": "cloud_download",
186
         "ligatures": "cloud_download",
243
         "prevSize": 32,
187
         "prevSize": 32,
244
         "code": 59650,
188
         "code": 59650,
245
         "name": "download"
189
         "name": "download"
246
       },
190
       },
247
       "setIdx": 0,
191
       "setIdx": 0,
248
-      "setId": 1,
249
-      "iconIdx": 7
192
+      "setId": 5,
193
+      "iconIdx": 6
250
     },
194
     },
251
     {
195
     {
252
       "icon": {
196
       "icon": {
264
       "attrs": [],
208
       "attrs": [],
265
       "properties": {
209
       "properties": {
266
         "id": 7,
210
         "id": 7,
267
-        "order": 89,
211
+        "order": 863,
268
         "ligatures": "create, edit, mode_edit",
212
         "ligatures": "create, edit, mode_edit",
269
         "prevSize": 32,
213
         "prevSize": 32,
270
         "code": 59655,
214
         "code": 59655,
271
         "name": "edit"
215
         "name": "edit"
272
       },
216
       },
273
       "setIdx": 0,
217
       "setIdx": 0,
274
-      "setId": 1,
275
-      "iconIdx": 8
218
+      "setId": 5,
219
+      "iconIdx": 7
276
     },
220
     },
277
     {
221
     {
278
       "icon": {
222
       "icon": {
290
       "attrs": [],
234
       "attrs": [],
291
       "properties": {
235
       "properties": {
292
         "id": 8,
236
         "id": 8,
293
-        "order": 85,
237
+        "order": 864,
294
         "ligatures": "description",
238
         "ligatures": "description",
295
         "prevSize": 32,
239
         "prevSize": 32,
296
         "code": 59656,
240
         "code": 59656,
297
         "name": "share-doc"
241
         "name": "share-doc"
298
       },
242
       },
299
       "setIdx": 0,
243
       "setIdx": 0,
300
-      "setId": 1,
301
-      "iconIdx": 9
244
+      "setId": 5,
245
+      "iconIdx": 8
302
     },
246
     },
303
     {
247
     {
304
       "icon": {
248
       "icon": {
315
       },
259
       },
316
       "attrs": [],
260
       "attrs": [],
317
       "properties": {
261
       "properties": {
318
-        "id": 10,
319
-        "order": 98,
262
+        "id": 9,
263
+        "order": 865,
320
         "ligatures": "eject",
264
         "ligatures": "eject",
321
         "prevSize": 32,
265
         "prevSize": 32,
322
         "code": 59652,
266
         "code": 59652,
323
         "name": "kick"
267
         "name": "kick"
324
       },
268
       },
325
       "setIdx": 0,
269
       "setIdx": 0,
326
-      "setId": 1,
327
-      "iconIdx": 10
270
+      "setId": 5,
271
+      "iconIdx": 9
328
     },
272
     },
329
     {
273
     {
330
       "icon": {
274
       "icon": {
341
       },
285
       },
342
       "attrs": [],
286
       "attrs": [],
343
       "properties": {
287
       "properties": {
344
-        "id": 11,
345
-        "order": 106,
288
+        "id": 10,
289
+        "order": 866,
346
         "ligatures": "expand_less",
290
         "ligatures": "expand_less",
347
         "prevSize": 32,
291
         "prevSize": 32,
348
         "code": 59679,
292
         "code": 59679,
349
         "name": "menu-up"
293
         "name": "menu-up"
350
       },
294
       },
351
       "setIdx": 0,
295
       "setIdx": 0,
352
-      "setId": 1,
353
-      "iconIdx": 11
296
+      "setId": 5,
297
+      "iconIdx": 10
354
     },
298
     },
355
     {
299
     {
356
       "icon": {
300
       "icon": {
367
       },
311
       },
368
       "attrs": [],
312
       "attrs": [],
369
       "properties": {
313
       "properties": {
370
-        "id": 12,
371
-        "order": 107,
314
+        "id": 11,
315
+        "order": 867,
372
         "ligatures": "expand_more",
316
         "ligatures": "expand_more",
373
         "prevSize": 32,
317
         "prevSize": 32,
374
         "code": 59680,
318
         "code": 59680,
375
         "name": "menu-down"
319
         "name": "menu-down"
376
       },
320
       },
377
       "setIdx": 0,
321
       "setIdx": 0,
378
-      "setId": 1,
379
-      "iconIdx": 12
322
+      "setId": 5,
323
+      "iconIdx": 11
380
     },
324
     },
381
     {
325
     {
382
       "icon": {
326
       "icon": {
393
       },
337
       },
394
       "attrs": [],
338
       "attrs": [],
395
       "properties": {
339
       "properties": {
396
-        "id": 13,
397
-        "order": 94,
340
+        "id": 12,
341
+        "order": 868,
398
         "ligatures": "fullscreen",
342
         "ligatures": "fullscreen",
399
         "prevSize": 32,
343
         "prevSize": 32,
400
         "code": 59659,
344
         "code": 59659,
401
         "name": "full-screen"
345
         "name": "full-screen"
402
       },
346
       },
403
       "setIdx": 0,
347
       "setIdx": 0,
404
-      "setId": 1,
405
-      "iconIdx": 13
348
+      "setId": 5,
349
+      "iconIdx": 12
406
     },
350
     },
407
     {
351
     {
408
       "icon": {
352
       "icon": {
419
       },
363
       },
420
       "attrs": [],
364
       "attrs": [],
421
       "properties": {
365
       "properties": {
422
-        "id": 14,
423
-        "order": 92,
366
+        "id": 13,
367
+        "order": 869,
424
         "ligatures": "fullscreen_exit",
368
         "ligatures": "fullscreen_exit",
425
         "prevSize": 32,
369
         "prevSize": 32,
426
         "code": 59660,
370
         "code": 59660,
427
         "name": "exit-full-screen"
371
         "name": "exit-full-screen"
428
       },
372
       },
429
       "setIdx": 0,
373
       "setIdx": 0,
430
-      "setId": 1,
431
-      "iconIdx": 14
374
+      "setId": 5,
375
+      "iconIdx": 13
432
     },
376
     },
433
     {
377
     {
434
       "icon": {
378
       "icon": {
445
       },
389
       },
446
       "attrs": [],
390
       "attrs": [],
447
       "properties": {
391
       "properties": {
448
-        "id": 15,
449
-        "order": 101,
392
+        "id": 14,
393
+        "order": 870,
450
         "ligatures": "grade, star",
394
         "ligatures": "grade, star",
451
         "prevSize": 32,
395
         "prevSize": 32,
452
         "code": 59658,
396
         "code": 59658,
453
         "name": "star-full"
397
         "name": "star-full"
454
       },
398
       },
455
       "setIdx": 0,
399
       "setIdx": 0,
456
-      "setId": 1,
457
-      "iconIdx": 15
400
+      "setId": 5,
401
+      "iconIdx": 14
458
     },
402
     },
459
     {
403
     {
460
       "icon": {
404
       "icon": {
471
       },
415
       },
472
       "attrs": [],
416
       "attrs": [],
473
       "properties": {
417
       "properties": {
474
-        "id": 16,
475
-        "order": 66,
418
+        "id": 15,
419
+        "order": 871,
476
         "ligatures": "lock_open",
420
         "ligatures": "lock_open",
477
         "prevSize": 32,
421
         "prevSize": 32,
478
         "code": 59661,
422
         "code": 59661,
479
         "name": "security"
423
         "name": "security"
480
       },
424
       },
481
       "setIdx": 0,
425
       "setIdx": 0,
482
-      "setId": 1,
483
-      "iconIdx": 16
426
+      "setId": 5,
427
+      "iconIdx": 15
484
     },
428
     },
485
     {
429
     {
486
       "icon": {
430
       "icon": {
497
       },
441
       },
498
       "attrs": [],
442
       "attrs": [],
499
       "properties": {
443
       "properties": {
500
-        "id": 17,
501
-        "order": 65,
444
+        "id": 16,
445
+        "order": 872,
502
         "ligatures": "lock_outline",
446
         "ligatures": "lock_outline",
503
         "prevSize": 32,
447
         "prevSize": 32,
504
         "code": 59662,
448
         "code": 59662,
505
         "name": "security-locked"
449
         "name": "security-locked"
506
       },
450
       },
507
       "setIdx": 0,
451
       "setIdx": 0,
508
-      "setId": 1,
509
-      "iconIdx": 17
452
+      "setId": 5,
453
+      "iconIdx": 16
510
     },
454
     },
511
     {
455
     {
512
       "icon": {
456
       "icon": {
523
       },
467
       },
524
       "attrs": [],
468
       "attrs": [],
525
       "properties": {
469
       "properties": {
526
-        "id": 18,
527
-        "order": 67,
470
+        "id": 17,
471
+        "order": 873,
528
         "ligatures": "loop, sync",
472
         "ligatures": "loop, sync",
529
         "prevSize": 32,
473
         "prevSize": 32,
530
         "code": 59663,
474
         "code": 59663,
531
         "name": "reload"
475
         "name": "reload"
532
       },
476
       },
533
       "setIdx": 0,
477
       "setIdx": 0,
534
-      "setId": 1,
535
-      "iconIdx": 18
478
+      "setId": 5,
479
+      "iconIdx": 17
536
     },
480
     },
537
     {
481
     {
538
       "icon": {
482
       "icon": {
549
       },
493
       },
550
       "attrs": [],
494
       "attrs": [],
551
       "properties": {
495
       "properties": {
552
-        "id": 19,
553
-        "order": 68,
496
+        "id": 18,
497
+        "order": 874,
554
         "ligatures": "mic",
498
         "ligatures": "mic",
555
         "prevSize": 32,
499
         "prevSize": 32,
556
         "code": 59664,
500
         "code": 59664,
557
         "name": "microphone"
501
         "name": "microphone"
558
       },
502
       },
559
       "setIdx": 0,
503
       "setIdx": 0,
560
-      "setId": 1,
561
-      "iconIdx": 19
504
+      "setId": 5,
505
+      "iconIdx": 18
562
     },
506
     },
563
     {
507
     {
564
       "icon": {
508
       "icon": {
575
       },
519
       },
576
       "attrs": [],
520
       "attrs": [],
577
       "properties": {
521
       "properties": {
578
-        "id": 20,
579
-        "order": 69,
522
+        "id": 19,
523
+        "order": 875,
580
         "ligatures": "mic_none",
524
         "ligatures": "mic_none",
581
         "prevSize": 32,
525
         "prevSize": 32,
582
         "code": 59665,
526
         "code": 59665,
583
         "name": "mic-empty"
527
         "name": "mic-empty"
584
       },
528
       },
585
       "setIdx": 0,
529
       "setIdx": 0,
586
-      "setId": 1,
587
-      "iconIdx": 20
530
+      "setId": 5,
531
+      "iconIdx": 19
588
     },
532
     },
589
     {
533
     {
590
       "icon": {
534
       "icon": {
601
       },
545
       },
602
       "attrs": [],
546
       "attrs": [],
603
       "properties": {
547
       "properties": {
604
-        "id": 21,
605
-        "order": 70,
548
+        "id": 20,
549
+        "order": 876,
606
         "ligatures": "mic_off",
550
         "ligatures": "mic_off",
607
         "prevSize": 32,
551
         "prevSize": 32,
608
         "code": 59666,
552
         "code": 59666,
609
         "name": "mic-disabled"
553
         "name": "mic-disabled"
610
       },
554
       },
611
       "setIdx": 0,
555
       "setIdx": 0,
612
-      "setId": 1,
613
-      "iconIdx": 21
556
+      "setId": 5,
557
+      "iconIdx": 20
614
     },
558
     },
615
     {
559
     {
616
       "icon": {
560
       "icon": {
627
       },
571
       },
628
       "attrs": [],
572
       "attrs": [],
629
       "properties": {
573
       "properties": {
630
-        "id": 22,
631
-        "order": 105,
574
+        "id": 21,
575
+        "order": 877,
632
         "ligatures": "pan_tool",
576
         "ligatures": "pan_tool",
633
         "prevSize": 32,
577
         "prevSize": 32,
634
         "code": 59678,
578
         "code": 59678,
635
         "name": "raised-hand"
579
         "name": "raised-hand"
636
       },
580
       },
637
       "setIdx": 0,
581
       "setIdx": 0,
638
-      "setId": 1,
639
-      "iconIdx": 22
582
+      "setId": 5,
583
+      "iconIdx": 21
640
     },
584
     },
641
     {
585
     {
642
       "icon": {
586
       "icon": {
653
       },
597
       },
654
       "attrs": [],
598
       "attrs": [],
655
       "properties": {
599
       "properties": {
656
-        "id": 23,
657
-        "order": 100,
600
+        "id": 22,
601
+        "order": 878,
658
         "ligatures": "people_outline",
602
         "ligatures": "people_outline",
659
         "prevSize": 32,
603
         "prevSize": 32,
660
         "code": 59675,
604
         "code": 59675,
661
         "name": "contactList"
605
         "name": "contactList"
662
       },
606
       },
663
       "setIdx": 0,
607
       "setIdx": 0,
664
-      "setId": 1,
665
-      "iconIdx": 23
608
+      "setId": 5,
609
+      "iconIdx": 22
666
     },
610
     },
667
     {
611
     {
668
       "icon": {
612
       "icon": {
679
       },
623
       },
680
       "attrs": [],
624
       "attrs": [],
681
       "properties": {
625
       "properties": {
682
-        "id": 24,
683
-        "order": 87,
626
+        "id": 23,
627
+        "order": 879,
684
         "ligatures": "person_add",
628
         "ligatures": "person_add",
685
         "prevSize": 32,
629
         "prevSize": 32,
686
         "code": 59667,
630
         "code": 59667,
687
         "name": "link"
631
         "name": "link"
688
       },
632
       },
689
       "setIdx": 0,
633
       "setIdx": 0,
690
-      "setId": 1,
691
-      "iconIdx": 24
634
+      "setId": 5,
635
+      "iconIdx": 23
692
     },
636
     },
693
     {
637
     {
694
       "icon": {
638
       "icon": {
705
       },
649
       },
706
       "attrs": [],
650
       "attrs": [],
707
       "properties": {
651
       "properties": {
708
-        "id": 25,
709
-        "order": 82,
652
+        "id": 24,
653
+        "order": 880,
710
         "ligatures": "play_circle_outline",
654
         "ligatures": "play_circle_outline",
711
         "prevSize": 32,
655
         "prevSize": 32,
712
         "code": 59668,
656
         "code": 59668,
713
         "name": "shared-video"
657
         "name": "shared-video"
714
       },
658
       },
715
       "setIdx": 0,
659
       "setIdx": 0,
716
-      "setId": 1,
717
-      "iconIdx": 25
660
+      "setId": 5,
661
+      "iconIdx": 24
718
     },
662
     },
719
     {
663
     {
720
       "icon": {
664
       "icon": {
731
       },
675
       },
732
       "attrs": [],
676
       "attrs": [],
733
       "properties": {
677
       "properties": {
734
-        "id": 26,
735
-        "order": 81,
678
+        "id": 25,
679
+        "order": 881,
736
         "ligatures": "settings",
680
         "ligatures": "settings",
737
         "prevSize": 32,
681
         "prevSize": 32,
738
         "code": 59669,
682
         "code": 59669,
739
         "name": "settings"
683
         "name": "settings"
740
       },
684
       },
741
       "setIdx": 0,
685
       "setIdx": 0,
742
-      "setId": 1,
743
-      "iconIdx": 26
686
+      "setId": 5,
687
+      "iconIdx": 25
744
     },
688
     },
745
     {
689
     {
746
       "icon": {
690
       "icon": {
757
       },
701
       },
758
       "attrs": [],
702
       "attrs": [],
759
       "properties": {
703
       "properties": {
760
-        "id": 27,
761
-        "order": 76,
704
+        "id": 26,
705
+        "order": 882,
762
         "ligatures": "star_border",
706
         "ligatures": "star_border",
763
         "prevSize": 32,
707
         "prevSize": 32,
764
         "code": 59670,
708
         "code": 59670,
765
         "name": "star"
709
         "name": "star"
766
       },
710
       },
767
       "setIdx": 0,
711
       "setIdx": 0,
768
-      "setId": 1,
769
-      "iconIdx": 27
712
+      "setId": 5,
713
+      "iconIdx": 26
770
     },
714
     },
771
     {
715
     {
772
       "icon": {
716
       "icon": {
783
       },
727
       },
784
       "attrs": [],
728
       "attrs": [],
785
       "properties": {
729
       "properties": {
786
-        "id": 28,
787
-        "order": 108,
730
+        "id": 27,
731
+        "order": 883,
788
         "ligatures": "switch_camera",
732
         "ligatures": "switch_camera",
789
         "prevSize": 32,
733
         "prevSize": 32,
790
         "code": 59681,
734
         "code": 59681,
791
         "name": "switch-camera"
735
         "name": "switch-camera"
792
       },
736
       },
793
       "setIdx": 0,
737
       "setIdx": 0,
794
-      "setId": 1,
795
-      "iconIdx": 28
738
+      "setId": 5,
739
+      "iconIdx": 27
796
     },
740
     },
797
     {
741
     {
798
       "icon": {
742
       "icon": {
809
       },
753
       },
810
       "attrs": [],
754
       "attrs": [],
811
       "properties": {
755
       "properties": {
812
-        "id": 29,
813
-        "order": 93,
756
+        "id": 28,
757
+        "order": 884,
814
         "ligatures": "tv",
758
         "ligatures": "tv",
815
         "prevSize": 32,
759
         "prevSize": 32,
816
         "code": 59671,
760
         "code": 59671,
817
         "name": "share-desktop"
761
         "name": "share-desktop"
818
       },
762
       },
819
       "setIdx": 0,
763
       "setIdx": 0,
820
-      "setId": 1,
821
-      "iconIdx": 29
764
+      "setId": 5,
765
+      "iconIdx": 28
822
     },
766
     },
823
     {
767
     {
824
       "icon": {
768
       "icon": {
835
       },
779
       },
836
       "attrs": [],
780
       "attrs": [],
837
       "properties": {
781
       "properties": {
838
-        "id": 30,
839
-        "order": 77,
782
+        "id": 29,
783
+        "order": 885,
840
         "ligatures": "videocam",
784
         "ligatures": "videocam",
841
         "prevSize": 32,
785
         "prevSize": 32,
842
         "code": 59672,
786
         "code": 59672,
843
         "name": "camera"
787
         "name": "camera"
844
       },
788
       },
845
       "setIdx": 0,
789
       "setIdx": 0,
846
-      "setId": 1,
847
-      "iconIdx": 30
790
+      "setId": 5,
791
+      "iconIdx": 29
848
     },
792
     },
849
     {
793
     {
850
       "icon": {
794
       "icon": {
861
       },
805
       },
862
       "attrs": [],
806
       "attrs": [],
863
       "properties": {
807
       "properties": {
864
-        "id": 31,
865
-        "order": 78,
808
+        "id": 30,
809
+        "order": 886,
866
         "ligatures": "videocam_off",
810
         "ligatures": "videocam_off",
867
         "prevSize": 32,
811
         "prevSize": 32,
868
         "code": 59673,
812
         "code": 59673,
869
         "name": "camera-disabled"
813
         "name": "camera-disabled"
870
       },
814
       },
871
       "setIdx": 0,
815
       "setIdx": 0,
872
-      "setId": 1,
873
-      "iconIdx": 31
816
+      "setId": 5,
817
+      "iconIdx": 30
874
     },
818
     },
875
     {
819
     {
876
       "icon": {
820
       "icon": {
887
       },
831
       },
888
       "attrs": [],
832
       "attrs": [],
889
       "properties": {
833
       "properties": {
890
-        "id": 32,
891
-        "order": 79,
834
+        "id": 31,
835
+        "order": 887,
892
         "ligatures": "volume_up",
836
         "ligatures": "volume_up",
893
         "prevSize": 32,
837
         "prevSize": 32,
894
         "code": 59674,
838
         "code": 59674,
895
         "name": "volume"
839
         "name": "volume"
896
       },
840
       },
897
       "setIdx": 0,
841
       "setIdx": 0,
898
-      "setId": 1,
899
-      "iconIdx": 32
842
+      "setId": 5,
843
+      "iconIdx": 31
900
     },
844
     },
901
     {
845
     {
902
       "icon": {
846
       "icon": {
936
         {}
880
         {}
937
       ],
881
       ],
938
       "properties": {
882
       "properties": {
939
-        "order": 33,
940
-        "id": 33,
883
+        "order": 888,
884
+        "id": 32,
941
         "name": "connection-lost",
885
         "name": "connection-lost",
942
         "prevSize": 32,
886
         "prevSize": 32,
943
         "code": 59648
887
         "code": 59648
944
       },
888
       },
945
       "setIdx": 0,
889
       "setIdx": 0,
946
-      "setId": 1,
947
-      "iconIdx": 33
890
+      "setId": 5,
891
+      "iconIdx": 32
948
     },
892
     },
949
     {
893
     {
950
       "icon": {
894
       "icon": {
1008
         }
952
         }
1009
       ],
953
       ],
1010
       "properties": {
954
       "properties": {
1011
-        "order": 37,
1012
-        "id": 34,
955
+        "order": 889,
956
+        "id": 33,
1013
         "prevSize": 32,
957
         "prevSize": 32,
1014
         "code": 58906,
958
         "code": 58906,
1015
         "name": "connection",
959
         "name": "connection",
1016
         "ligatures": ""
960
         "ligatures": ""
1017
       },
961
       },
1018
       "setIdx": 0,
962
       "setIdx": 0,
1019
-      "setId": 1,
1020
-      "iconIdx": 34
963
+      "setId": 5,
964
+      "iconIdx": 33
1021
     },
965
     },
1022
     {
966
     {
1023
       "icon": {
967
       "icon": {
1037
       },
981
       },
1038
       "attrs": [],
982
       "attrs": [],
1039
       "properties": {
983
       "properties": {
1040
-        "order": 43,
1041
-        "id": 35,
984
+        "order": 890,
985
+        "id": 34,
1042
         "prevSize": 32,
986
         "prevSize": 32,
1043
         "code": 58899,
987
         "code": 58899,
1044
         "name": "recDisable",
988
         "name": "recDisable",
1045
         "ligatures": ""
989
         "ligatures": ""
1046
       },
990
       },
1047
       "setIdx": 0,
991
       "setIdx": 0,
1048
-      "setId": 1,
1049
-      "iconIdx": 35
992
+      "setId": 5,
993
+      "iconIdx": 34
1050
     },
994
     },
1051
     {
995
     {
1052
       "icon": {
996
       "icon": {
1067
       },
1011
       },
1068
       "attrs": [],
1012
       "attrs": [],
1069
       "properties": {
1013
       "properties": {
1070
-        "order": 44,
1071
-        "id": 36,
1014
+        "order": 891,
1015
+        "id": 35,
1072
         "prevSize": 32,
1016
         "prevSize": 32,
1073
         "code": 58900,
1017
         "code": 58900,
1074
         "name": "recEnable",
1018
         "name": "recEnable",
1075
         "ligatures": ""
1019
         "ligatures": ""
1076
       },
1020
       },
1077
       "setIdx": 0,
1021
       "setIdx": 0,
1078
-      "setId": 1,
1079
-      "iconIdx": 36
1022
+      "setId": 5,
1023
+      "iconIdx": 35
1080
     },
1024
     },
1081
     {
1025
     {
1082
       "icon": {
1026
       "icon": {
1097
       },
1041
       },
1098
       "attrs": [],
1042
       "attrs": [],
1099
       "properties": {
1043
       "properties": {
1100
-        "order": 53,
1101
-        "id": 37,
1044
+        "order": 892,
1045
+        "id": 36,
1102
         "prevSize": 32,
1046
         "prevSize": 32,
1103
         "code": 58883,
1047
         "code": 58883,
1104
         "name": "presentation",
1048
         "name": "presentation",
1105
         "ligatures": ""
1049
         "ligatures": ""
1106
       },
1050
       },
1107
       "setIdx": 0,
1051
       "setIdx": 0,
1108
-      "setId": 1,
1109
-      "iconIdx": 37
1052
+      "setId": 5,
1053
+      "iconIdx": 36
1110
     },
1054
     },
1111
     {
1055
     {
1112
       "icon": {
1056
       "icon": {
1123
       },
1067
       },
1124
       "attrs": [],
1068
       "attrs": [],
1125
       "properties": {
1069
       "properties": {
1126
-        "order": 115,
1070
+        "order": 893,
1127
         "ligatures": "dialpad",
1071
         "ligatures": "dialpad",
1128
-        "id": 38,
1072
+        "id": 37,
1129
         "prevSize": 32,
1073
         "prevSize": 32,
1130
         "code": 59685,
1074
         "code": 59685,
1131
         "name": "dialpad"
1075
         "name": "dialpad"
1132
       },
1076
       },
1133
       "setIdx": 0,
1077
       "setIdx": 0,
1134
-      "setId": 1,
1135
-      "iconIdx": 38
1078
+      "setId": 5,
1079
+      "iconIdx": 37
1136
     },
1080
     },
1137
     {
1081
     {
1138
       "icon": {
1082
       "icon": {
1149
       },
1093
       },
1150
       "attrs": [],
1094
       "attrs": [],
1151
       "properties": {
1095
       "properties": {
1152
-        "order": 114,
1096
+        "order": 894,
1153
         "ligatures": "remove_red_eye, visibility",
1097
         "ligatures": "remove_red_eye, visibility",
1154
-        "id": 39,
1098
+        "id": 38,
1155
         "prevSize": 32,
1099
         "prevSize": 32,
1156
         "code": 59683,
1100
         "code": 59683,
1157
         "name": "visibility"
1101
         "name": "visibility"
1158
       },
1102
       },
1159
       "setIdx": 0,
1103
       "setIdx": 0,
1160
-      "setId": 1,
1161
-      "iconIdx": 39
1104
+      "setId": 5,
1105
+      "iconIdx": 38
1162
     },
1106
     },
1163
     {
1107
     {
1164
       "icon": {
1108
       "icon": {
1175
       },
1119
       },
1176
       "attrs": [],
1120
       "attrs": [],
1177
       "properties": {
1121
       "properties": {
1178
-        "order": 113,
1122
+        "order": 895,
1179
         "ligatures": "visibility_off",
1123
         "ligatures": "visibility_off",
1180
-        "id": 40,
1124
+        "id": 39,
1181
         "prevSize": 32,
1125
         "prevSize": 32,
1182
         "code": 59684,
1126
         "code": 59684,
1183
         "name": "visibility-off"
1127
         "name": "visibility-off"
1184
       },
1128
       },
1185
       "setIdx": 0,
1129
       "setIdx": 0,
1186
-      "setId": 1,
1187
-      "iconIdx": 40
1130
+      "setId": 5,
1131
+      "iconIdx": 39
1132
+    },
1133
+    {
1134
+      "icon": {
1135
+        "paths": [
1136
+          "M330.667 554.667c-0.427-14.933 6.4-29.44 17.92-39.253 32 6.827 61.867 20.053 88.747 39.253 0 29.013-23.893 52.907-53.333 52.907s-52.907-23.467-53.333-52.907zM586.667 554.667c26.88-18.773 56.747-32 88.747-38.827 11.52 9.813 18.347 24.32 17.92 38.827 0 29.867-23.893 53.76-53.333 53.76s-53.333-23.893-53.333-53.76v0zM512 384c-118.187-1.707-234.667 27.733-338.347 85.333l-2.987 42.667c0 52.48 12.373 104.107 35.84 151.040 101.12-15.36 203.093-23.040 305.493-23.040s204.373 7.68 305.493 23.040c23.467-46.933 35.84-98.56 35.84-151.040l-2.987-42.667c-103.68-57.6-220.16-87.040-338.347-85.333zM512 85.333c235.641 0 426.667 191.025 426.667 426.667s-191.025 426.667-426.667 426.667c-235.641 0-426.667-191.025-426.667-426.667s191.025-426.667 426.667-426.667z"
1137
+        ],
1138
+        "attrs": [
1139
+          {}
1140
+        ],
1141
+        "isMulticolor": false,
1142
+        "isMulticolor2": false,
1143
+        "tags": [
1144
+          "ninja"
1145
+        ],
1146
+        "grid": 24
1147
+      },
1148
+      "attrs": [
1149
+        {}
1150
+      ],
1151
+      "properties": {
1152
+        "order": 850,
1153
+        "id": 0,
1154
+        "name": "ninja",
1155
+        "prevSize": 32,
1156
+        "code": 59657
1157
+      },
1158
+      "setIdx": 1,
1159
+      "setId": 4,
1160
+      "iconIdx": 0
1161
+    },
1162
+    {
1163
+      "icon": {
1164
+        "paths": [
1165
+          "M282 460c62 120 162 220 282 282l94-94c12-12 30-16 44-10 48 16 100 24 152 24 24 0 42 18 42 42v150c0 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 44z"
1166
+        ],
1167
+        "attrs": [],
1168
+        "isMulticolor": false,
1169
+        "isMulticolor2": false,
1170
+        "tags": [
1171
+          "phone"
1172
+        ],
1173
+        "defaultCode": 57549,
1174
+        "grid": 24
1175
+      },
1176
+      "attrs": [],
1177
+      "properties": {
1178
+        "ligatures": "call, local_phone, phone",
1179
+        "id": 1,
1180
+        "order": 851,
1181
+        "prevSize": 32,
1182
+        "code": 57549,
1183
+        "name": "phone"
1184
+      },
1185
+      "setIdx": 1,
1186
+      "setId": 4,
1187
+      "iconIdx": 1
1188
+    },
1189
+    {
1190
+      "icon": {
1191
+        "paths": [
1192
+          "M810 554h-256v256h-84v-256h-256v-84h256v-256h84v256h256v84z"
1193
+        ],
1194
+        "attrs": [],
1195
+        "isMulticolor": false,
1196
+        "isMulticolor2": false,
1197
+        "tags": [
1198
+          "add"
1199
+        ],
1200
+        "defaultCode": 57669,
1201
+        "grid": 24
1202
+      },
1203
+      "attrs": [],
1204
+      "properties": {
1205
+        "ligatures": "add",
1206
+        "id": 12,
1207
+        "order": 896,
1208
+        "prevSize": 32,
1209
+        "code": 57669,
1210
+        "name": "add"
1211
+      },
1212
+      "setIdx": 3,
1213
+      "setId": 0,
1214
+      "iconIdx": 12
1188
     }
1215
     }
1189
   ],
1216
   ],
1190
   "height": 1024,
1217
   "height": 1024,

+ 8
- 1
interface_config.js 查看文件

35
         //main toolbar
35
         //main toolbar
36
         'microphone', 'camera', 'desktop', 'invite', 'fullscreen', 'fodeviceselection', 'hangup', // jshint ignore:line
36
         'microphone', 'camera', 'desktop', 'invite', 'fullscreen', 'fodeviceselection', 'hangup', // jshint ignore:line
37
         //extended toolbar
37
         //extended toolbar
38
-        'profile', 'contacts', 'chat', 'recording', 'etherpad', 'sharedvideo', 'dialout', 'settings', 'raisehand', 'filmstrip'], // jshint ignore:line
38
+        'profile', 'addtocall', 'contacts', 'chat', 'recording', 'etherpad', 'sharedvideo', 'dialout', 'settings', 'raisehand', 'filmstrip'], // jshint ignore:line
39
     /**
39
     /**
40
      * Main Toolbar Buttons
40
      * Main Toolbar Buttons
41
      * All of them should be in TOOLBAR_BUTTONS
41
      * All of them should be in TOOLBAR_BUTTONS
91
      * @type {boolean}
91
      * @type {boolean}
92
      */
92
      */
93
     MOBILE_APP_PROMO: true,
93
     MOBILE_APP_PROMO: true,
94
+
94
     /**
95
     /**
95
      * Maximum coeficient of the ratio of the large video to the visible area
96
      * Maximum coeficient of the ratio of the large video to the visible area
96
      * after the large video is scaled to fit the window.
97
      * after the large video is scaled to fit the window.
98
      * @type {number}
99
      * @type {number}
99
      */
100
      */
100
     MAXIMUM_ZOOMING_COEFFICIENT: 1.3
101
     MAXIMUM_ZOOMING_COEFFICIENT: 1.3
102
+
103
+    /*
104
+     * If indicated some of the error dialogs may point to the support URL for
105
+     * help.
106
+     */
107
+    // SUPPORT_URL: ""
101
 };
108
 };

+ 13
- 0
lang/main.json 查看文件

96
         "rejoinKeyTitle": "Rejoin"
96
         "rejoinKeyTitle": "Rejoin"
97
     },
97
     },
98
     "toolbar": {
98
     "toolbar": {
99
+        "addPeople": "Add people to your call",
99
         "audioonly": "Enable / Disable audio only mode (saves bandwidth)",
100
         "audioonly": "Enable / Disable audio only mode (saves bandwidth)",
100
         "mute": "Mute / Unmute",
101
         "mute": "Mute / Unmute",
101
         "videomute": "Start / Stop camera",
102
         "videomute": "Start / Stop camera",
456
         "statusMessage": "is now __status__",
457
         "statusMessage": "is now __status__",
457
         "enterPhone": "Enter phone number",
458
         "enterPhone": "Enter phone number",
458
         "phoneNotAllowed": "Oh, we don't support that destination yet! Sorry!"
459
         "phoneNotAllowed": "Oh, we don't support that destination yet! Sorry!"
460
+    },
461
+    "addPeople": {
462
+        "add": "Add",
463
+        "noResults": "No matching search results",
464
+        "searchPlaceholder": "Search for people and rooms to add",
465
+        "title": "Add people to your call"
466
+    },
467
+    "inlineDialogFailure": {
468
+        "msg": "We stumbled a bit.",
469
+        "retry": "Try again",
470
+        "support": "Support",
471
+        "supportMsg": "If this keeps happening, reach out to"
459
     }
472
     }
460
 }
473
 }

+ 10
- 5
package.json 查看文件

16
   "readmeFilename": "README.md",
16
   "readmeFilename": "README.md",
17
   "//": "Callstats.io does not work with recent versions of jsSHA (2.0.1 in particular)",
17
   "//": "Callstats.io does not work with recent versions of jsSHA (2.0.1 in particular)",
18
   "dependencies": {
18
   "dependencies": {
19
-    "@atlaskit/button": "1.0.3",
20
-    "@atlaskit/button-group": "1.0.0",
19
+    "@atlaskit/avatar": "4.0.5",
20
+    "@atlaskit/button": "3.0.0",
21
+    "@atlaskit/button-group": "1.1.3",
21
     "@atlaskit/dropdown-menu": "1.4.0",
22
     "@atlaskit/dropdown-menu": "1.4.0",
22
     "@atlaskit/field-text": "2.7.0",
23
     "@atlaskit/field-text": "2.7.0",
23
-    "@atlaskit/icon": "6.0.0",
24
-    "@atlaskit/modal-dialog": "1.2.4",
25
-    "@atlaskit/tabs": "1.2.5",
24
+    "@atlaskit/icon": "7.0.0",
25
+    "@atlaskit/inline-dialog": "3.2.0",
26
+    "@atlaskit/modal-dialog": "2.1.2",
27
+    "@atlaskit/multi-select": "6.2.0",
28
+    "@atlaskit/spinner": "2.2.3",
29
+    "@atlaskit/tabs": "2.0.0",
26
     "@atlassian/aui": "6.0.6",
30
     "@atlassian/aui": "6.0.6",
27
     "async": "0.9.0",
31
     "async": "0.9.0",
28
     "autosize": "1.18.13",
32
     "autosize": "1.18.13",
42
     "jwt-decode": "2.2.0",
46
     "jwt-decode": "2.2.0",
43
     "lib-jitsi-meet": "jitsi/lib-jitsi-meet",
47
     "lib-jitsi-meet": "jitsi/lib-jitsi-meet",
44
     "lodash": "4.17.4",
48
     "lodash": "4.17.4",
49
+    "nuclear-js": "1.4.0",
45
     "postis": "2.2.0",
50
     "postis": "2.2.0",
46
     "react": "15.4.2",
51
     "react": "15.4.2",
47
     "react-dom": "15.4.2",
52
     "react-dom": "15.4.2",

+ 5
- 2
react/features/base/dialog/components/StatelessDialog.web.js 查看文件

217
 
217
 
218
         return (
218
         return (
219
             <header>
219
             <header>
220
-                <h2>
220
+                <h3>
221
                     { this.props.titleString || t(this.props.titleKey) }
221
                     { this.props.titleString || t(this.props.titleKey) }
222
-                </h2>
222
+                </h3>
223
             </header>
223
             </header>
224
         );
224
         );
225
     }
225
     }
275
         }
275
         }
276
 
276
 
277
         if (event.key === 'Enter') {
277
         if (event.key === 'Enter') {
278
+            event.preventDefault();
279
+            event.stopPropagation();
280
+
278
             if (this.props.submitDisabled && !this.props.cancelDisabled) {
281
             if (this.props.submitDisabled && !this.props.cancelDisabled) {
279
                 this._onCancel();
282
                 this._onCancel();
280
             } else if (!this.props.okDisabled) {
283
             } else if (!this.props.okDisabled) {

+ 72
- 0
react/features/base/react/components/web/InlineDialogFailure.js 查看文件

1
+import AKButton from '@atlaskit/button';
2
+import React, { Component } from 'react';
3
+
4
+import { translate } from '../../../i18n';
5
+
6
+declare var interfaceConfig: Object;
7
+
8
+/**
9
+ * Inline dialog that represents a failure and allows a retry.
10
+ */
11
+class InlineDialogFailure extends Component {
12
+    /**
13
+     * {@code InlineDialogFailure}'s property types.
14
+     *
15
+     * @static
16
+     */
17
+    static propTypes = {
18
+        /**
19
+         * Allows to retry the call that previously didn't succeed.
20
+         */
21
+        onRetry: React.PropTypes.func,
22
+
23
+        /**
24
+         * Invoked to obtain translated strings.
25
+         */
26
+        t: React.PropTypes.func
27
+    };
28
+
29
+    /**
30
+     * Renders the content of this component.
31
+     *
32
+     * @returns {ReactElement}
33
+     */
34
+    render() {
35
+        const { t } = this.props;
36
+
37
+        const supportLink = interfaceConfig.SUPPORT_URL;
38
+        const supportLinkElem
39
+            = supportLink
40
+                ? ( // eslint-disable-line no-extra-parens
41
+                    <div className = 'inline-dialog-error-text'>
42
+                        <span>{ t('inlineDialogFailure.supportMsg') }</span>
43
+                        <span>
44
+                            <a
45
+                                href = { supportLink }
46
+                                rel = 'noopener noreferrer'
47
+                                target = '_blank'>
48
+                                { t('inlineDialogFailure.support') }
49
+                            </a>
50
+                        </span>
51
+                        <span>.</span>
52
+                    </div>
53
+                )
54
+                : null;
55
+
56
+        return (
57
+            <div className = 'inline-dialog-error'>
58
+                <div className = 'inline-dialog-error-text'>
59
+                    { t('inlineDialogFailure.msg') }
60
+                </div>
61
+                { supportLinkElem }
62
+                <AKButton
63
+                    className = 'inline-dialog-error-button'
64
+                    onClick = { this.props.onRetry } >
65
+                    { t('inlineDialogFailure.retry') }
66
+                </AKButton>
67
+            </div>
68
+        );
69
+    }
70
+}
71
+
72
+export default translate(InlineDialogFailure);

+ 319
- 0
react/features/base/react/components/web/MultiSelectAutocomplete.js 查看文件

1
+import { MultiSelectStateless } from '@atlaskit/multi-select';
2
+import AKInlineDialog from '@atlaskit/inline-dialog';
3
+import Spinner from '@atlaskit/spinner';
4
+import _debounce from 'lodash/debounce';
5
+import React, { Component } from 'react';
6
+
7
+import InlineDialogFailure from './InlineDialogFailure';
8
+
9
+/**
10
+ * A MultiSelect that is also auto-completing.
11
+ */
12
+class MultiSelectAutocomplete extends Component {
13
+
14
+    /**
15
+     * {@code MultiSelectAutocomplete} component's property types.
16
+     *
17
+     * @static
18
+     */
19
+    static propTypes = {
20
+        /**
21
+         * The default value of the selected item.
22
+         */
23
+        defaultValue: React.PropTypes.array,
24
+
25
+        /**
26
+         * Indicates if the component is disabled.
27
+         */
28
+        isDisabled: React.PropTypes.bool,
29
+
30
+        /**
31
+         * The text to show when no matches are found.
32
+         */
33
+        noMatchesFound: React.PropTypes.string,
34
+
35
+        /**
36
+         * The function called when the selection changes.
37
+         */
38
+        onSelectionChange: React.PropTypes.func,
39
+
40
+        /**
41
+         * The placeholder text of the input component.
42
+         */
43
+        placeholder: React.PropTypes.string,
44
+
45
+        /**
46
+         * The service providing the search.
47
+         */
48
+        resourceClient: React.PropTypes.shape({
49
+            makeQuery: React.PropTypes.func,
50
+            parseResults: React.PropTypes.func
51
+        }).isRequired,
52
+
53
+        /**
54
+         * Indicates if the component should fit the container.
55
+         */
56
+        shouldFitContainer: React.PropTypes.bool,
57
+
58
+        /**
59
+         * Indicates if we should focus.
60
+         */
61
+        shouldFocus: React.PropTypes.bool
62
+    };
63
+
64
+    /**
65
+     * Initializes a new {@code MultiSelectAutocomplete} instance.
66
+     *
67
+     * @param {Object} props - The read-only properties with which the new
68
+     * instance is to be initialized.
69
+     */
70
+    constructor(props) {
71
+        super(props);
72
+
73
+        const defaultValue = this.props.defaultValue || [];
74
+
75
+        this.state = {
76
+            /**
77
+             * Indicates if the dropdown is open.
78
+             */
79
+            isOpen: false,
80
+
81
+            /**
82
+             * The text that filters the query result of the search.
83
+             */
84
+            filterValue: '',
85
+
86
+            /**
87
+             * Indicates if the component is currently loading results.
88
+             */
89
+            loading: false,
90
+
91
+
92
+            /**
93
+             * Indicates if there was an error.
94
+             */
95
+            error: false,
96
+
97
+            /**
98
+             * The list of result items.
99
+             */
100
+            items: [],
101
+
102
+            /**
103
+             * The list of selected items.
104
+             */
105
+            selectedItems: [ ...defaultValue ]
106
+        };
107
+
108
+        this._onFilterChange = this._onFilterChange.bind(this);
109
+        this._onRetry = this._onRetry.bind(this);
110
+        this._onSelectionChange = this._onSelectionChange.bind(this);
111
+        this._sendQuery = _debounce(this._sendQuery.bind(this), 200);
112
+    }
113
+
114
+    /**
115
+     * Clears the selected items.
116
+     *
117
+     * @returns {void}
118
+     */
119
+    clear() {
120
+        this.setState({
121
+            selectedItems: []
122
+        });
123
+    }
124
+
125
+    /**
126
+     * Renders the content of this component.
127
+     *
128
+     * @returns {ReactElement}
129
+     */
130
+    render() {
131
+        const shouldFitContainer = this.props.shouldFitContainer || false;
132
+        const shouldFocus = this.props.shouldFocus || false;
133
+        const isDisabled = this.props.isDisabled || false;
134
+        const placeholder = this.props.placeholder || '';
135
+        const noMatchesFound = this.props.noMatchesFound || '';
136
+
137
+        return (
138
+            <div>
139
+                <MultiSelectStateless
140
+                    filterValue = { this.state.filterValue }
141
+                    isDisabled = { isDisabled }
142
+                    isOpen = { this.state.isOpen }
143
+                    items = { this.state.items }
144
+                    noMatchesFound = { noMatchesFound }
145
+                    onFilterChange = { this._onFilterChange }
146
+                    onRemoved = { this._onSelectionChange }
147
+                    onSelected = { this._onSelectionChange }
148
+                    placeholder = { placeholder }
149
+                    selectedItems = { this.state.selectedItems }
150
+                    shouldFitContainer = { shouldFitContainer }
151
+                    shouldFocus = { shouldFocus } />
152
+                { this._renderLoadingIndicator() }
153
+                { this._renderError() }
154
+            </div>
155
+        );
156
+    }
157
+
158
+    /**
159
+     * Sets the state and sends a query on filter change.
160
+     *
161
+     * @param {string} filterValue - The filter text value.
162
+     * @private
163
+     * @returns {void}
164
+     */
165
+    _onFilterChange(filterValue) {
166
+        this.setState({
167
+            // Clean the error if the filterValue is empty.
168
+            error: this.state.error && Boolean(filterValue),
169
+            filterValue,
170
+            isOpen: Boolean(this.state.items.length) && Boolean(filterValue),
171
+            items: filterValue ? this.state.items : []
172
+        });
173
+        if (filterValue) {
174
+            this._sendQuery(filterValue);
175
+        }
176
+    }
177
+
178
+    /**
179
+     * Retries the query on retry.
180
+     *
181
+     * @private
182
+     * @returns {void}
183
+     */
184
+    _onRetry() {
185
+        this._sendQuery(this.state.filterValue);
186
+    }
187
+
188
+    /**
189
+     * Updates the selected items when a selection event occurs.
190
+     *
191
+     * @param {Object} item - The selected item.
192
+     * @private
193
+     * @returns {void}
194
+     */
195
+    _onSelectionChange(item) {
196
+        const existing
197
+            = this.state.selectedItems.find(k => k.value === item.value);
198
+        let selectedItems = this.state.selectedItems;
199
+
200
+        if (existing) {
201
+            selectedItems = selectedItems.filter(k => k !== existing);
202
+        } else {
203
+            selectedItems.push(item);
204
+        }
205
+        this.setState({
206
+            isOpen: false,
207
+            selectedItems
208
+        });
209
+
210
+        if (this.props.onSelectionChange) {
211
+            this.props.onSelectionChange(selectedItems);
212
+        }
213
+    }
214
+
215
+    /**
216
+     * Renders the error UI.
217
+     *
218
+     * @returns {ReactElement|null}
219
+     */
220
+    _renderError() {
221
+        if (!this.state.error) {
222
+            return null;
223
+        }
224
+        const content = ( // eslint-disable-line no-extra-parens
225
+            <div className = 'autocomplete-error'>
226
+                <InlineDialogFailure
227
+                    onRetry = { this._onRetry } />
228
+            </div>
229
+        );
230
+
231
+        return (
232
+            <AKInlineDialog
233
+                content = { content }
234
+                isOpen = { true } />
235
+        );
236
+    }
237
+
238
+    /**
239
+     * Renders the loading indicator.
240
+     *
241
+     * @returns {ReactElement|null}
242
+     */
243
+    _renderLoadingIndicator() {
244
+        if (!(this.state.loading
245
+            && !this.state.items.length
246
+            && this.state.filterValue.length)) {
247
+            return null;
248
+        }
249
+
250
+        const content = ( // eslint-disable-line no-extra-parens
251
+            <div className = 'autocomplete-loading'>
252
+                <Spinner
253
+                    isCompleting = { false }
254
+                    size = 'medium' />
255
+            </div>
256
+        );
257
+
258
+        return (
259
+            <AKInlineDialog
260
+                content = { content }
261
+                isOpen = { true } />
262
+        );
263
+    }
264
+
265
+    /**
266
+     * Sends a query to the resourceClient.
267
+     *
268
+     * @param {string} filterValue - The string to use for the search.
269
+     * @returns {void}
270
+     */
271
+    _sendQuery(filterValue) {
272
+        if (!filterValue) {
273
+            return;
274
+        }
275
+
276
+        this.setState({
277
+            loading: true,
278
+            error: false
279
+        });
280
+
281
+        const resourceClient = this.props.resourceClient || {
282
+            makeQuery: () => Promise.resolve([]),
283
+            parseResults: results => results
284
+        };
285
+
286
+        resourceClient.makeQuery(filterValue)
287
+            .then(results => {
288
+                if (this.state.filterValue !== filterValue) {
289
+                    this.setState({
290
+                        loading: false,
291
+                        error: false
292
+                    });
293
+
294
+                    return;
295
+                }
296
+                const itemGroups = [
297
+                    {
298
+                        items: resourceClient.parseResults(results)
299
+                    }
300
+                ];
301
+
302
+                this.setState({
303
+                    items: itemGroups,
304
+                    isOpen: true,
305
+                    loading: false,
306
+                    error: false
307
+                });
308
+            })
309
+            .catch(() => {
310
+                this.setState({
311
+                    error: true,
312
+                    loading: false,
313
+                    isOpen: false
314
+                });
315
+            });
316
+    }
317
+}
318
+
319
+export default MultiSelectAutocomplete;

+ 1
- 0
react/features/base/react/components/web/index.js 查看文件

1
 export { default as Container } from './Container';
1
 export { default as Container } from './Container';
2
 export { default as Text } from './Text';
2
 export { default as Text } from './Text';
3
 export { default as Watermarks } from './Watermarks';
3
 export { default as Watermarks } from './Watermarks';
4
+export { default as MultiSelectAutocomplete } from './MultiSelectAutocomplete';

+ 3
- 3
react/features/device-selection/components/DeviceSelector.web.js 查看文件

4
 
4
 
5
 import { translate } from '../../base/i18n';
5
 import { translate } from '../../base/i18n';
6
 
6
 
7
-const EXPAND_ICON = <ExpandIcon label = 'expand' />;
8
-
9
 /**
7
 /**
10
  * React component for selecting a device from a select element. Wraps
8
  * React component for selecting a device from a select element. Wraps
11
  * AKDropdownMenu with device selection specific logic.
9
  * AKDropdownMenu with device selection specific logic.
117
                 <span className = 'device-selector-trigger-text'>
115
                 <span className = 'device-selector-trigger-text'>
118
                     { triggerText }
116
                     { triggerText }
119
                 </span>
117
                 </span>
120
-                { EXPAND_ICON }
118
+                <ExpandIcon
119
+                    label = 'expand'
120
+                    size = 'large' />
121
             </div>
121
             </div>
122
         );
122
         );
123
     }
123
     }

+ 2
- 2
react/features/dial-out/components/DialOutDialog.web.js 查看文件

109
     /**
109
     /**
110
      * Renders the dialog content.
110
      * Renders the dialog content.
111
      *
111
      *
112
-     * @returns {XML}
112
+     * @returns {ReactElement}
113
      * @private
113
      * @private
114
      */
114
      */
115
     _renderContent() {
115
     _renderContent() {
127
      * Renders the error message to display if the dial phone number is not
127
      * Renders the error message to display if the dial phone number is not
128
      * allowed.
128
      * allowed.
129
      *
129
      *
130
-     * @returns {XML}
130
+     * @returns {ReactElement}
131
      * @private
131
      * @private
132
      */
132
      */
133
     _renderErrorMessage() {
133
     _renderErrorMessage() {

+ 10
- 1
react/features/invite/actions.js 查看文件

4
     UPDATE_DIAL_IN_NUMBERS_FAILED,
4
     UPDATE_DIAL_IN_NUMBERS_FAILED,
5
     UPDATE_DIAL_IN_NUMBERS_SUCCESS
5
     UPDATE_DIAL_IN_NUMBERS_SUCCESS
6
 } from './actionTypes';
6
 } from './actionTypes';
7
-import { InviteDialog } from './components';
7
+import { AddPeopleDialog, InviteDialog } from './components';
8
 
8
 
9
 declare var $: Function;
9
 declare var $: Function;
10
 declare var APP: Object;
10
 declare var APP: Object;
18
     return openDialog(InviteDialog);
18
     return openDialog(InviteDialog);
19
 }
19
 }
20
 
20
 
21
+/**
22
+ * Opens the Add People Dialog.
23
+ *
24
+ * @returns {Function}
25
+ */
26
+export function openAddPeopleDialog() {
27
+    return openDialog(AddPeopleDialog);
28
+}
29
+
21
 /**
30
 /**
22
  * Sends AJAX requests for dial-in numbers and conference ID.
31
  * Sends AJAX requests for dial-in numbers and conference ID.
23
  *
32
  *

+ 3
- 0
react/features/invite/components/AddPeopleDialog.native.js 查看文件

1
+/**
2
+ * Created by ystamcheva on 8/6/17.
3
+ */

+ 259
- 0
react/features/invite/components/AddPeopleDialog.web.js 查看文件

1
+import React, { Component } from 'react';
2
+import { Immutable } from 'nuclear-js';
3
+import { connect } from 'react-redux';
4
+import Avatar from '@atlaskit/avatar';
5
+
6
+import { getInviteURL } from '../../base/connection';
7
+import { Dialog } from '../../base/dialog';
8
+import { translate } from '../../base/i18n';
9
+import MultiSelectAutocomplete
10
+    from '../../base/react/components/web/MultiSelectAutocomplete';
11
+
12
+import { invitePeople, searchPeople } from '../functions';
13
+
14
+/**
15
+ * The dialog that allows to invite people to the call.
16
+ */
17
+class AddPeopleDialog extends Component {
18
+    /**
19
+     * {@code AddPeopleDialog}'s property types.
20
+     *
21
+     * @static
22
+     */
23
+    static propTypes = {
24
+        /**
25
+         * The URL pointing to the service allowing for people invite.
26
+         */
27
+        _inviteServiceUrl: React.PropTypes.string,
28
+
29
+        /**
30
+         * The url of the conference to invite people to.
31
+         */
32
+        _inviteUrl: React.PropTypes.string,
33
+
34
+        /**
35
+         * The JWT token.
36
+         */
37
+        _jwt: React.PropTypes.string,
38
+
39
+        /**
40
+         * The URL pointing to the service allowing for people search.
41
+         */
42
+        _peopleSearchUrl: React.PropTypes.string,
43
+
44
+        /**
45
+         * Invoked to obtain translated strings.
46
+         */
47
+        t: React.PropTypes.func
48
+    };
49
+
50
+    /**
51
+     * Initializes a new {@code AddPeopleDialog} instance.
52
+     *
53
+     * @param {Object} props - The read-only properties with which the new
54
+     * instance is to be initialized.
55
+     */
56
+    constructor(props) {
57
+        super(props);
58
+
59
+        this.state = {
60
+            /**
61
+             * Indicating that an error occurred when adding people to the call.
62
+             */
63
+            addToCallError: false,
64
+
65
+            /**
66
+             * Indicating that we're currently adding the new people to the
67
+             * call.
68
+             */
69
+            addToCallInProgress: false,
70
+
71
+            /**
72
+             * The list of invite items.
73
+             */
74
+            inviteItems: new Immutable.List()
75
+        };
76
+
77
+        this._multiselect = null;
78
+        this._resourceClient = {
79
+            makeQuery: text => searchPeople(
80
+                this.props._peopleSearchUrl, this.props._jwt, text),
81
+            parseResults: response => response.map(user => {
82
+                const avatar = ( // eslint-disable-line no-extra-parens
83
+                    <Avatar
84
+                        size = 'medium'
85
+                        src = { user.avatar } />
86
+                );
87
+
88
+                return {
89
+                    content: user.name,
90
+                    value: user.id,
91
+                    elemBefore: avatar,
92
+                    item: user
93
+                };
94
+            })
95
+        };
96
+
97
+        this._isAddDisabled = this._isAddDisabled.bind(this);
98
+        this._onSelectionChange = this._onSelectionChange.bind(this);
99
+        this._onSubmit = this._onSubmit.bind(this);
100
+        this._setMultiSelectElement = this._setMultiSelectElement.bind(this);
101
+    }
102
+
103
+    /**
104
+     * React Component method that executes once component is updated.
105
+     *
106
+     * @param {Object} prevState - The state object before the update.
107
+     * @returns {void}
108
+     */
109
+    componentDidUpdate(prevState) {
110
+        /**
111
+         * Clears selected items from the multi select component on successful
112
+         * invite.
113
+         */
114
+        if (prevState.addToCallError
115
+            && !this.state.addToCallInProgress
116
+            && !this.state.addToCallError
117
+            && this._multiselect) {
118
+            this._multiselect.clear();
119
+        }
120
+    }
121
+
122
+    /**
123
+     * Renders the content of this component.
124
+     *
125
+     * @returns {ReactElement}
126
+     */
127
+    render() {
128
+        return (
129
+            <Dialog
130
+                okDisabled = { this._isAddDisabled() }
131
+                okTitleKey = 'addPeople.add'
132
+                onSubmit = { this._onSubmit }
133
+                titleKey = 'addPeople.title'
134
+                width = 'small'>
135
+                { this._getUserInputForm() }
136
+            </Dialog>
137
+        );
138
+    }
139
+
140
+    /**
141
+     * Renders the input form.
142
+     *
143
+     * @returns {ReactElement}
144
+     * @private
145
+     */
146
+    _getUserInputForm() {
147
+        const { t } = this.props;
148
+
149
+        return (
150
+            <div className = 'add-people-form-wrap'>
151
+                <MultiSelectAutocomplete
152
+                    isDisabled
153
+                        = { this.state.addToCallInProgress || false }
154
+                    noMatchesFound = { t('addPeople.noResults') }
155
+                    onSelectionChange = { this._onSelectionChange }
156
+                    placeholder = { t('addPeople.searchPlaceholder') }
157
+                    ref = { this._setMultiSelectElement }
158
+                    resourceClient = { this._resourceClient }
159
+                    shouldFitContainer = { true }
160
+                    shouldFocus = { true } />
161
+            </div>
162
+        );
163
+    }
164
+
165
+    /**
166
+     * Indicates if the Add button should be disabled.
167
+     *
168
+     * @returns {boolean} - True to indicate that the Add button should
169
+     * be disabled, false otherwise.
170
+     * @private
171
+     */
172
+    _isAddDisabled() {
173
+        return !this.state.inviteItems.length
174
+            || this.state.addToCallInProgress;
175
+    }
176
+
177
+    /**
178
+     * Handles a selection change.
179
+     *
180
+     * @param {Map} selectedItems - The list of selected items.
181
+     * @private
182
+     * @returns {void}
183
+     */
184
+    _onSelectionChange(selectedItems) {
185
+        const selectedIds = selectedItems.map(o => o.item);
186
+
187
+        this.setState({
188
+            inviteItems: selectedIds
189
+        });
190
+    }
191
+
192
+    /**
193
+     * Handles the submit button action.
194
+     *
195
+     * @private
196
+     * @returns {void}
197
+     */
198
+    _onSubmit() {
199
+        if (!this._isAddDisabled()) {
200
+            this.setState({
201
+                addToCallInProgress: true
202
+            });
203
+
204
+            invitePeople(
205
+                this.props._inviteServiceUrl,
206
+                this.props._inviteUrl,
207
+                this.props._jwt,
208
+                this.state.inviteItems)
209
+            .then(() => {
210
+                this.setState({
211
+                    addToCallInProgress: false
212
+                });
213
+            })
214
+            .catch(() => {
215
+                this.setState({
216
+                    addToCallInProgress: false,
217
+                    addToCallError: true
218
+                });
219
+            });
220
+        }
221
+    }
222
+
223
+    /**
224
+     * Sets the instance variable for the multi select component
225
+     * element so it can be accessed directly.
226
+     *
227
+     * @param {Object} element - The DOM element for the component's dialog.
228
+     * @private
229
+     * @returns {void}
230
+     */
231
+    _setMultiSelectElement(element) {
232
+        this._multiselect = element;
233
+    }
234
+}
235
+
236
+/**
237
+ * Maps (parts of) the Redux state to the associated
238
+ * {@code AddPeopleDialog}'s props.
239
+ *
240
+ * @param {Object} state - The Redux state.
241
+ * @private
242
+ * @returns {{
243
+ *     _peopleSearchUrl: React.PropTypes.string,
244
+ *     _jwt: React.PropTypes.string
245
+ * }}
246
+ */
247
+function _mapStateToProps(state) {
248
+    const { peopleSearchUrl, inviteServiceUrl } = state['features/base/config'];
249
+
250
+    return {
251
+        _jwt: state['features/jwt'].jwt,
252
+        _inviteUrl: getInviteURL(state),
253
+        _inviteServiceUrl: inviteServiceUrl,
254
+        _peopleSearchUrl: peopleSearchUrl
255
+    };
256
+}
257
+
258
+export default translate(
259
+    connect(_mapStateToProps)(AddPeopleDialog));

+ 1
- 0
react/features/invite/components/index.js 查看文件

1
 export { default as InviteDialog } from './InviteDialog';
1
 export { default as InviteDialog } from './InviteDialog';
2
+export { default as AddPeopleDialog } from './AddPeopleDialog';

+ 46
- 0
react/features/invite/functions.js 查看文件

1
+declare var $: Function;
2
+
3
+/**
4
+ * Sends an ajax request to a directory service.
5
+ *
6
+ * @param {string} serviceUrl - The service to query.
7
+ * @param {string} jwt - The jwt token to pass to the search service.
8
+ * @param {string} text - Text to search.
9
+ * @returns {Promise} - The promise created by the request.
10
+ */
11
+export function searchPeople(serviceUrl, jwt, text) {
12
+    const queryTypes = '["conferenceRooms","user","room"]';
13
+
14
+    return new Promise((resolve, reject) => {
15
+        $.getJSON(`${serviceUrl}?query=${encodeURIComponent(text)}
16
+            &queryTypes=${queryTypes}&jwt=${jwt}`,
17
+        response => resolve(response)
18
+        ).fail((jqxhr, textStatus, error) =>
19
+            reject(error)
20
+        );
21
+    });
22
+}
23
+
24
+/**
25
+ * Sends a post request to an invite service.
26
+ *
27
+ * @param {string} inviteServiceUrl - The invite service that generates the
28
+ * invitation.
29
+ * @param {string} inviteUrl - The url to the conference.
30
+ * @param {string} jwt - The jwt token to pass to the search service.
31
+ * @param {Immutable.List} inviteItems - The list of items to invite.
32
+ * @returns {Promise} - The promise created by the request.
33
+ */
34
+export function invitePeople(inviteServiceUrl, inviteUrl, jwt, inviteItems) { // eslint-disable-line max-params, max-len
35
+    return new Promise((resolve, reject) => {
36
+        $.post(`${inviteServiceUrl}?token=${jwt}`,
37
+            JSON.stringify({
38
+                'invited': inviteItems,
39
+                'url': inviteUrl }),
40
+            response => resolve(response),
41
+            'json')
42
+            .fail((jqxhr, textStatus, error) =>
43
+                reject(error)
44
+            );
45
+    });
46
+}

+ 1
- 0
react/features/jwt/middleware.js 查看文件

180
         if (jwtPayload) {
180
         if (jwtPayload) {
181
             const { context, iss } = jwtPayload;
181
             const { context, iss } = jwtPayload;
182
 
182
 
183
+            action.jwt = jwt;
183
             action.issuer = iss;
184
             action.issuer = iss;
184
             if (context) {
185
             if (context) {
185
                 action.callee = context.callee;
186
                 action.callee = context.callee;

+ 14
- 1
react/features/toolbox/defaultToolbarButtons.js 查看文件

4
 
4
 
5
 import { openDeviceSelectionDialog } from '../device-selection';
5
 import { openDeviceSelectionDialog } from '../device-selection';
6
 import { openDialOutDialog } from '../dial-out';
6
 import { openDialOutDialog } from '../dial-out';
7
-import { openInviteDialog } from '../invite';
7
+import { openAddPeopleDialog, openInviteDialog } from '../invite';
8
 import UIEvents from '../../../service/UI/UIEvents';
8
 import UIEvents from '../../../service/UI/UIEvents';
9
 
9
 
10
 declare var APP: Object;
10
 declare var APP: Object;
15
  * All toolbar buttons' descriptors.
15
  * All toolbar buttons' descriptors.
16
  */
16
  */
17
 const buttons: Object = {
17
 const buttons: Object = {
18
+    addtocall: {
19
+        classNames: [ 'button', 'icon-add' ],
20
+        enabled: true,
21
+        id: 'toolbar_button_add',
22
+        isDisplayed: () => !APP.store.getState()['features/jwt'].isGuest,
23
+        onClick() {
24
+            JitsiMeetJS.analytics.sendEvent('toolbar.add.clicked');
25
+
26
+            return openAddPeopleDialog();
27
+        },
28
+        tooltipKey: 'toolbar.addPeople'
29
+    },
30
+
18
     /**
31
     /**
19
      * The descriptor of the camera toolbar button.
32
      * The descriptor of the camera toolbar button.
20
      */
33
      */

正在加载...
取消
保存