Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

ConnectionIndicator.js 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /* global $, APP, interfaceConfig, JitsiMeetJS */
  2. /* jshint -W101 */
  3. /* eslint-disable no-unused-vars */
  4. import React from 'react';
  5. import ReactDOM from 'react-dom';
  6. import { ConnectionStatsTable } from '../../../react/features/connection-stats';
  7. /* eslint-enable no-unused-vars */
  8. import JitsiPopover from "../util/JitsiPopover";
  9. import UIUtil from "../util/UIUtil";
  10. const ParticipantConnectionStatus
  11. = JitsiMeetJS.constants.participantConnectionStatus;
  12. /**
  13. * Maps a connection quality value (in percent) to the width of the "full" icon.
  14. */
  15. const qualityToWidth = [
  16. // Full (5 bars)
  17. {percent: 80, width: "100%"},
  18. // 4 bars
  19. {percent: 60, width: "80%"},
  20. // 3 bars
  21. {percent: 40, width: "55%"},
  22. // 2 bars
  23. {percent: 20, width: "40%"},
  24. // 1 bar
  25. {percent: 0, width: "20%"}
  26. // Note: we never show 0 bars.
  27. ];
  28. /**
  29. * Constructs new connection indicator.
  30. * @param videoContainer the video container associated with the indicator.
  31. * @param videoId the identifier of the video
  32. * @constructor
  33. */
  34. function ConnectionIndicator(videoContainer, videoId) {
  35. this.videoContainer = videoContainer;
  36. this.bandwidth = null;
  37. this.packetLoss = null;
  38. this.bitrate = null;
  39. this.showMoreValue = false;
  40. this.resolution = null;
  41. this.transport = [];
  42. this.framerate = null;
  43. this.popover = null;
  44. this.id = videoId;
  45. this.create();
  46. this.isLocalVideo
  47. = this.videoContainer.videoSpanId === 'localVideoContainer';
  48. this.showMore = this.showMore.bind(this);
  49. }
  50. /**
  51. * Generates the html content.
  52. * @returns {string} the html content.
  53. */
  54. ConnectionIndicator.prototype.generateText = function () {
  55. /* jshint ignore:start */
  56. return (
  57. <ConnectionStatsTable
  58. bandwidth = { this.bandwidth }
  59. bitrate = { this.bitrate }
  60. isLocalVideo = { this.isLocalVideo }
  61. framerate = { this.framerate }
  62. onShowMore = { this.showMore }
  63. packetLoss = { this.packetLoss}
  64. resolution = { this.resolution }
  65. shouldShowMore = { this.showMoreValue }
  66. transport = { this.transport } />
  67. );
  68. /* jshint ignore:end */
  69. };
  70. /**
  71. * Shows or hide the additional information.
  72. */
  73. ConnectionIndicator.prototype.showMore = function () {
  74. this.showMoreValue = !this.showMoreValue;
  75. this.updatePopoverData();
  76. };
  77. function createIcon(classes, iconClass) {
  78. var icon = document.createElement("span");
  79. for(var i in classes) {
  80. icon.classList.add(classes[i]);
  81. }
  82. icon.appendChild(
  83. document.createElement("i")).classList.add(iconClass);
  84. return icon;
  85. }
  86. /**
  87. * Creates the indicator
  88. */
  89. ConnectionIndicator.prototype.create = function () {
  90. let indicatorId = 'connectionindicator';
  91. let element = UIUtil.getVideoThumbnailIndicatorSpan({
  92. videoSpanId: this.videoContainer.videoSpanId,
  93. indicatorId
  94. });
  95. element.classList.add('show');
  96. this.connectionIndicatorContainer = element;
  97. let popoverContent = (
  98. `<div class="connection-info" data-i18n="${indicatorId}.na"></div>`
  99. );
  100. this.popover = new JitsiPopover($(element), {
  101. content: popoverContent,
  102. skin: "black",
  103. onBeforePosition: el => APP.translation.translateElement(el),
  104. position: interfaceConfig.VERTICAL_FILMSTRIP ? 'left' : 'top'
  105. });
  106. // override popover show method to make sure we will update the content
  107. // before showing the popover
  108. var origShowFunc = this.popover.show;
  109. this.popover.show = function () {
  110. // update content by forcing it, to finish even if popover
  111. // is not visible
  112. this.updatePopoverData(true);
  113. // call the original show, passing its actual this
  114. origShowFunc.call(this.popover);
  115. }.bind(this);
  116. let connectionIconContainer = document.createElement('div');
  117. connectionIconContainer.className = 'connection indicatoricon';
  118. this.emptyIcon = connectionIconContainer.appendChild(
  119. createIcon(["connection_empty"], "icon-connection"));
  120. this.fullIcon = connectionIconContainer.appendChild(
  121. createIcon(["connection_full"], "icon-connection"));
  122. this.interruptedIndicator = connectionIconContainer.appendChild(
  123. createIcon(["connection_lost"],"icon-connection-lost"));
  124. this.ninjaIndicator = connectionIconContainer.appendChild(
  125. createIcon(["connection_ninja"],"icon-ninja"));
  126. $(this.interruptedIndicator).hide();
  127. $(this.ninjaIndicator).hide();
  128. this.connectionIndicatorContainer.appendChild(connectionIconContainer);
  129. };
  130. /**
  131. * Removes the indicator
  132. */
  133. ConnectionIndicator.prototype.remove = function() {
  134. if (this.connectionIndicatorContainer.parentNode) {
  135. this.connectionIndicatorContainer.parentNode.removeChild(
  136. this.connectionIndicatorContainer);
  137. }
  138. this.popover.forceHide();
  139. };
  140. /**
  141. * Updates the UI which displays or not a warning about user's connectivity
  142. * problems.
  143. *
  144. * @param {ParticipantConnectionStatus} connectionStatus
  145. */
  146. ConnectionIndicator.prototype.updateConnectionStatusIndicator
  147. = function (connectionStatus) {
  148. this.connectionStatus = connectionStatus;
  149. if (connectionStatus === ParticipantConnectionStatus.INTERRUPTED) {
  150. $(this.interruptedIndicator).show();
  151. $(this.emptyIcon).hide();
  152. $(this.fullIcon).hide();
  153. $(this.ninjaIndicator).hide();
  154. } else if (connectionStatus === ParticipantConnectionStatus.INACTIVE) {
  155. $(this.interruptedIndicator).hide();
  156. $(this.emptyIcon).hide();
  157. $(this.fullIcon).hide();
  158. $(this.ninjaIndicator).show();
  159. } else {
  160. $(this.interruptedIndicator).hide();
  161. $(this.emptyIcon).show();
  162. $(this.fullIcon).show();
  163. $(this.ninjaIndicator).hide();
  164. }
  165. };
  166. /**
  167. * Updates the data of the indicator
  168. * @param percent the percent of connection quality
  169. * @param object the statistics data.
  170. */
  171. ConnectionIndicator.prototype.updateConnectionQuality =
  172. function (percent, object) {
  173. if (!percent) {
  174. this.connectionIndicatorContainer.style.display = "none";
  175. this.popover.forceHide();
  176. return;
  177. } else {
  178. if(this.connectionIndicatorContainer.style.display == "none") {
  179. this.connectionIndicatorContainer.style.display = "block";
  180. }
  181. }
  182. if (object) {
  183. this.bandwidth = object.bandwidth;
  184. this.bitrate = object.bitrate;
  185. this.packetLoss = object.packetLoss;
  186. this.transport = object.transport;
  187. if (object.resolution) {
  188. this.resolution = object.resolution;
  189. }
  190. if (object.framerate)
  191. this.framerate = object.framerate;
  192. }
  193. let width = qualityToWidth.find(x => percent >= x.percent);
  194. this.fullIcon.style.width = width.width;
  195. this.updatePopoverData();
  196. };
  197. /**
  198. * Updates the resolution
  199. * @param resolution the new resolution
  200. */
  201. ConnectionIndicator.prototype.updateResolution = function (resolution) {
  202. this.resolution = resolution;
  203. this.updatePopoverData();
  204. };
  205. /**
  206. * Updates the framerate
  207. * @param framerate the new resolution
  208. */
  209. ConnectionIndicator.prototype.updateFramerate = function (framerate) {
  210. this.framerate = framerate;
  211. this.updatePopoverData();
  212. };
  213. /**
  214. * Updates the content of the popover if its visible
  215. * @param force to work even if popover is not visible
  216. */
  217. ConnectionIndicator.prototype.updatePopoverData = function (force) {
  218. // generate content, translate it and add it to document only if
  219. // popover is visible or we force to do so.
  220. if(this.popover.popoverShown || force) {
  221. this.popover.updateContent(this.generateText());
  222. }
  223. };
  224. /**
  225. * Hides the popover
  226. */
  227. ConnectionIndicator.prototype.hide = function () {
  228. this.popover.forceHide();
  229. };
  230. /**
  231. * Hides the indicator
  232. */
  233. ConnectionIndicator.prototype.hideIndicator = function () {
  234. this.connectionIndicatorContainer.style.display = "none";
  235. if(this.popover)
  236. this.popover.forceHide();
  237. };
  238. /**
  239. * Adds a hover listener to the popover.
  240. */
  241. ConnectionIndicator.prototype.addPopoverHoverListener = function (listener) {
  242. this.popover.addOnHoverPopover(listener);
  243. };
  244. export default ConnectionIndicator;