Ver código fonte

feat(connection-indicator): implement automatic hiding on good connection (#2009)

* ref(connection-stats): use PropTypes package

* feat(connection-stats): display a summary of the connection quality

* feat(connection-indicator): show empty bars for interrupted connection

* feat(connection-indicator): change background color based on status

* feat(connection-indicator): implement automatic hiding on good connection

* fix(connection-indicator): explicitly set font size

Currently non-react code will set an icon size on ConnectionIndicator.
This doesn't work on initial call join in vertical filmstrip after
some changes to support hiding the indicator. The chosen fix is
passing in the icon size to mirror what would happe with full
filmstrip reactification.

* ref(connection-stats): rename statuses

* feat(connection-indicator): make hiding behavior configurable

The original implementation made the auto hiding of the indicator
configured in interfaceConfig.

* fix(connection-indicator): readd class expected by torture tests

* fix(connection-indicator): change connection quality display styling

Bold the connection summary in the stats popover so it stands out.
Change the summaries so there are only three--strong, nonoptimal,
poor.

* fix(connection-indicator): gray background on lost connection

* feat(icons): add new gsm bars icon

* feat(connection-indicator): use new 3-bar icon

* ref(icons): remove icon-connection and icon-connection-lost

Both have been replaced by icon-gsm-bars so they are not
being referenced anymore. Mobile looks to have connect-lost
as a separate icon in font-icons/jitsi.json.
j8
virtuacoplenny 7 anos atrás
pai
commit
483e2ee202

+ 5
- 0
css/_connection-info.scss Ver arquivo

@@ -37,6 +37,11 @@
37 37
         color: $downloadConnectionIconColor;
38 38
     }
39 39
 
40
+    &__status
41
+    {
42
+        font-weight: bold;
43
+    }
44
+
40 45
     &__upload
41 46
     {
42 47
         @extend .connection-info__icon;

+ 3
- 6
css/_font.scss Ver arquivo

@@ -127,12 +127,6 @@
127 127
 .icon-volume:before {
128 128
     content: "\e91a";
129 129
 }
130
-.icon-connection-lost:before {
131
-    content: "\e900";
132
-}
133
-.icon-connection:before {
134
-    content: "\e61a";
135
-}
136 130
 .icon-recDisable:before {
137 131
     content: "\e613";
138 132
 }
@@ -160,3 +154,6 @@
160 154
 .icon-info:before {
161 155
     content: "\e922";
162 156
 }
157
+.icon-gsm-bars:before {
158
+    content: "\e926";
159
+}

+ 29
- 20
css/_videolayout_default.scss Ver arquivo

@@ -87,6 +87,7 @@
87 87
          * positioning depends on the trigger (indicator icon).
88 88
          */
89 89
         .indicator {
90
+            margin-left: 5px;
90 91
             margin-top: $toolbarIconMargin;
91 92
         }
92 93
 
@@ -94,16 +95,6 @@
94 95
             margin-left: $toolbarIconMargin;
95 96
         }
96 97
 
97
-        .connection-indicator,
98
-        div.indicator-container,
99
-         {
100
-            margin-right: 4px;
101
-        }
102
-
103
-        div.indicator:last-child {
104
-            margin-right: 0;
105
-        }
106
-
107 98
         .indicator-container {
108 99
             display: inline-block;
109 100
             vertical-align: top;
@@ -138,18 +129,13 @@
138 129
                 left: 0;
139 130
                 @include transform(translate(0, -50%));
140 131
 
141
-                &_empty
132
+                &_empty,
133
+                &_lost
142 134
                 {
143 135
                     color: #8B8B8B;/*#FFFFFF*/
144 136
                     overflow: hidden;
145 137
                 }
146 138
 
147
-                &_lost
148
-                {
149
-                    color: #8B8B8B;
150
-                    overflow: visible;
151
-                }
152
-
153 139
                 &_full
154 140
                 {
155 141
                     @include topLeft();
@@ -163,12 +149,15 @@
163 149
                 }
164 150
             }
165 151
 
166
-            .icon-connection,
167
-            .icon-connection-lost {
152
+            .icon-gsm-bars {
168 153
                 cursor: pointer;
169 154
                 font-size: 1em;
170 155
             }
171 156
         }
157
+
158
+        .hide-connection-indicator {
159
+            display: none;
160
+        }
172 161
     }
173 162
 
174 163
     &__hoverOverlay {
@@ -355,7 +344,27 @@
355 344
 }
356 345
 
357 346
 .connection-indicator {
358
-  background: $connectionIndicatorBg;
347
+    background: $connectionIndicatorBg;
348
+
349
+    &.status-high {
350
+        background: green;
351
+    }
352
+
353
+    &.status-med {
354
+        background: #FFD740;
355
+    }
356
+
357
+    &.status-lost {
358
+        background: gray;
359
+    }
360
+
361
+    &.status-low {
362
+        background: #BF2117;
363
+    }
364
+
365
+    &.status-other {
366
+        background: $connectionIndicatorBg;
367
+    }
359 368
 }
360 369
 
361 370
 .remote-video-menu-trigger,

BIN
fonts/jitsi.eot Ver arquivo


+ 1
- 2
fonts/jitsi.svg Ver arquivo

@@ -13,8 +13,6 @@
13 13
 <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" />
14 14
 <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" />
15 15
 <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" />
16
-<glyph unicode="&#xe61a;" glyph-name="connection" horiz-adv-x="1444" d="M3.881 210.835h220.26v-210.835h-220.26v210.835zM308.817 414.143h220.27v-414.143h-220.27v414.143zM613.764 617.412h220.268v-617.412h-220.268v617.412zM918.685 820.715h220.265v-820.715h-220.265v820.715zM1223.629 1024h220.263v-1024h-220.263v1024z" />
17
-<glyph unicode="&#xe900;" glyph-name="connection-lost" horiz-adv-x="1414" d="M0 299.153h196.337v-187.951h-196.337v187.951zM271.842 480.372h196.337v-369.169h-196.337v369.169zM543.656 661.562h196.337v-550.36h-196.337v550.36zM815.47 842.766v-731.564h119.56c-14.589 33.025-23.125 71.503-23.232 111.943 0.132 86.42 38.697 163.851 99.656 216.468l0.348 403.153h-196.332zM1087.292 1024v-533.672c28.874 10.572 62.222 16.73 97.009 16.825 35.717-0.129 69.823-6.614 101.322-18.371l-1.999 535.218h-196.332zM1192.868 439.852c-0.009 0-0.020 0-0.031 0-122.247 0-221.351-98.447-221.372-219.896 0-0.007 0-0.014 0-0.021 0-121.467 99.111-219.935 221.372-219.935 0.011 0 0.021 0 0.032 0 122.248 0.014 221.345 98.477 221.345 219.935 0 0.007 0 0.013 0 0.020-0.021 121.441-99.11 219.883-221.345 219.897zM1194.706 372.607c87.601-0.006 158.614-69.787 158.614-155.866 0-0.006 0-0.012 0-0.019-0.022-86.062-71.026-155.822-158.614-155.828-87.588 0.006-158.593 69.766-158.615 155.826 0 0.007 0 0.014 0 0.020 0 86.079 71.013 155.86 158.613 155.866zM1286.795 355.682l48.348-52.528-236.375-217.567-48.348 52.528 236.375 217.567z" />
18 16
 <glyph unicode="&#xe901;" glyph-name="avatar" d="M512 204c106 0 200 56 256 138-2 84-172 132-256 132-86 0-254-48-256-132 56-82 150-138 256-138zM512 810c-70 0-128-58-128-128s58-128 128-128 128 58 128 128-58 128-128 128zM512 938c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426z" />
