Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. var UI = {};
  2. var VideoLayout = require("./videolayout/VideoLayout.js");
  3. var AudioLevels = require("./audio_levels/AudioLevels.js");
  4. var Prezi = require("./prezi/Prezi.js");
  5. var Etherpad = require("./etherpad/Etherpad.js");
  6. var Chat = require("./side_pannels/chat/Chat.js");
  7. var Toolbar = require("./toolbars/toolbar");
  8. var ToolbarToggler = require("./toolbars/toolbartoggler");
  9. var BottomToolbar = require("./toolbars/BottomToolbar");
  10. var ContactList = require("./side_pannels/contactlist/ContactList");
  11. var Avatar = require("./avatar/Avatar");
  12. //var EventEmitter = require("events");
  13. var SettingsMenu = require("./side_pannels/settings/SettingsMenu");
  14. var Settings = require("./side_pannels/settings/Settings");
  15. var PanelToggler = require("./side_pannels/SidePanelToggler");
  16. var RoomNameGenerator = require("./welcome_page/RoomnameGenerator");
  17. UI.messageHandler = require("./util/MessageHandler");
  18. var messageHandler = UI.messageHandler;
  19. //var eventEmitter = new EventEmitter();
  20. function setupPrezi()
  21. {
  22. $("#reloadPresentationLink").click(function()
  23. {
  24. Prezi.reloadPresentation();
  25. });
  26. }
  27. function setupChat()
  28. {
  29. Chat.init();
  30. $("#toggle_smileys").click(function() {
  31. Chat.toggleSmileys();
  32. });
  33. }
  34. function setupToolbars() {
  35. Toolbar.init();
  36. Toolbar.setupButtonsFromConfig();
  37. BottomToolbar.init();
  38. }
  39. function registerListeners() {
  40. RTC.addStreamListener(function (stream) {
  41. switch (stream.type)
  42. {
  43. case "audio":
  44. VideoLayout.changeLocalAudio(stream.getOriginalStream());
  45. break;
  46. case "video":
  47. VideoLayout.changeLocalVideo(stream.getOriginalStream(), true);
  48. break;
  49. case "stream":
  50. VideoLayout.changeLocalStream(stream.getOriginalStream());
  51. break;
  52. case "desktop":
  53. VideoLayout.changeLocalVideo(stream, !isUsingScreenStream);
  54. break;
  55. }
  56. }, StreamEventTypes.EVENT_TYPE_LOCAL_CREATED);
  57. RTC.addStreamListener(function (stream) {
  58. VideoLayout.onRemoteStreamAdded(stream);
  59. }, StreamEventTypes.EVENT_TYPE_REMOTE_CREATED);
  60. // Listen for large video size updates
  61. document.getElementById('largeVideo')
  62. .addEventListener('loadedmetadata', function (e) {
  63. currentVideoWidth = this.videoWidth;
  64. currentVideoHeight = this.videoHeight;
  65. VideoLayout.positionLarge(currentVideoWidth, currentVideoHeight);
  66. });
  67. statistics.addAudioLevelListener(function(jid, audioLevel)
  68. {
  69. var resourceJid;
  70. if(jid === statistics.LOCAL_JID)
  71. {
  72. resourceJid = AudioLevels.LOCAL_LEVEL;
  73. if(RTC.localAudio.isMuted())
  74. {
  75. audioLevel = 0;
  76. }
  77. }
  78. else
  79. {
  80. resourceJid = Strophe.getResourceFromJid(jid);
  81. }
  82. AudioLevels.updateAudioLevel(resourceJid, audioLevel,
  83. UI.getLargeVideoState().userResourceJid);
  84. });
  85. }
  86. function bindEvents()
  87. {
  88. /**
  89. * Resizes and repositions videos in full screen mode.
  90. */
  91. $(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange',
  92. function () {
  93. VideoLayout.resizeLargeVideoContainer();
  94. VideoLayout.positionLarge();
  95. isFullScreen = document.fullScreen ||
  96. document.mozFullScreen ||
  97. document.webkitIsFullScreen;
  98. }
  99. );
  100. $(window).resize(function () {
  101. VideoLayout.resizeLargeVideoContainer();
  102. VideoLayout.positionLarge();
  103. });
  104. }
  105. UI.start = function () {
  106. document.title = interfaceConfig.APP_NAME;
  107. if(config.enableWelcomePage && window.location.pathname == "/" &&
  108. (!window.localStorage.welcomePageDisabled || window.localStorage.welcomePageDisabled == "false"))
  109. {
  110. $("#videoconference_page").hide();
  111. var setupWelcomePage = require("./welcome_page/WelcomePage");
  112. setupWelcomePage();
  113. return;
  114. }
  115. if (interfaceConfig.SHOW_JITSI_WATERMARK) {
  116. var leftWatermarkDiv
  117. = $("#largeVideoContainer div[class='watermark leftwatermark']");
  118. leftWatermarkDiv.css({display: 'block'});
  119. leftWatermarkDiv.parent().get(0).href
  120. = interfaceConfig.JITSI_WATERMARK_LINK;
  121. }
  122. if (interfaceConfig.SHOW_BRAND_WATERMARK) {
  123. var rightWatermarkDiv
  124. = $("#largeVideoContainer div[class='watermark rightwatermark']");
  125. rightWatermarkDiv.css({display: 'block'});
  126. rightWatermarkDiv.parent().get(0).href
  127. = interfaceConfig.BRAND_WATERMARK_LINK;
  128. rightWatermarkDiv.get(0).style.backgroundImage
  129. = "url(images/rightwatermark.png)";
  130. }
  131. if (interfaceConfig.SHOW_POWERED_BY) {
  132. $("#largeVideoContainer>a[class='poweredby']").css({display: 'block'});
  133. }
  134. $("#welcome_page").hide();
  135. $('body').popover({ selector: '[data-toggle=popover]',
  136. trigger: 'click hover',
  137. content: function() {
  138. return this.getAttribute("content") +
  139. KeyboardShortcut.getShortcut(this.getAttribute("shortcut"));
  140. }
  141. });
  142. VideoLayout.resizeLargeVideoContainer();
  143. $("#videospace").mousemove(function () {
  144. return ToolbarToggler.showToolbar();
  145. });
  146. // Set the defaults for prompt dialogs.
  147. jQuery.prompt.setDefaults({persistent: false});
  148. // KeyboardShortcut.init();
  149. registerListeners();
  150. bindEvents();
  151. setupPrezi();
  152. setupToolbars();
  153. setupChat();
  154. document.title = interfaceConfig.APP_NAME;
  155. $("#downloadlog").click(function (event) {
  156. dump(event.target);
  157. });
  158. if(config.enableWelcomePage && window.location.pathname == "/" &&
  159. (!window.localStorage.welcomePageDisabled || window.localStorage.welcomePageDisabled == "false"))
  160. {
  161. $("#videoconference_page").hide();
  162. var setupWelcomePage = require("./welcome_page/WelcomePage");
  163. setupWelcomePage();
  164. return;
  165. }
  166. $("#welcome_page").hide();
  167. document.getElementById('largeVideo').volume = 0;
  168. if (!$('#settings').is(':visible')) {
  169. console.log('init');
  170. init();
  171. } else {
  172. loginInfo.onsubmit = function (e) {
  173. if (e.preventDefault) e.preventDefault();
  174. $('#settings').hide();
  175. init();
  176. };
  177. }
  178. toastr.options = {
  179. "closeButton": true,
  180. "debug": false,
  181. "positionClass": "notification-bottom-right",
  182. "onclick": null,
  183. "showDuration": "300",
  184. "hideDuration": "1000",
  185. "timeOut": "2000",
  186. "extendedTimeOut": "1000",
  187. "showEasing": "swing",
  188. "hideEasing": "linear",
  189. "showMethod": "fadeIn",
  190. "hideMethod": "fadeOut",
  191. "reposition": function() {
  192. if(PanelToggler.isVisible()) {
  193. $("#toast-container").addClass("notification-bottom-right-center");
  194. } else {
  195. $("#toast-container").removeClass("notification-bottom-right-center");
  196. }
  197. },
  198. "newestOnTop": false
  199. };
  200. $('#settingsmenu>input').keyup(function(event){
  201. if(event.keyCode === 13) {//enter
  202. SettingsMenu.update();
  203. }
  204. });
  205. $("#updateSettings").click(function () {
  206. SettingsMenu.update();
  207. });
  208. };
  209. UI.setUserAvatar = function (jid, id) {
  210. Avatar.setUserAvatar(jid, id);
  211. };
  212. UI.toggleSmileys = function () {
  213. Chat.toggleSmileys();
  214. };
  215. UI.chatAddError = function(errorMessage, originalText)
  216. {
  217. return Chat.chatAddError(errorMessage, originalText);
  218. };
  219. UI.chatSetSubject = function(text)
  220. {
  221. return Chat.chatSetSubject(text);
  222. };
  223. UI.updateChatConversation = function (from, displayName, message) {
  224. return Chat.updateChatConversation(from, displayName, message);
  225. };
  226. UI.onMucJoined = function (jid, info) {
  227. Toolbar.updateRoomUrl(window.location.href);
  228. document.getElementById('localNick').appendChild(
  229. document.createTextNode(Strophe.getResourceFromJid(jid) + ' (me)')
  230. );
  231. var settings = Settings.getSettings();
  232. // Add myself to the contact list.
  233. ContactList.addContact(jid, settings.email || settings.uid);
  234. // Once we've joined the muc show the toolbar
  235. ToolbarToggler.showToolbar();
  236. // Show authenticate button if needed
  237. Toolbar.showAuthenticateButton(
  238. Moderator.isExternalAuthEnabled() && !Moderator.isModerator());
  239. var displayName = !config.displayJids
  240. ? info.displayName : Strophe.getResourceFromJid(jid);
  241. if (displayName)
  242. $(document).trigger('displaynamechanged',
  243. ['localVideoContainer', displayName + ' (me)']);
  244. };
  245. UI.initEtherpad = function (name) {
  246. Etherpad.init(name);
  247. };
  248. UI.onMucLeft = function (jid) {
  249. console.log('left.muc', jid);
  250. var displayName = $('#participant_' + Strophe.getResourceFromJid(jid) +
  251. '>.displayname').html();
  252. messageHandler.notify(displayName || 'Somebody',
  253. 'disconnected',
  254. 'disconnected');
  255. // Need to call this with a slight delay, otherwise the element couldn't be
  256. // found for some reason.
  257. // XXX(gp) it works fine without the timeout for me (with Chrome 38).
  258. window.setTimeout(function () {
  259. var container = document.getElementById(
  260. 'participant_' + Strophe.getResourceFromJid(jid));
  261. if (container) {
  262. ContactList.removeContact(jid);
  263. VideoLayout.removeConnectionIndicator(jid);
  264. // hide here, wait for video to close before removing
  265. $(container).hide();
  266. VideoLayout.resizeThumbnails();
  267. }
  268. }, 10);
  269. // Unlock large video
  270. if (focusedVideoInfo && focusedVideoInfo.jid === jid)
  271. {
  272. console.info("Focused video owner has left the conference");
  273. focusedVideoInfo = null;
  274. }
  275. };
  276. UI.getSettings = function () {
  277. return Settings.getSettings();
  278. };
  279. UI.toggleFilmStrip = function () {
  280. return BottomToolbar.toggleFilmStrip();
  281. };
  282. UI.toggleChat = function () {
  283. return BottomToolbar.toggleChat();
  284. };
  285. UI.toggleContactList = function () {
  286. return BottomToolbar.toggleContactList();
  287. };
  288. UI.onLocalRoleChange = function (jid, info, pres) {
  289. console.info("My role changed, new role: " + info.role);
  290. var isModerator = Moderator.isModerator();
  291. VideoLayout.showModeratorIndicator();
  292. Toolbar.showAuthenticateButton(
  293. Moderator.isExternalAuthEnabled() && !isModerator);
  294. if (isModerator) {
  295. Toolbar.closeAuthenticationWindow();
  296. messageHandler.notify(
  297. 'Me', 'connected', 'Moderator rights granted !');
  298. }
  299. };
  300. UI.onDisposeConference = function (unload) {
  301. Toolbar.showAuthenticateButton(false);
  302. };
  303. UI.onModeratorStatusChanged = function (isModerator) {
  304. Toolbar.showSipCallButton(isModerator);
  305. Toolbar.showRecordingButton(
  306. isModerator); //&&
  307. // FIXME:
  308. // Recording visible if
  309. // there are at least 2(+ 1 focus) participants
  310. //Object.keys(connection.emuc.members).length >= 3);
  311. if (isModerator && config.etherpad_base) {
  312. Etherpad.init();
  313. }
  314. };
  315. UI.onPasswordReqiured = function (callback) {
  316. // password is required
  317. Toolbar.lockLockButton();
  318. messageHandler.openTwoButtonDialog(null,
  319. '<h2>Password required</h2>' +
  320. '<input id="lockKey" type="text" placeholder="password" autofocus>',
  321. true,
  322. "Ok",
  323. function (e, v, m, f) {},
  324. function (event) {
  325. document.getElementById('lockKey').focus();
  326. },
  327. function (e, v, m, f) {
  328. if (v) {
  329. var lockKey = document.getElementById('lockKey');
  330. if (lockKey.value !== null) {
  331. Toolbar.setSharedKey(lockKey.value);
  332. callback(lockKey.value);
  333. }
  334. }
  335. }
  336. );
  337. };
  338. UI.onAuthenticationRequired = function () {
  339. // This is the loop that will wait for the room to be created by
  340. // someone else. 'auth_required.moderator' will bring us back here.
  341. authRetryId = window.setTimeout(
  342. function () {
  343. Moderator.allocateConferenceFocus(roomName, doJoinAfterFocus);
  344. }, 5000);
  345. // Show prompt only if it's not open
  346. if (authDialog !== null) {
  347. return;
  348. }
  349. // extract room name from 'room@muc.server.net'
  350. var room = roomName.substr(0, roomName.indexOf('@'));
  351. authDialog = messageHandler.openDialog(
  352. 'Stop',
  353. 'Authentication is required to create room:<br/><b>' + room +
  354. '</b></br> You can either authenticate to create the room or ' +
  355. 'just wait for someone else to do so.',
  356. true,
  357. {
  358. Authenticate: 'authNow'
  359. },
  360. function (onSubmitEvent, submitValue) {
  361. // Do not close the dialog yet
  362. onSubmitEvent.preventDefault();
  363. // Open login popup
  364. if (submitValue === 'authNow') {
  365. Toolbar.authenticateClicked();
  366. }
  367. }
  368. );
  369. };
  370. UI.setRecordingButtonState = function (state) {
  371. Toolbar.setRecordingButtonState(state);
  372. };
  373. UI.changeDesktopSharingButtonState = function (isUsingScreenStream) {
  374. Toolbar.changeDesktopSharingButtonState(isUsingScreenStream);
  375. };
  376. UI.inputDisplayNameHandler = function (value) {
  377. VideoLayout.inputDisplayNameHandler(value);
  378. };
  379. UI.onMucEntered = function (jid, id, displayName) {
  380. messageHandler.notify(displayName || 'Somebody',
  381. 'connected',
  382. 'connected');
  383. // Add Peer's container
  384. VideoLayout.ensurePeerContainerExists(jid,id);
  385. };
  386. UI.onMucPresenceStatus = function ( jid, info) {
  387. VideoLayout.setPresenceStatus(
  388. 'participant_' + Strophe.getResourceFromJid(jid), info.status);
  389. };
  390. UI.onMucRoleChanged = function (role, displayName) {
  391. VideoLayout.showModeratorIndicator();
  392. if (role === 'moderator') {
  393. var displayName = displayName;
  394. if (!displayName) {
  395. displayName = 'Somebody';
  396. }
  397. messageHandler.notify(
  398. displayName,
  399. 'connected',
  400. 'Moderator rights granted to ' + displayName + '!');
  401. }
  402. };
  403. UI.updateLocalConnectionStats = function(percent, stats)
  404. {
  405. VideoLayout.updateLocalConnectionStats(percent, stats);
  406. };
  407. UI.updateConnectionStats = function(jid, percent, stats)
  408. {
  409. VideoLayout.updateConnectionStats(jid, percent, stats);
  410. };
  411. UI.onStatsStop = function () {
  412. VideoLayout.onStatsStop();
  413. };
  414. UI.getLargeVideoState = function()
  415. {
  416. return VideoLayout.getLargeVideoState();
  417. };
  418. UI.showLocalAudioIndicator = function (mute) {
  419. VideoLayout.showLocalAudioIndicator(mute);
  420. };
  421. UI.changeLocalVideo = function (stream, flipx) {
  422. VideoLayout.changeLocalVideo(stream, flipx);
  423. };
  424. UI.generateRoomName = function() {
  425. var roomnode = null;
  426. var path = window.location.pathname;
  427. // determinde the room node from the url
  428. // TODO: just the roomnode or the whole bare jid?
  429. if (config.getroomnode && typeof config.getroomnode === 'function') {
  430. // custom function might be responsible for doing the pushstate
  431. roomnode = config.getroomnode(path);
  432. } else {
  433. /* fall back to default strategy
  434. * this is making assumptions about how the URL->room mapping happens.
  435. * It currently assumes deployment at root, with a rewrite like the
  436. * following one (for nginx):
  437. location ~ ^/([a-zA-Z0-9]+)$ {
  438. rewrite ^/(.*)$ / break;
  439. }
  440. */
  441. if (path.length > 1) {
  442. roomnode = path.substr(1).toLowerCase();
  443. } else {
  444. var word = RoomNameGenerator.generateRoomWithoutSeparator();
  445. roomnode = word.toLowerCase();
  446. window.history.pushState('VideoChat',
  447. 'Room: ' + word, window.location.pathname + word);
  448. }
  449. }
  450. roomName = roomnode + '@' + config.hosts.muc;
  451. };
  452. UI.connectionIndicatorShowMore = function(id)
  453. {
  454. return VideoLayout.connectionIndicators[id].showMore();
  455. };
  456. UI.showToolbar = function () {
  457. return ToolbarToggler.showToolbar();
  458. };
  459. UI.dockToolbar = function (isDock) {
  460. return ToolbarToggler.dockToolbar(isDock);
  461. };
  462. function dump(elem, filename) {
  463. elem = elem.parentNode;
  464. elem.download = filename || 'meetlog.json';
  465. elem.href = 'data:application/json;charset=utf-8,\n';
  466. var data = {};
  467. if (connection.jingle) {
  468. data = connection.jingle.populateData();
  469. }
  470. var metadata = {};
  471. metadata.time = new Date();
  472. metadata.url = window.location.href;
  473. metadata.ua = navigator.userAgent;
  474. if (connection.logger) {
  475. metadata.xmpp = connection.logger.log;
  476. }
  477. data.metadata = metadata;
  478. elem.href += encodeURIComponent(JSON.stringify(data, null, ' '));
  479. return false;
  480. }
  481. module.exports = UI;