Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

SmallVideo.js 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. var UIUtil = require("../util/UIUtil");
  2. var LargeVideo = require("./LargeVideo");
  3. function SmallVideo(){
  4. this.isMuted = false;
  5. this.hasAvatar = false;
  6. }
  7. function setVisibility(selector, show) {
  8. if (selector && selector.length > 0) {
  9. selector.css("visibility", show ? "visible" : "hidden");
  10. }
  11. }
  12. SmallVideo.prototype.showDisplayName = function(isShow) {
  13. var nameSpan = $('#' + this.videoSpanId + '>span.displayname').get(0);
  14. if (isShow) {
  15. if (nameSpan && nameSpan.innerHTML && nameSpan.innerHTML.length)
  16. nameSpan.setAttribute("style", "display:inline-block;");
  17. }
  18. else {
  19. if (nameSpan)
  20. nameSpan.setAttribute("style", "display:none;");
  21. }
  22. };
  23. SmallVideo.prototype.setDeviceAvailabilityIcons = function (devices) {
  24. if(!this.container)
  25. return;
  26. $("#" + this.videoSpanId + " > .noMic").remove();
  27. $("#" + this.videoSpanId + " > .noVideo").remove();
  28. if(!devices.audio)
  29. {
  30. this.container.appendChild(
  31. document.createElement("div")).setAttribute("class","noMic");
  32. }
  33. if(!devices.video)
  34. {
  35. this.container.appendChild(
  36. document.createElement("div")).setAttribute("class","noVideo");
  37. }
  38. if(!devices.audio && !devices.video)
  39. {
  40. $("#" + this.videoSpanId + " > .noMic").css("background-position", "75%");
  41. $("#" + this.videoSpanId + " > .noVideo").css("background-position", "25%");
  42. $("#" + this.videoSpanId + " > .noVideo").css("background-color", "transparent");
  43. }
  44. }
  45. /**
  46. * Shows the presence status message for the given video.
  47. */
  48. SmallVideo.prototype.setPresenceStatus = function (statusMsg) {
  49. if (!this.container) {
  50. // No container
  51. return;
  52. }
  53. var statusSpan = $('#' + this.videoSpanId + '>span.status');
  54. if (!statusSpan.length) {
  55. //Add status span
  56. statusSpan = document.createElement('span');
  57. statusSpan.className = 'status';
  58. statusSpan.id = this.videoSpanId + '_status';
  59. $('#' + this.videoSpanId)[0].appendChild(statusSpan);
  60. statusSpan = $('#' + this.videoSpanId + '>span.status');
  61. }
  62. // Display status
  63. if (statusMsg && statusMsg.length) {
  64. $('#' + this.videoSpanId + '_status').text(statusMsg);
  65. statusSpan.get(0).setAttribute("style", "display:inline-block;");
  66. }
  67. else {
  68. // Hide
  69. statusSpan.get(0).setAttribute("style", "display:none;");
  70. }
  71. };
  72. /**
  73. * Creates an audio or video stream element.
  74. */
  75. SmallVideo.createStreamElement = function (sid, stream) {
  76. var isVideo = stream.getVideoTracks().length > 0;
  77. var element = isVideo
  78. ? document.createElement('video')
  79. : document.createElement('audio');
  80. var id = (isVideo ? 'remoteVideo_' : 'remoteAudio_')
  81. + sid + '_' + APP.RTC.getStreamID(stream);
  82. element.id = id;
  83. element.autoplay = true;
  84. element.oncontextmenu = function () { return false; };
  85. return element;
  86. };
  87. /**
  88. * Updates the data for the indicator
  89. * @param id the id of the indicator
  90. * @param percent the percent for connection quality
  91. * @param object the data
  92. */
  93. SmallVideo.prototype.updateStatsIndicator = function (percent, object) {
  94. if(this.connectionIndicator)
  95. this.connectionIndicator.updateConnectionQuality(percent, object);
  96. }
  97. SmallVideo.prototype.hideIndicator = function () {
  98. if(this.connectionIndicator)
  99. this.connectionIndicator.hideIndicator();
  100. }
  101. /**
  102. * Shows audio muted indicator over small videos.
  103. * @param {string} isMuted
  104. */
  105. SmallVideo.prototype.showAudioIndicator = function(isMuted) {
  106. var audioMutedSpan = $('#' + this.videoSpanId + '>span.audioMuted');
  107. if (!isMuted) {
  108. if (audioMutedSpan.length > 0) {
  109. audioMutedSpan.popover('hide');
  110. audioMutedSpan.remove();
  111. }
  112. }
  113. else {
  114. if(audioMutedSpan.length == 0 ) {
  115. audioMutedSpan = document.createElement('span');
  116. audioMutedSpan.className = 'audioMuted';
  117. UIUtil.setTooltip(audioMutedSpan,
  118. "videothumbnail.mute",
  119. "top");
  120. this.container.appendChild(audioMutedSpan);
  121. APP.translation.translateElement($('#' + this.videoSpanId + " > span"));
  122. var mutedIndicator = document.createElement('i');
  123. mutedIndicator.className = 'icon-mic-disabled';
  124. audioMutedSpan.appendChild(mutedIndicator);
  125. }
  126. this.updateIconPositions();
  127. }
  128. this.isMuted = isMuted;
  129. };
  130. /**
  131. * Shows video muted indicator over small videos.
  132. */
  133. SmallVideo.prototype.showVideoIndicator = function(isMuted) {
  134. this.showAvatar(isMuted);
  135. var videoMutedSpan = $('#' + this.videoSpanId + '>span.videoMuted');
  136. if (isMuted === false) {
  137. if (videoMutedSpan.length > 0) {
  138. videoMutedSpan.remove();
  139. }
  140. }
  141. else {
  142. if(videoMutedSpan.length == 0) {
  143. videoMutedSpan = document.createElement('span');
  144. videoMutedSpan.className = 'videoMuted';
  145. this.container.appendChild(videoMutedSpan);
  146. var mutedIndicator = document.createElement('i');
  147. mutedIndicator.className = 'icon-camera-disabled';
  148. UIUtil.setTooltip(mutedIndicator,
  149. "videothumbnail.videomute",
  150. "top");
  151. videoMutedSpan.appendChild(mutedIndicator);
  152. //translate texts for muted indicator
  153. APP.translation.translateElement($('#' + this.videoSpanId + " > span > i"));
  154. }
  155. this.updateIconPositions();
  156. }
  157. };
  158. SmallVideo.prototype.enableDominantSpeaker = function (isEnable)
  159. {
  160. var displayName = this.resourceJid;
  161. var nameSpan = $('#' + this.videoSpanId + '>span.displayname');
  162. if (nameSpan.length > 0)
  163. displayName = nameSpan.html();
  164. console.log("UI enable dominant speaker",
  165. displayName,
  166. this.resourceJid,
  167. isEnable);
  168. if (!this.container) {
  169. return;
  170. }
  171. var video = $('#' + this.videoSpanId + '>video');
  172. if (video && video.length > 0) {
  173. if (isEnable) {
  174. this.showDisplayName(LargeVideo.isLargeVideoOnTop());
  175. if (!this.container.classList.contains("dominantspeaker"))
  176. this.container.classList.add("dominantspeaker");
  177. }
  178. else {
  179. this.showDisplayName(false);
  180. if (this.container.classList.contains("dominantspeaker"))
  181. this.container.classList.remove("dominantspeaker");
  182. }
  183. }
  184. this.showAvatar();
  185. };
  186. SmallVideo.prototype.updateIconPositions = function () {
  187. var audioMutedSpan = $('#' + this.videoSpanId + '>span.audioMuted');
  188. var connectionIndicator = $('#' + this.videoSpanId + '>div.connectionindicator');
  189. var videoMutedSpan = $('#' + this.videoSpanId + '>span.videoMuted');
  190. if(connectionIndicator.length > 0
  191. && connectionIndicator[0].style.display != "none") {
  192. audioMutedSpan.css({right: "23px"});
  193. videoMutedSpan.css({right: ((audioMutedSpan.length > 0? 23 : 0) + 30) + "px"});
  194. }
  195. else
  196. {
  197. audioMutedSpan.css({right: "0px"});
  198. videoMutedSpan.css({right: (audioMutedSpan.length > 0? 30 : 0) + "px"});
  199. }
  200. }
  201. /**
  202. * Creates the element indicating the moderator(owner) of the conference.
  203. *
  204. * @param parentElement the parent element where the owner indicator will
  205. * be added
  206. */
  207. SmallVideo.prototype.createModeratorIndicatorElement = function () {
  208. // Show moderator indicator
  209. var indicatorSpan = $('#' + this.videoSpanId + ' .focusindicator');
  210. if (!indicatorSpan || indicatorSpan.length === 0) {
  211. indicatorSpan = document.createElement('span');
  212. indicatorSpan.className = 'focusindicator';
  213. this.container.appendChild(indicatorSpan);
  214. indicatorSpan = $('#' + this.videoSpanId + ' .focusindicator');
  215. }
  216. if (indicatorSpan.children().length !== 0)
  217. return;
  218. var moderatorIndicator = document.createElement('i');
  219. moderatorIndicator.className = 'fa fa-star';
  220. indicatorSpan[0].appendChild(moderatorIndicator);
  221. UIUtil.setTooltip(indicatorSpan[0],
  222. "videothumbnail.moderator",
  223. "top");
  224. //translates text in focus indicators
  225. APP.translation.translateElement($('#' + this.videoSpanId + ' .focusindicator'));
  226. }
  227. SmallVideo.prototype.getSrc = function () {
  228. return APP.RTC.getVideoSrc($('#' + this.videoSpanId).find("video").get(0));
  229. }
  230. SmallVideo.prototype.focus = function(isFocused)
  231. {
  232. if(!isFocused) {
  233. this.container.classList.remove("videoContainerFocused");
  234. }
  235. else
  236. {
  237. this.container.classList.add("videoContainerFocused");
  238. }
  239. }
  240. SmallVideo.prototype.hasVideo = function () {
  241. return $("#" + this.videoSpanId).find("video").length !== 0;
  242. }
  243. /**
  244. * Hides or shows the user's avatar
  245. * @param show whether we should show the avatar or not
  246. * video because there is no dominant speaker and no focused speaker
  247. */
  248. SmallVideo.prototype.showAvatar = function (show) {
  249. if(!this.hasAvatar)
  250. return;
  251. var video = $('#' + this.videoSpanId).find("video");
  252. var avatar = $('#avatar_' + this.resourceJid);
  253. if (show === undefined || show === null) {
  254. if(!this.VideoLayout.isInLastN(this.resourceJid)) {
  255. show = true;
  256. }
  257. else
  258. {
  259. show = APP.RTC.isVideoMuted(this.peerJid);
  260. }
  261. }
  262. if (LargeVideo.showAvatar(this.resourceJid, show))
  263. {
  264. setVisibility(avatar, false);
  265. setVisibility(video, false);
  266. } else {
  267. if (video && video.length > 0) {
  268. setVisibility(video, !show);
  269. }
  270. setVisibility(avatar, show);
  271. }
  272. }
  273. SmallVideo.prototype.avatarChanged = function (thumbUrl) {
  274. var thumbnail = $('#' + this.videoSpanId);
  275. var avatar = $('#avatar_' + this.resourceJid);
  276. this.hasAvatar = true;
  277. // set the avatar in the thumbnail
  278. if (avatar && avatar.length > 0) {
  279. avatar[0].src = thumbUrl;
  280. } else {
  281. if (thumbnail && thumbnail.length > 0) {
  282. avatar = document.createElement('img');
  283. avatar.id = 'avatar_' + this.resourceJid;
  284. avatar.className = 'userAvatar';
  285. avatar.src = thumbUrl;
  286. thumbnail.append(avatar);
  287. }
  288. }
  289. }
  290. module.exports = SmallVideo;