19 17
 <glyph unicode="&#xe902;" glyph-name="download" d="M726 470h-128v170h-172v-170h-128l214-214zM826 596c110-8 198-100 198-212 0-118-96-214-214-214h-554c-142 0-256 114-256 256 0 132 100 240 228 254 54 102 160 174 284 174 156 0 284-110 314-258z" />
20 18
 <glyph unicode="&#xe903;" glyph-name="mic-camera-combined" d="M756.704 628.138l267.296 202.213v-635.075l-267.296 202.213v-191.923c0-12.085-11.296-21.863-25.216-21.863h-706.272c-13.92 0-25.216 9.777-25.216 21.863v612.25c0 12.085 11.296 21.863 25.216 21.863h706.272c13.92 0 25.216-9.777 25.216-21.863v-189.679zM371.338 376.228c47.817 0 86.529 40.232 86.529 89.811v184.835c0 49.651-38.713 89.883-86.529 89.883-47.788 0-86.515-40.232-86.515-89.883v-184.835c0-49.579 38.756-89.811 86.515-89.811v0zM356.754 314.070v-32.78h33.718v33.412c73.858 9.606 131.235 73.73 131.235 151.351v88.232h-30.636v-88.232c0-67.57-53.696-122.534-119.734-122.534-66.024 0-119.691 54.964-119.691 122.534v88.232h-30.636v-88.232c0-79.215 59.674-144.502 135.744-151.969v-0.014z" />
@@ -52,4 +50,5 @@
52 50
 <glyph unicode="&#xe923;" glyph-name="visibility" d="M512 640c70 0 128-58 128-128s-58-128-128-128-128 58-128 128 58 128 128 128zM512 298c118 0 214 96 214 214s-96 214-214 214-214-96-214-214 96-214 214-214zM512 832c214 0 396-132 470-320-74-188-256-320-470-320s-396 132-470 320c74 188 256 320 470 320z" />
53 51
 <glyph unicode="&#xe924;" glyph-name="visibility-off" d="M506 640h6c70 0 128-58 128-128v-8zM322 606c-14-28-24-60-24-94 0-118 96-214 214-214 34 0 66 10 94 24l-66 66c-8-2-18-4-28-4-70 0-128 58-128 128 0 10 2 20 4 28zM86 842l54 54 756-756-54-54c-47.968 47.365-96.266 94.401-144 142-58-24-120-36-186-36-214 0-396 132-470 320 34 84 90 156 160 212-39.017 38.983-77.307 78.693-116 118zM512 726c-28 0-54-6-78-16l-92 92c52 20 110 30 170 30 214 0 394-132 468-320-32-80-82-148-146-202l-124 124c10 24 16 50 16 78 0 118-96 214-214 214z" />
54 52
 <glyph unicode="&#xe925;" glyph-name="dialpad" d="M512 982c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM512 726c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM768 726c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM768 470c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM512 470c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM768 810c-46 0-86 40-86 86s40 86 86 86 86-40 86-86-40-86-86-86zM256 470c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM256 726c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM256 982c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM512 214c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86z" />
53
+<glyph unicode="&#xe926;" glyph-name="gsm-bars-black" d="M896 1024c70.692 0 128-57.308 128-128v-768c0-70.692-57.308-128-128-128s-128 57.308-128 128v768c0 70.692 57.308 128 128 128zM512 768c70.692 0 128-57.308 128-128v-512c0-70.692-57.308-128-128-128s-128 57.308-128 128v512c0 70.692 57.308 128 128 128zM128 384v0c70.692 0 128-57.308 128-128v-128c0-70.692-57.308-128-128-128s-128 57.308-128 128v128c0 70.692 57.308 128 128 128v0z" />
55 54
 </font></defs></svg>

BIN
fonts/jitsi.ttf Ver arquivo


BIN
fonts/jitsi.woff Ver arquivo


+ 71
- 163
fonts/selection.json Ver arquivo

