You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

UI.js 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  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("./../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 Authentication = require("./authentication/Authentication");
  20. var UIUtil = require("./util/UIUtil");
  21. var NicknameHandler = require("./util/NicknameHandler");
  22. var CQEvents = require("../../service/connectionquality/CQEvents");
  23. var DesktopSharingEventTypes
  24. = require("../../service/desktopsharing/DesktopSharingEventTypes");
  25. var RTCEvents = require("../../service/RTC/RTCEvents");
  26. var StreamEventTypes = require("../../service/RTC/StreamEventTypes");
  27. var XMPPEvents = require("../../service/xmpp/XMPPEvents");
  28. var MemberEvents = require("../../service/members/Events");
  29. var eventEmitter = new EventEmitter();
  30. var roomName = null;
  31. function setupPrezi()
  32. {
  33. $("#reloadPresentationLink").click(function()
  34. {
  35. Prezi.reloadPresentation();
  36. });
  37. }
  38. function setupChat()
  39. {
  40. Chat.init();
  41. $("#toggle_smileys").click(function() {
  42. Chat.toggleSmileys();
  43. });
  44. }
  45. function setupToolbars() {
  46. Toolbar.init(UI);
  47. Toolbar.setupButtonsFromConfig();
  48. BottomToolbar.init();
  49. }
  50. function streamHandler(stream) {
  51. switch (stream.type)
  52. {
  53. case "audio":
  54. VideoLayout.changeLocalAudio(stream);
  55. break;
  56. case "video":
  57. VideoLayout.changeLocalVideo(stream);
  58. break;
  59. case "stream":
  60. VideoLayout.changeLocalStream(stream);
  61. break;
  62. }
  63. }
  64. function onDisposeConference(unload) {
  65. Toolbar.showAuthenticateButton(false);
  66. };
  67. function onDisplayNameChanged(jid, displayName) {
  68. ContactList.onDisplayNameChange(jid, displayName);
  69. SettingsMenu.onDisplayNameChange(jid, displayName);
  70. VideoLayout.onDisplayNameChanged(jid, displayName);
  71. }
  72. function registerListeners() {
  73. APP.RTC.addStreamListener(streamHandler, StreamEventTypes.EVENT_TYPE_LOCAL_CREATED);
  74. APP.RTC.addStreamListener(streamHandler, StreamEventTypes.EVENT_TYPE_LOCAL_CHANGED);
  75. APP.RTC.addStreamListener(function (stream) {
  76. VideoLayout.onRemoteStreamAdded(stream);
  77. }, StreamEventTypes.EVENT_TYPE_REMOTE_CREATED);
  78. APP.RTC.addStreamListener(function (jid) {
  79. VideoLayout.onVideoTypeChanged(jid);
  80. }, StreamEventTypes.EVENT_TYPE_REMOTE_CHANGED);
  81. APP.RTC.addListener(RTCEvents.LASTN_CHANGED, onLastNChanged);
  82. APP.RTC.addListener(RTCEvents.DOMINANTSPEAKER_CHANGED, function (resourceJid) {
  83. VideoLayout.onDominantSpeakerChanged(resourceJid);
  84. });
  85. APP.RTC.addListener(RTCEvents.LASTN_ENDPOINT_CHANGED,
  86. function (lastNEndpoints, endpointsEnteringLastN, stream) {
  87. VideoLayout.onLastNEndpointsChanged(lastNEndpoints,
  88. endpointsEnteringLastN, stream);
  89. });
  90. APP.RTC.addListener(RTCEvents.SIMULCAST_LAYER_CHANGED,
  91. function (endpointSimulcastLayers) {
  92. VideoLayout.onSimulcastLayersChanged(endpointSimulcastLayers);
  93. });
  94. APP.RTC.addListener(RTCEvents.SIMULCAST_LAYER_CHANGING,
  95. function (endpointSimulcastLayers) {
  96. VideoLayout.onSimulcastLayersChanging(endpointSimulcastLayers);
  97. });
  98. APP.RTC.addListener(RTCEvents.AVAILABLE_DEVICES_CHANGED,
  99. function (devices) {
  100. VideoLayout.setDeviceAvailabilityIcons(null, devices);
  101. })
  102. APP.statistics.addAudioLevelListener(function(jid, audioLevel)
  103. {
  104. var resourceJid;
  105. if(jid === APP.statistics.LOCAL_JID)
  106. {
  107. resourceJid = AudioLevels.LOCAL_LEVEL;
  108. if(APP.RTC.localAudio.isMuted())
  109. {
  110. audioLevel = 0;
  111. }
  112. }
  113. else
  114. {
  115. resourceJid = Strophe.getResourceFromJid(jid);
  116. }
  117. AudioLevels.updateAudioLevel(resourceJid, audioLevel,
  118. UI.getLargeVideoState().userResourceJid);
  119. });
  120. APP.desktopsharing.addListener(function () {
  121. ToolbarToggler.showDesktopSharingButton();
  122. }, DesktopSharingEventTypes.INIT);
  123. APP.desktopsharing.addListener(
  124. Toolbar.changeDesktopSharingButtonState,
  125. DesktopSharingEventTypes.SWITCHING_DONE);
  126. APP.connectionquality.addListener(CQEvents.LOCALSTATS_UPDATED,
  127. VideoLayout.updateLocalConnectionStats);
  128. APP.connectionquality.addListener(CQEvents.REMOTESTATS_UPDATED,
  129. VideoLayout.updateConnectionStats);
  130. APP.connectionquality.addListener(CQEvents.STOP,
  131. VideoLayout.onStatsStop);
  132. APP.xmpp.addListener(XMPPEvents.DISPOSE_CONFERENCE, onDisposeConference);
  133. APP.xmpp.addListener(XMPPEvents.GRACEFUL_SHUTDOWN, function () {
  134. messageHandler.openMessageDialog(
  135. 'dialog.serviceUnavailable',
  136. 'dialog.gracefulShutdown'
  137. );
  138. });
  139. APP.xmpp.addListener(XMPPEvents.RESERVATION_ERROR, function (code, msg) {
  140. var title = APP.translation.generateTranslatonHTML(
  141. "dialog.reservationError");
  142. var message = APP.translation.generateTranslatonHTML(
  143. "dialog.reservationErrorMsg", {code: code, msg: msg});
  144. messageHandler.openDialog(
  145. title,
  146. message,
  147. true, {},
  148. function (event, value, message, formVals)
  149. {
  150. return false;
  151. }
  152. );
  153. });
  154. APP.xmpp.addListener(XMPPEvents.KICKED, function () {
  155. messageHandler.openMessageDialog("dialog.sessTerminated",
  156. "dialog.kickMessage");
  157. });
  158. APP.xmpp.addListener(XMPPEvents.MUC_DESTROYED, function (reason) {
  159. //FIXME: use Session Terminated from translation, but
  160. // 'reason' text comes from XMPP packet and is not translated
  161. var title = APP.translation.generateTranslatonHTML("dialog.sessTerminated");
  162. messageHandler.openDialog(
  163. title, reason, true, {},
  164. function (event, value, message, formVals)
  165. {
  166. return false;
  167. }
  168. );
  169. });
  170. APP.xmpp.addListener(XMPPEvents.BRIDGE_DOWN, function () {
  171. messageHandler.showError("dialog.error",
  172. "dialog.bridgeUnavailable");
  173. });
  174. APP.xmpp.addListener(XMPPEvents.USER_ID_CHANGED, function (from, id) {
  175. Avatar.setUserAvatar(from, id);
  176. });
  177. APP.xmpp.addListener(XMPPEvents.STREAMS_CHANGED, function (jid, changedStreams) {
  178. for(stream in changedStreams)
  179. {
  180. // might need to update the direction if participant just went from sendrecv to recvonly
  181. if (stream.type === 'video' || stream.type === 'screen') {
  182. var el = $('#participant_' + Strophe.getResourceFromJid(jid) + '>video');
  183. switch (stream.direction) {
  184. case 'sendrecv':
  185. el.show();
  186. break;
  187. case 'recvonly':
  188. el.hide();
  189. // FIXME: Check if we have to change large video
  190. //VideoLayout.updateLargeVideo(el);
  191. break;
  192. }
  193. }
  194. }
  195. });
  196. APP.xmpp.addListener(XMPPEvents.DISPLAY_NAME_CHANGED, onDisplayNameChanged);
  197. APP.xmpp.addListener(XMPPEvents.MUC_JOINED, onMucJoined);
  198. APP.xmpp.addListener(XMPPEvents.LOCAL_ROLE_CHANGED, onLocalRoleChanged);
  199. APP.xmpp.addListener(XMPPEvents.MUC_MEMBER_JOINED, onMucMemberJoined);
  200. APP.xmpp.addListener(XMPPEvents.MUC_ROLE_CHANGED, onMucRoleChanged);
  201. APP.xmpp.addListener(XMPPEvents.PRESENCE_STATUS, onMucPresenceStatus);
  202. APP.xmpp.addListener(XMPPEvents.SUBJECT_CHANGED, chatSetSubject);
  203. APP.xmpp.addListener(XMPPEvents.MESSAGE_RECEIVED, updateChatConversation);
  204. APP.xmpp.addListener(XMPPEvents.MUC_MEMBER_LEFT, onMucMemberLeft);
  205. APP.xmpp.addListener(XMPPEvents.PASSWORD_REQUIRED, onPasswordRequired);
  206. APP.xmpp.addListener(XMPPEvents.CHAT_ERROR_RECEIVED, chatAddError);
  207. APP.xmpp.addListener(XMPPEvents.ETHERPAD, initEtherpad);
  208. APP.xmpp.addListener(XMPPEvents.AUTHENTICATION_REQUIRED,
  209. onAuthenticationRequired);
  210. APP.xmpp.addListener(XMPPEvents.DEVICE_AVAILABLE,
  211. function (resource, devices) {
  212. VideoLayout.setDeviceAvailabilityIcons(resource, devices);
  213. });
  214. APP.members.addListener(MemberEvents.DTMF_SUPPORT_CHANGED,
  215. onDtmfSupportChanged);
  216. }
  217. /**
  218. * Mutes/unmutes the local video.
  219. *
  220. * @param mute <tt>true</tt> to mute the local video; otherwise, <tt>false</tt>
  221. * @param options an object which specifies optional arguments such as the
  222. * <tt>boolean</tt> key <tt>byUser</tt> with default value <tt>true</tt> which
  223. * specifies whether the method was initiated in response to a user command (in
  224. * contrast to an automatic decision taken by the application logic)
  225. */
  226. function setVideoMute(mute, options) {
  227. APP.RTC.setVideoMute(mute,
  228. UI.setVideoMuteButtonsState,
  229. options);
  230. }
  231. function bindEvents()
  232. {
  233. /**
  234. * Resizes and repositions videos in full screen mode.
  235. */
  236. $(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange',
  237. function () {
  238. VideoLayout.resizeLargeVideoContainer();
  239. VideoLayout.positionLarge();
  240. }
  241. );
  242. $(window).resize(function () {
  243. VideoLayout.resizeLargeVideoContainer();
  244. VideoLayout.positionLarge();
  245. });
  246. }
  247. UI.start = function (init) {
  248. document.title = interfaceConfig.APP_NAME;
  249. if(config.enableWelcomePage && window.location.pathname == "/" &&
  250. (!window.localStorage.welcomePageDisabled || window.localStorage.welcomePageDisabled == "false"))
  251. {
  252. $("#videoconference_page").hide();
  253. var setupWelcomePage = require("./welcome_page/WelcomePage");
  254. setupWelcomePage();
  255. return;
  256. }
  257. if (interfaceConfig.SHOW_JITSI_WATERMARK) {
  258. var leftWatermarkDiv
  259. = $("#largeVideoContainer div[class='watermark leftwatermark']");
  260. leftWatermarkDiv.css({display: 'block'});
  261. leftWatermarkDiv.parent().get(0).href
  262. = interfaceConfig.JITSI_WATERMARK_LINK;
  263. }
  264. if (interfaceConfig.SHOW_BRAND_WATERMARK) {
  265. var rightWatermarkDiv
  266. = $("#largeVideoContainer div[class='watermark rightwatermark']");
  267. rightWatermarkDiv.css({display: 'block'});
  268. rightWatermarkDiv.parent().get(0).href
  269. = interfaceConfig.BRAND_WATERMARK_LINK;
  270. rightWatermarkDiv.get(0).style.backgroundImage
  271. = "url(images/rightwatermark.png)";
  272. }
  273. if (interfaceConfig.SHOW_POWERED_BY) {
  274. $("#largeVideoContainer>a[class='poweredby']").css({display: 'block'});
  275. }
  276. $("#welcome_page").hide();
  277. VideoLayout.resizeLargeVideoContainer();
  278. $("#videospace").mousemove(function () {
  279. return ToolbarToggler.showToolbar();
  280. });
  281. // Set the defaults for prompt dialogs.
  282. jQuery.prompt.setDefaults({persistent: false});
  283. VideoLayout.init(eventEmitter);
  284. AudioLevels.init();
  285. NicknameHandler.init(eventEmitter);
  286. registerListeners();
  287. bindEvents();
  288. setupPrezi();
  289. setupToolbars();
  290. setupChat();
  291. document.title = interfaceConfig.APP_NAME;
  292. $("#downloadlog").click(function (event) {
  293. dump(event.target);
  294. });
  295. if(config.enableWelcomePage && window.location.pathname == "/" &&
  296. (!window.localStorage.welcomePageDisabled || window.localStorage.welcomePageDisabled == "false"))
  297. {
  298. $("#videoconference_page").hide();
  299. var setupWelcomePage = require("./welcome_page/WelcomePage");
  300. setupWelcomePage();
  301. return;
  302. }
  303. $("#welcome_page").hide();
  304. // Display notice message at the top of the toolbar
  305. if (config.noticeMessage) {
  306. $('#noticeText').text(config.noticeMessage);
  307. $('#notice').css({display: 'block'});
  308. }
  309. document.getElementById('largeVideo').volume = 0;
  310. if (!$('#settings').is(':visible')) {
  311. console.log('init');
  312. init();
  313. } else {
  314. loginInfo.onsubmit = function (e) {
  315. if (e.preventDefault) e.preventDefault();
  316. $('#settings').hide();
  317. init();
  318. };
  319. }
  320. toastr.options = {
  321. "closeButton": true,
  322. "debug": false,
  323. "positionClass": "notification-bottom-right",
  324. "onclick": null,
  325. "showDuration": "300",
  326. "hideDuration": "1000",
  327. "timeOut": "2000",
  328. "extendedTimeOut": "1000",
  329. "showEasing": "swing",
  330. "hideEasing": "linear",
  331. "showMethod": "fadeIn",
  332. "hideMethod": "fadeOut",
  333. "reposition": function() {
  334. if(PanelToggler.isVisible()) {
  335. $("#toast-container").addClass("notification-bottom-right-center");
  336. } else {
  337. $("#toast-container").removeClass("notification-bottom-right-center");
  338. }
  339. },
  340. "newestOnTop": false
  341. };
  342. SettingsMenu.init();
  343. };
  344. function chatAddError(errorMessage, originalText)
  345. {
  346. return Chat.chatAddError(errorMessage, originalText);
  347. };
  348. function chatSetSubject(text)
  349. {
  350. return Chat.chatSetSubject(text);
  351. };
  352. function updateChatConversation(from, displayName, message) {
  353. return Chat.updateChatConversation(from, displayName, message);
  354. };
  355. function onMucJoined(jid, info) {
  356. Toolbar.updateRoomUrl(window.location.href);
  357. var meHTML = APP.translation.generateTranslatonHTML("me");
  358. $("#localNick").html(Strophe.getResourceFromJid(jid) + " (" + meHTML + ")");
  359. var settings = Settings.getSettings();
  360. // Add myself to the contact list.
  361. ContactList.addContact(jid, settings.email || settings.uid);
  362. // Once we've joined the muc show the toolbar
  363. ToolbarToggler.showToolbar();
  364. var displayName = !config.displayJids
  365. ? info.displayName : Strophe.getResourceFromJid(jid);
  366. if (displayName)
  367. onDisplayNameChanged('localVideoContainer', displayName);
  368. }
  369. function initEtherpad(name) {
  370. Etherpad.init(name);
  371. };
  372. function onMucMemberLeft(jid) {
  373. console.log('left.muc', jid);
  374. var displayName = $('#participant_' + Strophe.getResourceFromJid(jid) +
  375. '>.displayname').html();
  376. messageHandler.notify(displayName,'notify.somebody',
  377. 'disconnected',
  378. 'notify.disconnected');
  379. // Need to call this with a slight delay, otherwise the element couldn't be
  380. // found for some reason.
  381. // XXX(gp) it works fine without the timeout for me (with Chrome 38).
  382. window.setTimeout(function () {
  383. var container = document.getElementById(
  384. 'participant_' + Strophe.getResourceFromJid(jid));
  385. if (container) {
  386. ContactList.removeContact(jid);
  387. VideoLayout.removeConnectionIndicator(jid);
  388. // hide here, wait for video to close before removing
  389. $(container).hide();
  390. VideoLayout.resizeThumbnails();
  391. }
  392. }, 10);
  393. VideoLayout.participantLeft(jid);
  394. };
  395. function onLocalRoleChanged(jid, info, pres, isModerator)
  396. {
  397. console.info("My role changed, new role: " + info.role);
  398. onModeratorStatusChanged(isModerator);
  399. VideoLayout.showModeratorIndicator();
  400. if (isModerator) {
  401. Authentication.closeAuthenticationWindow();
  402. messageHandler.notify(null, "notify.me",
  403. 'connected', "notify.moderator");
  404. }
  405. }
  406. function onModeratorStatusChanged(isModerator) {
  407. Toolbar.showSipCallButton(isModerator);
  408. Toolbar.showRecordingButton(
  409. isModerator); //&&
  410. // FIXME:
  411. // Recording visible if
  412. // there are at least 2(+ 1 focus) participants
  413. //Object.keys(connection.emuc.members).length >= 3);
  414. if (isModerator && config.etherpad_base) {
  415. Etherpad.init();
  416. }
  417. };
  418. function onPasswordRequired(callback) {
  419. // password is required
  420. Toolbar.lockLockButton();
  421. var message = '<h2 data-i18n="dialog.passwordRequired">';
  422. message += APP.translation.translateString(
  423. "dialog.passwordRequired");
  424. message += '</h2>' +
  425. '<input name="lockKey" type="text" data-i18n=' +
  426. '"[placeholder]dialog.password" placeholder="' +
  427. APP.translation.translateString("dialog.password") +
  428. '" autofocus>';
  429. messageHandler.openTwoButtonDialog(null, null, null, message,
  430. true,
  431. "dialog.Ok",
  432. function (e, v, m, f) {},
  433. null,
  434. function (e, v, m, f) {
  435. if (v) {
  436. var lockKey = f.lockKey;
  437. if (lockKey) {
  438. Toolbar.setSharedKey(lockKey);
  439. callback(lockKey);
  440. }
  441. }
  442. },
  443. ':input:first'
  444. );
  445. }
  446. /**
  447. * The dialpad button is shown iff there is at least one member that supports
  448. * DTMF (e.g. jigasi).
  449. */
  450. function onDtmfSupportChanged(dtmfSupport) {
  451. //TODO: enable when the UI is ready
  452. //Toolbar.showDialPadButton(dtmfSupport);
  453. }
  454. function onMucMemberJoined(jid, id, displayName) {
  455. messageHandler.notify(displayName,'notify.somebody',
  456. 'connected',
  457. 'notify.connected');
  458. // Add Peer's container
  459. VideoLayout.ensurePeerContainerExists(jid,id);
  460. }
  461. function onMucPresenceStatus( jid, info) {
  462. VideoLayout.setPresenceStatus(
  463. 'participant_' + Strophe.getResourceFromJid(jid), info.status);
  464. }
  465. function onMucRoleChanged(role, displayName) {
  466. VideoLayout.showModeratorIndicator();
  467. if (role === 'moderator') {
  468. var messageKey, messageOptions = {};
  469. if (!displayName) {
  470. messageKey = "notify.grantedToUnknown";
  471. }
  472. else
  473. {
  474. messageKey = "notify.grantedTo";
  475. messageOptions = {to: displayName};
  476. }
  477. messageHandler.notify(
  478. displayName,'notify.somebody',
  479. 'connected', messageKey,
  480. messageOptions);
  481. }
  482. }
  483. function onAuthenticationRequired(intervalCallback) {
  484. Authentication.openAuthenticationDialog(
  485. roomName, intervalCallback, function () {
  486. Toolbar.authenticateClicked();
  487. });
  488. };
  489. function onLastNChanged(oldValue, newValue) {
  490. if (config.muteLocalVideoIfNotInLastN) {
  491. setVideoMute(!newValue, { 'byUser': false });
  492. }
  493. }
  494. UI.toggleSmileys = function () {
  495. Chat.toggleSmileys();
  496. };
  497. UI.getSettings = function () {
  498. return Settings.getSettings();
  499. };
  500. UI.toggleFilmStrip = function () {
  501. return BottomToolbar.toggleFilmStrip();
  502. };
  503. UI.toggleChat = function () {
  504. return BottomToolbar.toggleChat();
  505. };
  506. UI.toggleContactList = function () {
  507. return BottomToolbar.toggleContactList();
  508. };
  509. UI.inputDisplayNameHandler = function (value) {
  510. VideoLayout.inputDisplayNameHandler(value);
  511. };
  512. UI.getLargeVideoState = function()
  513. {
  514. return VideoLayout.getLargeVideoState();
  515. };
  516. UI.generateRoomName = function() {
  517. if(roomName)
  518. return roomName;
  519. var roomnode = null;
  520. var path = window.location.pathname;
  521. // determinde the room node from the url
  522. // TODO: just the roomnode or the whole bare jid?
  523. if (config.getroomnode && typeof config.getroomnode === 'function') {
  524. // custom function might be responsible for doing the pushstate
  525. roomnode = config.getroomnode(path);
  526. } else {
  527. /* fall back to default strategy
  528. * this is making assumptions about how the URL->room mapping happens.
  529. * It currently assumes deployment at root, with a rewrite like the
  530. * following one (for nginx):
  531. location ~ ^/([a-zA-Z0-9]+)$ {
  532. rewrite ^/(.*)$ / break;
  533. }
  534. */
  535. if (path.length > 1) {
  536. roomnode = path.substr(1).toLowerCase();
  537. } else {
  538. var word = RoomNameGenerator.generateRoomWithoutSeparator();
  539. roomnode = word.toLowerCase();
  540. window.history.pushState('VideoChat',
  541. 'Room: ' + word, window.location.pathname + word);
  542. }
  543. }
  544. roomName = roomnode + '@' + config.hosts.muc;
  545. return roomName;
  546. };
  547. UI.connectionIndicatorShowMore = function(id)
  548. {
  549. return VideoLayout.connectionIndicators[id].showMore();
  550. };
  551. UI.showLoginPopup = function(callback)
  552. {
  553. console.log('password is required');
  554. var message = '<h2 data-i18n="dialog.passwordRequired">';
  555. message += APP.translation.translateString(
  556. "dialog.passwordRequired");
  557. message += '</h2>' +
  558. '<input name="username" type="text" ' +
  559. 'placeholder="user@domain.net" autofocus>' +
  560. '<input name="password" ' +
  561. 'type="password" data-i18n="[placeholder]dialog.userPassword"' +
  562. ' placeholder="user password">';
  563. UI.messageHandler.openTwoButtonDialog(null, null, null, message,
  564. true,
  565. "dialog.Ok",
  566. function (e, v, m, f) {
  567. if (v) {
  568. if (f.username !== null && f.password != null) {
  569. callback(f.username, f.password);
  570. }
  571. }
  572. },
  573. null, null, ':input:first'
  574. );
  575. }
  576. UI.checkForNicknameAndJoin = function () {
  577. Authentication.closeAuthenticationDialog();
  578. Authentication.stopInterval();
  579. var nick = null;
  580. if (config.useNicks) {
  581. nick = window.prompt('Your nickname (optional)');
  582. }
  583. APP.xmpp.joinRoom(roomName, config.useNicks, nick);
  584. };
  585. function dump(elem, filename) {
  586. elem = elem.parentNode;
  587. elem.download = filename || 'meetlog.json';
  588. elem.href = 'data:application/json;charset=utf-8,\n';
  589. var data = APP.xmpp.populateData();
  590. var metadata = {};
  591. metadata.time = new Date();
  592. metadata.url = window.location.href;
  593. metadata.ua = navigator.userAgent;
  594. var log = APP.xmpp.getLogger();
  595. if (log) {
  596. metadata.xmpp = log;
  597. }
  598. data.metadata = metadata;
  599. elem.href += encodeURIComponent(JSON.stringify(data, null, ' '));
  600. return false;
  601. }
  602. UI.getRoomName = function () {
  603. return roomName;
  604. };
  605. /**
  606. * Mutes/unmutes the local video.
  607. */
  608. UI.toggleVideo = function () {
  609. setVideoMute(!APP.RTC.localVideo.isMuted());
  610. };
  611. /**
  612. * Mutes / unmutes audio for the local participant.
  613. */
  614. UI.toggleAudio = function() {
  615. UI.setAudioMuted(!APP.RTC.localAudio.isMuted());
  616. };
  617. /**
  618. * Sets muted audio state for the local participant.
  619. */
  620. UI.setAudioMuted = function (mute) {
  621. if(!APP.xmpp.setAudioMute(mute, function () {
  622. VideoLayout.showLocalAudioIndicator(mute);
  623. UIUtil.buttonClick("#mute", "icon-microphone icon-mic-disabled");
  624. }))
  625. {
  626. // We still click the button.
  627. UIUtil.buttonClick("#mute", "icon-microphone icon-mic-disabled");
  628. return;
  629. }
  630. }
  631. UI.addListener = function (type, listener) {
  632. eventEmitter.on(type, listener);
  633. }
  634. UI.clickOnVideo = function (videoNumber) {
  635. var remoteVideos = $(".videocontainer:not(#mixedstream)");
  636. if (remoteVideos.length > videoNumber) {
  637. remoteVideos[videoNumber].click();
  638. }
  639. }
  640. //Used by torture
  641. UI.showToolbar = function () {
  642. return ToolbarToggler.showToolbar();
  643. }
  644. //Used by torture
  645. UI.dockToolbar = function (isDock) {
  646. return ToolbarToggler.dockToolbar(isDock);
  647. }
  648. UI.setVideoMuteButtonsState = function (mute) {
  649. var video = $('#video');
  650. var communicativeClass = "icon-camera";
  651. var muteClass = "icon-camera icon-camera-disabled";
  652. if (mute) {
  653. video.removeClass(communicativeClass);
  654. video.addClass(muteClass);
  655. } else {
  656. video.removeClass(muteClass);
  657. video.addClass(communicativeClass);
  658. }
  659. }
  660. module.exports = UI;