@@ -1,6 +1,35 @@
1 1
 {
2 2
   "IcoMoonType": "selection",
3 3
   "icons": [
4
+    {
5
+      "icon": {
6
+        "paths": [
7
+          "M896 0c70.692 0 128 57.308 128 128v768c0 70.692-57.308 128-128 128s-128-57.308-128-128v-768c0-70.692 57.308-128 128-128zM512 256c70.692 0 128 57.308 128 128v512c0 70.692-57.308 128-128 128s-128-57.308-128-128v-512c0-70.692 57.308-128 128-128zM128 640v0c70.692 0 128 57.308 128 128v128c0 70.692-57.308 128-128 128s-128-57.308-128-128v-128c0-70.692 57.308-128 128-128v0z"
8
+        ],
9
+        "attrs": [
10
+          {}
11
+        ],
12
+        "isMulticolor": false,
13
+        "isMulticolor2": false,
14
+        "grid": 0,
15
+        "tags": [
16
+          "gsm-bars-black"
17
+        ]
18
+      },
19
+      "attrs": [
20
+        {}
21
+      ],
22
+      "properties": {
23
+        "order": 901,
24
+        "id": 0,
25
+        "name": "gsm-bars-black",
26
+        "prevSize": 32,
27
+        "code": 59686
28
+      },
29
+      "setIdx": 0,
30
+      "setId": 1,
31
+      "iconIdx": 0
32
+    },
4 33
     {
5 34
       "icon": {
6 35
         "paths": [
@@ -28,7 +57,7 @@
28 57
       },
29 58
       "setIdx": 0,
30 59
       "setId": 1,
31
-      "iconIdx": 0
60
+      "iconIdx": 1
32 61
     },
33 62
     {
34 63
       "icon": {
@@ -57,7 +86,7 @@
57 86
       },
58 87
       "setIdx": 0,
59 88
       "setId": 1,
60
-      "iconIdx": 1
89
+      "iconIdx": 2
61 90
     },
62 91
     {
63 92
       "icon": {
@@ -86,7 +115,7 @@
86 115
       },
87 116
       "setIdx": 0,
88 117
       "setId": 1,
89
-      "iconIdx": 2
118
+      "iconIdx": 3
90 119
     },
91 120
     {
92 121
       "icon": {
@@ -115,7 +144,7 @@
115 144
       },
116 145
       "setIdx": 0,
117 146
       "setId": 1,
118
-      "iconIdx": 3
147
+      "iconIdx": 4
119 148
     },
120 149
     {
121 150
       "icon": {
@@ -141,7 +170,7 @@
141 170
       },
142 171
       "setIdx": 0,
143 172
       "setId": 1,
144
-      "iconIdx": 4
173
+      "iconIdx": 5
145 174
     },
146 175
     {
147 176
       "icon": {
@@ -167,7 +196,7 @@
167 196
       },
168 197
       "setIdx": 0,
169 198
       "setId": 1,
170
-      "iconIdx": 5
199
+      "iconIdx": 6
171 200
     },
172 201
     {
173 202
       "icon": {
@@ -193,7 +222,7 @@
193 222
       },
194 223
       "setIdx": 0,
195 224
       "setId": 1,
196
-      "iconIdx": 6
225
+      "iconIdx": 7
197 226
     },
198 227
     {
199 228
       "icon": {
@@ -219,7 +248,7 @@
219 248
       },
220 249
       "setIdx": 0,
221 250
       "setId": 1,
222
-      "iconIdx": 7
251
+      "iconIdx": 8
223 252
     },
224 253
     {
225 254
       "icon": {
@@ -245,7 +274,7 @@
245 274
       },
246 275
       "setIdx": 0,
247 276
       "setId": 1,
248
-      "iconIdx": 8
277
+      "iconIdx": 9
249 278
     },
250 279
     {
251 280
       "icon": {
@@ -271,7 +300,7 @@
271 300
       },
272 301
       "setIdx": 0,
273 302
       "setId": 1,
274
-      "iconIdx": 9
303
+      "iconIdx": 10
275 304
     },
276 305
     {
277 306
       "icon": {
@@ -297,7 +326,7 @@
297 326
       },
298 327
       "setIdx": 0,
299 328
       "setId": 1,
300
-      "iconIdx": 10
329
+      "iconIdx": 11
301 330
     },
302 331
     {
303 332
       "icon": {
@@ -323,7 +352,7 @@
323 352
       },
324 353
       "setIdx": 0,
325 354
       "setId": 1,
326
-      "iconIdx": 11
355
+      "iconIdx": 12
327 356
     },
328 357
     {
329 358
       "icon": {
@@ -349,7 +378,7 @@
349 378
       },
350 379
       "setIdx": 0,
351 380
       "setId": 1,
352
-      "iconIdx": 12
381
+      "iconIdx": 13
353 382
     },
354 383
     {
355 384
       "icon": {
@@ -375,7 +404,7 @@
375 404
       },
376 405
       "setIdx": 0,
377 406
       "setId": 1,
378
-      "iconIdx": 13
407
+      "iconIdx": 14
379 408
     },
380 409
     {
381 410
       "icon": {
@@ -401,7 +430,7 @@
401 430
       },
402 431
       "setIdx": 0,
403 432
       "setId": 1,
404
-      "iconIdx": 14
433
+      "iconIdx": 15
405 434
     },
406 435
     {
407 436
       "icon": {
@@ -427,7 +456,7 @@
427 456
       },
428 457
       "setIdx": 0,
429 458
       "setId": 1,
430
-      "iconIdx": 15
459
+      "iconIdx": 16
431 460
     },
432 461
     {
433 462
       "icon": {
@@ -453,7 +482,7 @@
453 482
       },
454 483
       "setIdx": 0,
455 484
       "setId": 1,
456
-      "iconIdx": 16
485
+      "iconIdx": 17
457 486
     },
458 487
     {
459 488
       "icon": {
@@ -479,7 +508,7 @@
479 508
       },
480 509
       "setIdx": 0,
481 510
       "setId": 1,
482
-      "iconIdx": 17
511
+      "iconIdx": 18
483 512
     },
484 513
     {
485 514
       "icon": {
@@ -505,7 +534,7 @@
505 534
       },
506 535
       "setIdx": 0,
507 536
       "setId": 1,
508
-      "iconIdx": 18
537
+      "iconIdx": 19
509 538
     },
510 539
     {
511 540
       "icon": {
@@ -531,7 +560,7 @@
531 560
       },
532 561
       "setIdx": 0,
533 562
       "setId": 1,
534
-      "iconIdx": 19
563
+      "iconIdx": 20
535 564
     },
536 565
     {
537 566
       "icon": {
@@ -557,7 +586,7 @@
557 586
       },
558 587
       "setIdx": 0,
559 588
       "setId": 1,
560
-      "iconIdx": 20
589
+      "iconIdx": 21
561 590
     },
562 591
     {
563 592
       "icon": {
@@ -583,7 +612,7 @@
583 612
       },
584 613
       "setIdx": 0,
585 614
       "setId": 1,
586
-      "iconIdx": 21
615
+      "iconIdx": 22
587 616
     },
588 617
     {
589 618
       "icon": {
@@ -609,7 +638,7 @@
609 638
       },
610 639
       "setIdx": 0,
611 640
       "setId": 1,
612
-      "iconIdx": 22
641
+      "iconIdx": 23
613 642
     },
614 643
     {
615 644
       "icon": {
@@ -635,7 +664,7 @@
635 664
       },
636 665
       "setIdx": 0,
637 666
       "setId": 1,
638
-      "iconIdx": 23
667
+      "iconIdx": 24
639 668
     },
640 669
     {
641 670
       "icon": {
@@ -661,7 +690,7 @@
661 690
       },
662 691
       "setIdx": 0,
663 692
       "setId": 1,
664
-      "iconIdx": 24
693
+      "iconIdx": 25
665 694
     },
666 695
     {
667 696
       "icon": {
@@ -687,7 +716,7 @@
687 716
       },
688 717
       "setIdx": 0,
689 718
       "setId": 1,
690
-      "iconIdx": 25
719
+      "iconIdx": 26
691 720
     },
692 721
     {
693 722
       "icon": {
@@ -713,7 +742,7 @@
713 742
       },
714 743
       "setIdx": 0,
715 744
       "setId": 1,
716
-      "iconIdx": 26
745
+      "iconIdx": 27
717 746
     },
718 747
     {
719 748
       "icon": {
@@ -739,7 +768,7 @@
739 768
       },
740 769
       "setIdx": 0,
741 770
       "setId": 1,
742
-      "iconIdx": 27
771
+      "iconIdx": 28
743 772
     },
744 773
     {
745 774
       "icon": {
@@ -765,7 +794,7 @@
765 794
       },
766 795
       "setIdx": 0,
767 796
       "setId": 1,
768
-      "iconIdx": 28
797
+      "iconIdx": 29
769 798
     },
770 799
     {
771 800
       "icon": {
@@ -791,7 +820,7 @@
791 820
       },
792 821
       "setIdx": 0,
793 822
       "setId": 1,
794
-      "iconIdx": 29
823
+      "iconIdx": 30
795 824
     },
796 825
     {
797 826
       "icon": {
@@ -817,7 +846,7 @@
817 846
       },
818 847
       "setIdx": 0,
819 848
       "setId": 1,
820
-      "iconIdx": 30
849
+      "iconIdx": 31
821 850
     },
822 851
     {
823 852
       "icon": {
@@ -843,7 +872,7 @@
843 872
       },
844 873
       "setIdx": 0,
845 874
       "setId": 1,
846
-      "iconIdx": 31
875
+      "iconIdx": 32
847 876
     },
848 877
     {
849 878
       "icon": {
@@ -869,129 +898,8 @@
869 898
       },
870 899
       "setIdx": 0,
871 900
       "setId": 1,
872
-      "iconIdx": 32
873
-    },
874
-    {
875
-      "icon": {
876
-        "paths": [
877
-          "M-0 724.847h196.337v187.951h-196.337v-187.951z",
878
-          "M271.842 543.628h196.337v369.169h-196.337v-369.169z",
879
-          "M543.656 362.438h196.337v550.36h-196.337v-550.36z",
880
-          "M815.47 181.234v731.564h119.56c-14.589-33.025-23.125-71.503-23.232-111.943 0.132-86.42 38.697-163.851 99.656-216.468l0.348-403.153h-196.332z",
881
-          "M1087.292-0v533.672c28.874-10.572 62.222-16.73 97.009-16.825 35.717 0.129 69.823 6.614 101.322 18.371l-1.999-535.218h-196.332z",
882
-          "M1192.868 584.148c-0.009-0-0.020-0-0.031-0-122.247 0-221.351 98.447-221.372 219.896-0 0.007-0 0.014-0 0.021 0 121.467 99.111 219.935 221.372 219.935 0.011 0 0.021-0 0.032-0 122.248-0.014 221.345-98.477 221.345-219.935 0-0.007-0-0.013-0-0.020-0.021-121.441-99.11-219.883-221.345-219.897zM1194.706 651.393c87.601 0.006 158.614 69.787 158.614 155.866 0 0.006-0 0.012-0 0.019-0.022 86.062-71.026 155.822-158.614 155.828-87.588-0.006-158.593-69.766-158.615-155.826-0-0.007-0-0.014-0-0.020 0-86.079 71.013-155.86 158.613-155.866z",
883
-          "M1286.795 668.318l48.348 52.528-236.375 217.567-48.348-52.528 236.375-217.567z"
884
-        ],
885
-        "width": 1414,
886
-        "attrs": [
887
-          {},
888
-          {},
889
-          {},
890
-          {},
891
-          {},
892
-          {},
893
-          {}
894
-        ],
895
-        "isMulticolor": false,
896
-        "isMulticolor2": false,
897
-        "tags": [
898
-          "connection-lost"
899
-        ],
900
-        "grid": 0
901
-      },
902
-      "attrs": [
903
-        {},
904
-        {},
905
-        {},
906
-        {},
907
-        {},
908
-        {},
909
-        {}
910
-      ],
911
-      "properties": {
912
-        "order": 888,
913
-        "id": 32,
914
-        "name": "connection-lost",
915
-        "prevSize": 32,
916
-        "code": 59648
917
-      },
918
-      "setIdx": 0,
919
-      "setId": 1,
920 901
       "iconIdx": 33
921 902
     },
922
-    {
923
-      "icon": {
924
-        "paths": [
925
-          "M3.881 813.165h220.26v210.835h-220.26v-210.835z",
926
-          "M308.817 609.857h220.27v414.143h-220.27v-414.143z",
927
-          "M613.764 406.588h220.268v617.412h-220.268v-617.412z",
928
-          "M918.685 203.285h220.265v820.715h-220.265v-820.715z",
929
-          "M1223.629 0h220.263v1024h-220.263v-1024z"
930
-        ],
931
-        "width": 1444,
932
-        "attrs": [
933
-          {
934
-            "opacity": 1,
935
-            "visibility": false
936
-          },
937
-          {
938
-            "opacity": 1,
939
-            "visibility": false
940
-          },
941
-          {
942
-            "opacity": 1,
943
-            "visibility": false
944
-          },
945
-          {
946
-            "opacity": 1,
947
-            "visibility": false
948
-          },
949
-          {
950
-            "opacity": 1,
951
-            "visibility": false
952
-          }
953
-        ],
954
-        "isMulticolor": false,
955
-        "isMulticolor2": false,
956
-        "tags": [
957
-          "connection-2"
958
-        ],
959
-        "grid": 0
960
-      },
961
-      "attrs": [
962
-        {
963
-          "opacity": 1,
964
-          "visibility": false
965
-        },
966
-        {
967
-          "opacity": 1,
968
-          "visibility": false
969
-        },
970
-        {
971
-          "opacity": 1,
972
-          "visibility": false
973
-        },
974
-        {
975
-          "opacity": 1,
976
-          "visibility": false
977
-        },
978
-        {
979
-          "opacity": 1,
980
-          "visibility": false
981
-        }
982
-      ],
983
-      "properties": {
984
-        "order": 889,
985
-        "id": 33,
986
-        "prevSize": 32,
987
-        "code": 58906,
988
-        "name": "connection",
989
-        "ligatures": ""
990
-      },
991
-      "setIdx": 0,
992
-      "setId": 1,
993
-      "iconIdx": 34
994
-    },
995 903
     {
996 904
       "icon": {
997 905
         "paths": [
@@ -1019,7 +927,7 @@
1019 927
       },
1020 928
       "setIdx": 0,
1021 929
       "setId": 1,
1022
-      "iconIdx": 35
930
+      "iconIdx": 36
1023 931
     },
1024 932
     {
1025 933
       "icon": {
@@ -1049,7 +957,7 @@
1049 957
       },
1050 958
       "setIdx": 0,
1051 959
       "setId": 1,
1052
-      "iconIdx": 36
960
+      "iconIdx": 37
1053 961
     },
1054 962
     {
1055 963
       "icon": {
@@ -1079,7 +987,7 @@
1079 987
       },
1080 988
       "setIdx": 0,
1081 989
       "setId": 1,
1082
-      "iconIdx": 37
990
+      "iconIdx": 38
1083 991
     },
1084 992
     {
1085 993
       "icon": {
@@ -1105,7 +1013,7 @@
1105 1013
       },
1106 1014
       "setIdx": 0,
1107 1015
       "setId": 1,
1108
-      "iconIdx": 38
1016
+      "iconIdx": 39
1109 1017
     },
1110 1018
     {
1111 1019
       "icon": {
@@ -1131,7 +1039,7 @@
1131 1039
       },
1132 1040
       "setIdx": 0,
1133 1041
       "setId": 1,
1134
-      "iconIdx": 39
1042
+      "iconIdx": 40
1135 1043
     },
1136 1044
     {
1137 1045
       "icon": {
@@ -1157,7 +1065,7 @@
1157 1065
       },
1158 1066
       "setIdx": 0,
1159 1067
       "setId": 1,
1160
-      "iconIdx": 40
1068
+      "iconIdx": 41
1161 1069
     },
1162 1070
     {
1163 1071
       "icon": {
@@ -1184,7 +1092,7 @@
1184 1092
       },
1185 1093
       "setIdx": 0,
1186 1094
       "setId": 1,
1187
-      "iconIdx": 41
1095
+      "iconIdx": 42
1188 1096
     },
1189 1097
     {
1190 1098
       "icon": {
@@ -1213,7 +1121,7 @@
1213 1121
       },
1214 1122
       "setIdx": 0,
1215 1123
       "setId": 1,
1216
-      "iconIdx": 42
1124
+      "iconIdx": 43
1217 1125
     },
1218 1126
     {
1219 1127
       "icon": {
@@ -1240,7 +1148,7 @@
1240 1148
       },
1241 1149
       "setIdx": 0,
1242 1150
       "setId": 1,
1243
-      "iconIdx": 43
1151
+      "iconIdx": 44
1244 1152
     },
1245 1153
     {
1246 1154
       "icon": {
@@ -1267,7 +1175,7 @@
1267 1175
       },
1268 1176
       "setIdx": 0,
1269 1177
       "setId": 1,
1270
-      "iconIdx": 44
1178
+      "iconIdx": 45
1271 1179
     }
1272 1180
   ],
1273 1181
   "height": 1024,

+ 21
- 2
interface_config.js Ver arquivo

@@ -98,11 +98,30 @@ var interfaceConfig = { // eslint-disable-line no-unused-vars
98 98
      *
99 99
      * @type {number}
100 100
      */
101
-    MAXIMUM_ZOOMING_COEFFICIENT: 1.3
101
+    MAXIMUM_ZOOMING_COEFFICIENT: 1.3,
102 102
 
103 103
     /*
104 104
      * If indicated some of the error dialogs may point to the support URL for
105 105
      * help.
106 106
      */
107
-    // SUPPORT_URL: ""
107
+    // SUPPORT_URL: "",
108
+
109
+    /**
110
+     * Whether the connection indicator icon should hide itself based on
111
+     * connection strength. If true, the connection indicator will remain
112
+     * displayed while the participant has a weak connection and will hide
113
+     * itself after the CONNECTION_INDICATOR_HIDE_TIMEOUT when the connection is
114
+     * strong.
115
+     *
116
+     * @type {boolean}
117
+     */
118
+    CONNECTION_INDICATOR_AUTO_HIDE_ENABLED: false,
119
+
120
+    /**
121
+     * How long the connection indicator should remain displayed before hiding.
122
+     * Used in conjunction with CONNECTION_INDICATOR_AUTOHIDE_ENABLED.
123
+     *
124
+     * @type {number}
125
+     */
126
+    CONNECTION_INDICATOR_AUTO_HIDE_TIMEOUT: 5000
108 127
 };

+ 9
- 1
lang/main.json Ver arquivo

@@ -200,7 +200,15 @@
200 200
         "bandwidth": "Estimated bandwidth:",
201 201
         "na": "Come back here for connection information once the conference starts",
202 202
         "peer_to_peer": " (p2p)",
203
-        "turn": " (turn)"
203
+        "turn": " (turn)",
204
+        "quality": {
205
+            "good": "Good",
206
+            "inactive": "Inactive",
207
+            "lost": "Lost",
208
+            "nonoptimal": "Nonoptimal",
209
+            "poor": "Poor"
210
+        },
211
+        "status": "Connection:"
204 212
     },
205 213
     "notify": {
206 214
         "disconnected": "disconnected",

+ 6
- 0
modules/UI/videolayout/SmallVideo.js Ver arquivo

@@ -253,10 +253,12 @@ SmallVideo.prototype.bindHoverHandler = function () {
253 253
         () => {
254 254
             this.videoIsHovered = true;
255 255
             this.updateView();
256
+            this.updateIndicators();
256 257
         },
257 258
         () => {
258 259
             this.videoIsHovered = false;
259 260
             this.updateView();
261
+            this.updateIndicators();
260 262
         }
261 263
     );
262 264
 };
@@ -755,6 +757,8 @@ SmallVideo.prototype.updateIndicators = function () {
755 757
         = this.container.querySelector('.videocontainer__toptoolbar');
756 758
 
757 759
     const iconSize = UIUtil.getIndicatorFontSize();
760
+    const showConnectionIndicator = this.videoIsHovered
761
+        || !interfaceConfig.CONNECTION_INDICATOR_AUTO_HIDE_ENABLED;
758 762
     const tooltipPosition = interfaceConfig.VERTICAL_FILMSTRIP ? 'left' : 'top';
759 763
 
760 764
     /* jshint ignore:start */
@@ -763,7 +767,9 @@ SmallVideo.prototype.updateIndicators = function () {
763 767
             <div>
764 768
                 { this._showConnectionIndicator
765 769
                     ? <ConnectionIndicator
770
+                        alwaysVisible = { showConnectionIndicator }
766 771
                         connectionStatus = { this._connectionStatus }
772
+                        iconSize = { iconSize }
767 773
                         isLocalVideo = { this.isLocal }
768 774
                         enableStatsDisplay = { !interfaceConfig.filmStripOnly }
769 775
                         statsPopoverPosition = { this.statsPopoverLocation }

+ 223
- 57
react/features/connection-indicator/components/ConnectionIndicator.js Ver arquivo

@@ -1,48 +1,57 @@
1
+import PropTypes from 'prop-types';
1 2
 import React, { Component } from 'react';
2 3
 
4
+import { translate } from '../../base/i18n';
3 5
 import { JitsiParticipantConnectionStatus } from '../../base/lib-jitsi-meet';
4 6
 import { Popover } from '../../base/popover';
5 7
 import { ConnectionStatsTable } from '../../connection-stats';
6 8
 
7 9
 import statsEmitter from '../statsEmitter';
8 10
 
9
-declare var $: Object;
10 11
 declare var interfaceConfig: Object;
11 12
 
12
-// Converts the percent for connection quality into a string recognized for CSS.
13
+/**
14
+ * The connection quality percentage that must be reached to be considered of
15
+ * good quality and can result in the connection indicator being hidden.
16
+ *
17
+ * @type {number}
18
+ */
19
+const INDICATOR_DISPLAY_THRESHOLD = 70;
20
+
21
+/**
22
+ * An array of display configurations for the connection indicator and its bars.
23
+ * The ordering is done specifically for faster iteration to find a matching
24
+ * configuration to the current connection strength percentage.
25
+ *
26
+ * @type {Object[]}
27
+ */
13 28
 const QUALITY_TO_WIDTH = [
14 29
 
15
-    // Full (5 bars)
30
+    // Full (3 bars)
16 31
     {
17
-        percent: 80,
32
+        colorClass: 'status-high',
33
+        percent: INDICATOR_DISPLAY_THRESHOLD,
34
+        tip: 'connectionindicator.quality.good',
18 35
         width: '100%'
19 36
     },
20 37
 
21
-    // 4 bars
22
-    {
23
-        percent: 60,
24
-        width: '80%'
25
-    },
26
-
27
-    // 3 bars
28
-    {
29
-        percent: 40,
30
-        width: '55%'
31
-    },
32
-
33 38
     // 2 bars
34 39
     {
35
-        percent: 20,
36
-        width: '40%'
40
+        colorClass: 'status-med',
41
+        percent: 40,
42
+        tip: 'connectionindicator.quality.nonoptimal',
43
+        width: '66%'
37 44
     },
38 45
 
39 46
     // 1 bar
40 47
     {
48
+        colorClass: 'status-low',
41 49
         percent: 0,
42
-        width: '20%'
50
+        tip: 'connectionindicator.quality.poor',
51
+        width: '33%'
43 52
     }
44 53
 
45
-    // Note: we never show 0 bars.
54
+    // Note: we never show 0 bars as long as there is a connection.
46 55
 ];
47 56
 
48 57
 /**
@@ -58,41 +67,52 @@ class ConnectionIndicator extends Component {
58 67
      * @static
59 68
      */
60 69
     static propTypes = {
70
+        /**
71
+         * Whether or not the component should ignore setting a visibility class
72
+         * for hiding the component when the connection quality is not strong.
73
+         */
74
+        alwaysVisible: PropTypes.bool,
75
+
61 76
         /**
62 77
          * The current condition of the user's connection, matching one of the
63 78
          * enumerated values in the library.
64 79
          *
65 80
          * @type {JitsiParticipantConnectionStatus}
66 81
          */
67
-        connectionStatus: React.PropTypes.string,
82
+        connectionStatus: PropTypes.string,
68 83
 
69 84
         /**
70 85
          * Whether or not clicking the indicator should display a popover for
71 86
          * more details.
72 87
          */
73
-        enableStatsDisplay: React.PropTypes.bool,
88
+        enableStatsDisplay: PropTypes.bool,
89
+
90
+        /**
91
+         * The font-size for the icon.
92
+         */
93
+        iconSize: PropTypes.number,
74 94
 
75 95
         /**
76 96
          * Whether or not the displays stats are for local video.
77 97
          */
78
-        isLocalVideo: React.PropTypes.bool,
98
+        isLocalVideo: PropTypes.bool,
79 99
 
80 100
         /**
81 101
          * Relative to the icon from where the popover for more connection
82 102
          * details should display.
83 103
          */
84
-        statsPopoverPosition: React.PropTypes.string,
104
+        statsPopoverPosition: PropTypes.string,
85 105
 
86 106
         /**
87 107
          * Invoked to obtain translated strings.
88 108
          */
89
-        t: React.PropTypes.func,
109
+        t: PropTypes.func,
90 110
 
91 111
         /**
92 112
          * The user ID associated with the displayed connection indication and
93 113
          * stats.
94 114
          */
95
-        userID: React.PropTypes.string
115
+        userID: PropTypes.string
96 116
     };
97 117
 
98 118
     /**
@@ -105,6 +125,23 @@ class ConnectionIndicator extends Component {
105 125
         super(props);
106 126
 
107 127
         this.state = {
128
+            /**
129
+             * The timeout for automatically hiding the indicator.
130
+             *
131
+             * @type {timeoutID}
132
+             */
133
+            autoHideTimeout: null,
134
+
135
+            /**
136
+             * Whether or not a CSS class should be applied to the root for
137
+             * hiding the connection indicator. By default the indicator should
138
+             * start out hidden because the current connection status is not
139
+             * known at mount.
140
+             *
141
+             * @type {boolean}
142
+             */
143
+            showIndicator: false,
144
+
108 145
             /**
109 146
              * Whether or not the popover content should display additional
110 147
              * statistics.
@@ -154,7 +191,8 @@ class ConnectionIndicator extends Component {
154 191
     }
155 192
 
156 193
     /**
157
-     * Sets the state to hide the Statistics Table popover.
194
+     * Cleans up any queued processes, which includes listening for new stats
195
+     * and clearing any timeout to hide the indicator.
158 196
      *
159 197
      * @private
160 198
      * @returns {void}
@@ -162,6 +200,8 @@ class ConnectionIndicator extends Component {
162 200
     componentWillUnmount() {
163 201
         statsEmitter.unsubscribeToClientStats(
164 202
             this.props.userID, this._onStatsUpdated);
203
+
204
+        clearTimeout(this.state.autoHideTimeout);
165 205
     }
166 206
 
167 207
     /**
@@ -171,13 +211,22 @@ class ConnectionIndicator extends Component {
171 211
      * @returns {ReactElement}
172 212
      */
173 213
     render() {
214
+        const visibilityClass = this._getVisibilityClass();
215
+        const rootClassNames = `indicator-container ${visibilityClass}`;
216
+
217
+        const colorClass = this._getConnectionColorClass();
218
+        const indicatorContainerClassNames
219
+            = `connection-indicator indicator ${colorClass}`;
220
+
174 221
         return (
175 222
             <Popover
176
-                className = 'indicator-container'
223
+                className = { rootClassNames }
177 224
                 content = { this._renderStatisticsTable() }
178 225
                 position = { this.props.statsPopoverPosition }>
179 226
                 <div className = 'popover-trigger'>
180
-                    <div className = 'connection-indicator indicator'>
227
+                    <div
228
+                        className = { indicatorContainerClassNames }
229
+                        style = {{ fontSize: this.props.iconSize }}>
181 230
                         <div className = 'connection indicatoricon'>
182 231
                             { this._renderIcon() }
183 232
                         </div>
@@ -187,6 +236,83 @@ class ConnectionIndicator extends Component {
187 236
         );
188 237
     }
189 238
 
239
+    /**
240
+     * Returns a CSS class that interprets the current connection status as a
241
+     * color.
242
+     *
243
+     * @private
244
+     * @returns {string}
245
+     */
246
+    _getConnectionColorClass() {
247
+        const { connectionStatus } = this.props;
248
+        const { percent } = this.state.stats;
249
+        const { INACTIVE, INTERRUPTED } = JitsiParticipantConnectionStatus;
250
+
251
+        if (connectionStatus === INACTIVE) {
252
+            return 'status-other';
253
+        } else if (connectionStatus === INTERRUPTED) {
254
+            return 'status-lost';
255
+        } else if (typeof percent === 'undefined') {
256
+            return 'status-high';
257
+        }
258
+
259
+        return QUALITY_TO_WIDTH.find(x => percent >= x.percent).colorClass;
260
+    }
261
+
262
+    /**
263
+     * Returns a string that describes the current connection status.
264
+     *
265
+     * @private
266
+     * @returns {string}
267
+     */
268
+    _getConnectionStatusTip() {
269
+        let tipKey;
270
+
271
+        switch (this.props.connectionStatus) {
272
+        case JitsiParticipantConnectionStatus.INTERRUPTED:
273
+            tipKey = 'connectionindicator.quality.lost';
274
+            break;
275
+
276
+        case JitsiParticipantConnectionStatus.INACTIVE:
277
+            tipKey = 'connectionindicator.quality.inactive';
278
+            break;
279
+
280
+        default: {
281
+            const { percent } = this.state.stats;
282
+
283
+            if (typeof percent === 'undefined') {
284
+                // If percentage is undefined then there are no stats available
285
+                // yet, likely because only a local connection has been
286
+                // established so far. Assume a strong connection to start.
287
+                tipKey = 'connectionindicator.quality.good';
288
+            } else {
289
+                const config = QUALITY_TO_WIDTH.find(x => percent >= x.percent);
290
+
291
+                tipKey = config.tip;
292
+            }
293
+        }
294
+        }
295
+
296
+        return this.props.t(tipKey);
297
+    }
298
+
299
+    /**
300
+     * Returns additional class names to add to the root of the component. The
301
+     * class names are intended to be used for hiding or showing the indicator.
302
+     *
303
+     * @private
304
+     * @returns {string}
305
+     */
306
+    _getVisibilityClass() {
307
+        const { connectionStatus } = this.props;
308
+
309
+        return this.state.showIndicator
310
+            || this.props.alwaysVisible
311
+            || connectionStatus === JitsiParticipantConnectionStatus.INTERRUPTED
312
+            || connectionStatus === JitsiParticipantConnectionStatus.INACTIVE
313
+            ? 'show-connection-indicator' : 'hide-connection-indicator';
314
+    }
315
+
190 316
     /**
191 317
      * Callback invoked when new connection stats associated with the passed in
192 318
      * user ID are available. Will update the component's display of current
@@ -209,6 +335,9 @@ class ConnectionIndicator extends Component {
209 335
         this.setState({
210 336
             stats: newStats
211 337
         });
338
+
339
+        // Rely on React to batch setState actions.
340
+        this._updateIndicatorAutoHide(newStats.percent);
212 341
     }
213 342
 
214 343
     /**
@@ -229,40 +358,46 @@ class ConnectionIndicator extends Component {
229 358
      * @returns {ReactElement}
230 359
      */
231 360
     _renderIcon() {
232
-        switch (this.props.connectionStatus) {
233
-        case JitsiParticipantConnectionStatus.INTERRUPTED:
234
-            return (
235
-                <span className = 'connection_lost'>
236
-                    <i className = 'icon-connection-lost' />
237
-                </span>
238
-            );
239
-        case JitsiParticipantConnectionStatus.INACTIVE:
361
+        if (this.props.connectionStatus
362
+            === JitsiParticipantConnectionStatus.INACTIVE) {
240 363
             return (
241 364
                 <span className = 'connection_ninja'>
242 365
                     <i className = 'icon-ninja' />
243 366
                 </span>
244 367
             );
245
-        default: {
246
-            const { percent } = this.state.stats;
247
-            const width = QUALITY_TO_WIDTH.find(x => percent >= x.percent);
248
-            const iconWidth = width && width.width
249
-                ? { width: width && width.width } : {};
250
-
251
-            return [
252
-                <span
253
-                    className = 'connection_empty'
254
-                    key = 'icon-empty'>
255
-                    <i className = 'icon-connection' />
256
-                </span>,
257
-                <span
258
-                    className = 'connection_full'
259
-                    key = 'icon-full'
260
-                    style = { iconWidth }>
261
-                    <i className = 'icon-connection' />
262
-                </span>
263
-            ];
264 368
         }
369
+
370
+        let iconWidth;
371
+        let emptyIconWrapperClassName = 'connection_empty';
372
+
373
+        if (this.props.connectionStatus
374
+            === JitsiParticipantConnectionStatus.INTERRUPTED) {
375
+
376
+            // emptyIconWrapperClassName is used by the torture tests to
377
+            // identify lost connection status handling.
378
+            emptyIconWrapperClassName = 'connection_lost';
379
+            iconWidth = '0%';
380
+        } else if (typeof this.state.stats.percent === 'undefined') {
381
+            iconWidth = '100%';
382
+        } else {
383
+            const { percent } = this.state.stats;
384
+
385
+            iconWidth = QUALITY_TO_WIDTH.find(x => percent >= x.percent).width;
265 386
         }
387
+
388
+        return [
389
+            <span
390
+                className = { emptyIconWrapperClassName }
391
+                key = 'icon-empty'>
392
+                <i className = 'icon-gsm-bars' />
393
+            </span>,
394
+            <span
395
+                className = 'connection_full'
396
+                key = 'icon-full'
397
+                style = {{ width: iconWidth }}>
398
+                <i className = 'icon-gsm-bars' />
399
+            </span>
400
+        ];
266 401
     }
267 402
 
268 403
     /**
@@ -284,6 +419,7 @@ class ConnectionIndicator extends Component {
284 419
             <ConnectionStatsTable
285 420
                 bandwidth = { bandwidth }
286 421
                 bitrate = { bitrate }
422
+                connectionSummary = { this._getConnectionStatusTip() }
287 423
                 framerate = { framerate }
288 424
                 isLocalVideo = { this.props.isLocalVideo }
289 425
                 onShowMore = { this._onToggleShowMore }
@@ -293,6 +429,36 @@ class ConnectionIndicator extends Component {
293 429
                 transport = { transport } />
294 430
         );
295 431
     }
432
+
433
+    /**
434
+     * Updates the internal state for automatically hiding the indicator.
435
+     *
436
+     * @param {number} percent - The current connection quality percentage
437
+     * between the values 0 and 100.
438
+     * @private
439
+     * @returns {void}
440
+     */
441
+    _updateIndicatorAutoHide(percent) {
442
+        if (percent < INDICATOR_DISPLAY_THRESHOLD) {
443
+            clearTimeout(this.state.autoHideTimeout);
444
+            this.setState({
445
+                autoHideTimeout: null,
446
+                showIndicator: true
447
+            });
448
+        } else if (this.state.autoHideTimeout) {
449
+            // This clause is intentionally left blank because no further action
450
+            // is needed if the percent is below the threshold and there is an
451
+            // autoHideTimeout set.
452
+        } else {
453
+            this.setState({
454
+                autoHideTimeout: setTimeout(() => {
455
+                    this.setState({
456
+                        showIndicator: false
457
+                    });
458
+                }, interfaceConfig.CONNECTION_INDICATOR_AUTO_HIDE_TIMEOUT)
459
+            });
460
+        }
461
+    }
296 462
 }
297 463
 
298
-export default ConnectionIndicator;
464
+export default translate(ConnectionIndicator);

+ 35
- 10
react/features/connection-stats/components/ConnectionStatsTable.js Ver arquivo

@@ -1,3 +1,4 @@
1
+import PropTypes from 'prop-types';
1 2
 import React, { Component } from 'react';
2 3
 
3 4
 import { translate } from '../../base/i18n';
@@ -21,7 +22,7 @@ class ConnectionStatsTable extends Component {
21 22
          *     upload: Number
22 23
          * }}
23 24
          */
24
-        bandwidth: React.PropTypes.object,
25
+        bandwidth: PropTypes.object,
25 26
 
26 27
         /**
27 28
          * Statistics related to bitrate.
@@ -30,7 +31,12 @@ class ConnectionStatsTable extends Component {
30 31
          *     upload: Number
31 32
          * }}
32 33
          */
33
-        bitrate: React.PropTypes.object,
34
+        bitrate: PropTypes.object,
35
+
36
+        /**
37
+         * A message describing the connection quality.
38
+         */
39
+        connectionSummary: PropTypes.string,
34 40
 
35 41
         /**
36 42
          * Statistics related to framerates for each ssrc.
@@ -38,17 +44,17 @@ class ConnectionStatsTable extends Component {
38 44
          *     [ ssrc ]: Number
39 45
          * }}
40 46
          */
41
-        framerate: React.PropTypes.object,
47
+        framerate: PropTypes.object,
42 48
 
43 49
         /**
44 50
          * Whether or not the statitics are for local video.
45 51
          */
46
-        isLocalVideo: React.PropTypes.bool,
52
+        isLocalVideo: PropTypes.bool,
47 53
 
48 54
         /**
49 55
          * Callback to invoke when the show additional stats link is clicked.
50 56
          */
51
-        onShowMore: React.PropTypes.func,
57
+        onShowMore: PropTypes.func,
52 58
 
53 59
         /**
54 60
          * Statistics related to packet loss.
@@ -57,7 +63,7 @@ class ConnectionStatsTable extends Component {
57 63
          *     upload: Number
58 64
          * }}
59 65
          */
60
-        packetLoss: React.PropTypes.object,
66
+        packetLoss: PropTypes.object,
61 67
 
62 68
         /**
63 69
          * Statistics related to display resolutions for each ssrc.
@@ -68,23 +74,23 @@ class ConnectionStatsTable extends Component {
68 74
          *     }
69 75
          * }}
70 76
          */
71
-        resolution: React.PropTypes.object,
77
+        resolution: PropTypes.object,
72 78
 
73 79
         /**
74 80
          * Whether or not additional stats about bandwidth and transport should
75 81
          * be displayed. Will not display even if true for remote participants.
76 82
          */
77
-        shouldShowMore: React.PropTypes.bool,
83
+        shouldShowMore: PropTypes.bool,
78 84
 
79 85
         /**
80 86
          * Invoked to obtain translated strings.
81 87
          */
82
-        t: React.PropTypes.func,
88
+        t: PropTypes.func,
83 89
 
84 90
         /**
85 91
          * Statistics related to transports.
86 92
          */
87
-        transport: React.PropTypes.array
93
+        transport: PropTypes.array
88 94
     };
89 95
 
90 96
     /**
@@ -184,6 +190,24 @@ class ConnectionStatsTable extends Component {
184 190
         );
185 191
     }
186 192
 
193
+    /**
194
+     * Creates a table row as a ReactElement for displaying a summary message
195
+     * about the current connection status.
196
+     *
197
+     * @private
198
+     * @returns {ReactElement}
199
+     */
200
+    _renderConnectionSummary() {
201
+        return (
202
+            <tr className = 'connection-info__status'>
203
+                <td>
204
+                    <span>{ this.props.t('connectionindicator.status') }</span>
205
+                </td>
206
+                <td>{ this.props.connectionSummary }</td>
207
+            </tr>
208
+        );
209
+    }
210
+
187 211
     /**
188 212
      * Creates a table row as a ReactElement for displaying frame rate related
189 213
      * statistics.
@@ -309,6 +333,7 @@ class ConnectionStatsTable extends Component {
309 333
         return (
310 334
             <table className = 'connection-info__container'>
311 335
                 <tbody>
336
+                    { this._renderConnectionSummary() }
312 337
                     { this._renderBitrate() }
313 338
                     { this._renderPacketLoss() }
314 339
                     { this._renderResolution() }

Carregando…
Cancelar
Salvar