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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. /* global APP,$, buttonClick, config, lockRoom,
  2. setSharedKey, Util */
  3. var messageHandler = require("../util/MessageHandler");
  4. var BottomToolbar = require("./BottomToolbar");
  5. var Prezi = require("../prezi/Prezi");
  6. var Etherpad = require("../etherpad/Etherpad");
  7. var PanelToggler = require("../side_pannels/SidePanelToggler");
  8. var Authentication = require("../authentication/Authentication");
  9. var UIUtil = require("../util/UIUtil");
  10. var AuthenticationEvents
  11. = require("../../../service/authentication/AuthenticationEvents");
  12. var roomUrl = null;
  13. var sharedKey = '';
  14. var UI = null;
  15. var buttonHandlers =
  16. {
  17. "toolbar_button_mute": function () {
  18. return APP.UI.toggleAudio();
  19. },
  20. "toolbar_button_camera": function () {
  21. return APP.UI.toggleVideo();
  22. },
  23. /*"toolbar_button_authentication": function () {
  24. return Toolbar.authenticateClicked();
  25. },*/
  26. "toolbar_button_record": function () {
  27. return toggleRecording();
  28. },
  29. "toolbar_button_security": function () {
  30. return Toolbar.openLockDialog();
  31. },
  32. "toolbar_button_link": function () {
  33. return Toolbar.openLinkDialog();
  34. },
  35. "toolbar_button_chat": function () {
  36. return BottomToolbar.toggleChat();
  37. },
  38. "toolbar_button_prezi": function () {
  39. return Prezi.openPreziDialog();
  40. },
  41. "toolbar_button_etherpad": function () {
  42. return Etherpad.toggleEtherpad(0);
  43. },
  44. "toolbar_button_desktopsharing": function () {
  45. return APP.desktopsharing.toggleScreenSharing();
  46. },
  47. "toolbar_button_fullScreen": function()
  48. {
  49. UIUtil.buttonClick("#fullScreen", "icon-full-screen icon-exit-full-screen");
  50. return Toolbar.toggleFullScreen();
  51. },
  52. "toolbar_button_sip": function () {
  53. return callSipButtonClicked();
  54. },
  55. "toolbar_button_settings": function () {
  56. PanelToggler.toggleSettingsMenu();
  57. },
  58. "toolbar_button_hangup": function () {
  59. return hangup();
  60. },
  61. "toolbar_button_login": function () {
  62. Toolbar.authenticateClicked();
  63. },
  64. "toolbar_button_logout": function () {
  65. // Ask for confirmation
  66. messageHandler.openTwoButtonDialog(
  67. "dialog.logoutTitle", "Logout",
  68. "dialog.logoutQuestion",
  69. "Are you sure you want to logout and stop the conference ?",
  70. false, "Yes",
  71. function (evt, yes) {
  72. if (yes) {
  73. APP.xmpp.logout(function (url) {
  74. if (url) {
  75. window.location.href = url;
  76. } else {
  77. hangup();
  78. }
  79. });
  80. }
  81. });
  82. }
  83. };
  84. function hangup() {
  85. APP.xmpp.disposeConference();
  86. if(config.enableWelcomePage)
  87. {
  88. setTimeout(function()
  89. {
  90. window.localStorage.welcomePageDisabled = false;
  91. window.location.pathname = "/";
  92. }, 10000);
  93. }
  94. var title = APP.translation.generateTranslatonHTML(
  95. "dialog.sessTerminated", "Session Terminated");
  96. var msg = APP.translation.generateTranslatonHTML(
  97. "dialog.hungUp","You hung up the call");
  98. var button = APP.translation.generateTranslatonHTML(
  99. "dialog.joinAgain", "Join again");
  100. var buttons = {};
  101. buttons.joinAgain = {title: button, value: true};
  102. UI.messageHandler.openDialog(
  103. title,
  104. msg,
  105. true,
  106. buttons,
  107. function(event, value, message, formVals)
  108. {
  109. window.location.reload();
  110. return false;
  111. }
  112. );
  113. }
  114. /**
  115. * Starts or stops the recording for the conference.
  116. */
  117. function toggleRecording() {
  118. APP.xmpp.toggleRecording(function (callback) {
  119. var msg = APP.translation.generateTranslatonHTML(
  120. "dialog.recordingToken", "Enter recording token");
  121. APP.UI.messageHandler.openTwoButtonDialog(null, null, null,
  122. '<h2>' + msg + '</h2>' +
  123. '<input id="recordingToken" type="text" ' +
  124. 'placeholder="token" autofocus>',
  125. false,
  126. "dialog.Save",
  127. function (e, v, m, f) {
  128. if (v) {
  129. var token = document.getElementById('recordingToken');
  130. if (token.value) {
  131. callback(UIUtil.escapeHtml(token.value));
  132. }
  133. }
  134. },
  135. function (event) {
  136. document.getElementById('recordingToken').focus();
  137. },
  138. function () {
  139. }
  140. );
  141. }, Toolbar.setRecordingButtonState, Toolbar.setRecordingButtonState);
  142. }
  143. /**
  144. * Locks / unlocks the room.
  145. */
  146. function lockRoom(lock) {
  147. var currentSharedKey = '';
  148. if (lock)
  149. currentSharedKey = sharedKey;
  150. APP.xmpp.lockRoom(currentSharedKey, function (res) {
  151. // password is required
  152. if (sharedKey)
  153. {
  154. console.log('set room password');
  155. Toolbar.lockLockButton();
  156. }
  157. else
  158. {
  159. console.log('removed room password');
  160. Toolbar.unlockLockButton();
  161. }
  162. }, function (err) {
  163. console.warn('setting password failed', err);
  164. messageHandler.showError("dialog.lockTitle", 'Lock failed',
  165. "dialog.lockMessage",
  166. 'Failed to lock conference.',
  167. err);
  168. Toolbar.setSharedKey('');
  169. }, function () {
  170. console.warn('room passwords not supported');
  171. messageHandler.showError("dialog.warning", 'Warning',
  172. "dialog.passwordNotSupported",
  173. 'Room passwords are currently not supported.');
  174. Toolbar.setSharedKey('');
  175. });
  176. };
  177. /**
  178. * Invite participants to conference.
  179. */
  180. function inviteParticipants() {
  181. if (roomUrl === null)
  182. return;
  183. var sharedKeyText = "";
  184. if (sharedKey && sharedKey.length > 0) {
  185. sharedKeyText =
  186. "This conference is password protected. Please use the " +
  187. "following pin when joining:%0D%0A%0D%0A" +
  188. sharedKey + "%0D%0A%0D%0A";
  189. }
  190. var conferenceName = roomUrl.substring(roomUrl.lastIndexOf('/') + 1);
  191. var subject = "Invitation to a " + interfaceConfig.APP_NAME + " (" + conferenceName + ")";
  192. var body = "Hey there, I%27d like to invite you to a " + interfaceConfig.APP_NAME +
  193. " conference I%27ve just set up.%0D%0A%0D%0A" +
  194. "Please click on the following link in order" +
  195. " to join the conference.%0D%0A%0D%0A" +
  196. roomUrl +
  197. "%0D%0A%0D%0A" +
  198. sharedKeyText +
  199. "Note that " + interfaceConfig.APP_NAME + " is currently" +
  200. " only supported by Chromium," +
  201. " Google Chrome and Opera, so you need" +
  202. " to be using one of these browsers.%0D%0A%0D%0A" +
  203. "Talk to you in a sec!";
  204. if (window.localStorage.displayname) {
  205. body += "%0D%0A%0D%0A" + window.localStorage.displayname;
  206. }
  207. if (interfaceConfig.INVITATION_POWERED_BY) {
  208. body += "%0D%0A%0D%0A--%0D%0Apowered by jitsi.org";
  209. }
  210. window.open("mailto:?subject=" + subject + "&body=" + body, '_blank');
  211. }
  212. function callSipButtonClicked()
  213. {
  214. var defaultNumber
  215. = config.defaultSipNumber ? config.defaultSipNumber : '';
  216. var sipMsg = APP.translation.generateTranslatonHTML(
  217. "dialog.sipMsg", "Enter SIP number");
  218. messageHandler.openTwoButtonDialog(null, null, null,
  219. '<h2>' + sipMsg + '</h2>' +
  220. '<input id="sipNumber" type="text"' +
  221. ' value="' + defaultNumber + '" autofocus>',
  222. false,
  223. "dialog.Dial",
  224. function (e, v, m, f) {
  225. if (v) {
  226. var numberInput = document.getElementById('sipNumber');
  227. if (numberInput.value) {
  228. APP.xmpp.dial(numberInput.value, 'fromnumber',
  229. UI.getRoomName(), sharedKey);
  230. }
  231. }
  232. },
  233. function (event) {
  234. document.getElementById('sipNumber').focus();
  235. }
  236. );
  237. }
  238. var Toolbar = (function (my) {
  239. my.init = function (ui) {
  240. for(var k in buttonHandlers)
  241. $("#" + k).click(buttonHandlers[k]);
  242. UI = ui;
  243. // Update login info
  244. APP.xmpp.addListener(
  245. AuthenticationEvents.IDENTITY_UPDATED,
  246. function (authenticationEnabled, userIdentity) {
  247. var loggedIn = false;
  248. if (userIdentity) {
  249. loggedIn = true;
  250. }
  251. //FIXME: XMPP authentication need improvements for "live" login
  252. if (!APP.xmpp.isExternalAuthEnabled() && !loggedIn)
  253. {
  254. authenticationEnabled = false;
  255. }
  256. Toolbar.showAuthenticateButton(authenticationEnabled);
  257. if (authenticationEnabled) {
  258. Toolbar.setAuthenticatedIdentity(userIdentity);
  259. Toolbar.showLoginButton(!loggedIn);
  260. Toolbar.showLogoutButton(loggedIn);
  261. }
  262. }
  263. );
  264. },
  265. /**
  266. * Sets shared key
  267. * @param sKey the shared key
  268. */
  269. my.setSharedKey = function (sKey) {
  270. sharedKey = sKey;
  271. };
  272. my.authenticateClicked = function () {
  273. Authentication.focusAuthenticationWindow();
  274. // Get authentication URL
  275. if (!APP.xmpp.getMUCJoined()) {
  276. APP.xmpp.getLoginUrl(UI.getRoomName(), function (url) {
  277. // If conference has not been started yet - redirect to login page
  278. window.location.href = url;
  279. });
  280. } else {
  281. APP.xmpp.getPopupLoginUrl(UI.getRoomName(), function (url) {
  282. // Otherwise - open popup with authentication URL
  283. var authenticationWindow = Authentication.createAuthenticationWindow(
  284. function () {
  285. // On popup closed - retry room allocation
  286. APP.xmpp.allocateConferenceFocus(
  287. APP.UI.getRoomName(),
  288. function () { console.info("AUTH DONE"); }
  289. );
  290. }, url);
  291. if (!authenticationWindow) {
  292. messageHandler.openMessageDialog(
  293. null, null, "dialog.popupError",
  294. "Your browser is blocking popup windows from this site." +
  295. " Please enable popups in your browser security settings" +
  296. " and try again.");
  297. }
  298. });
  299. }
  300. };
  301. /**
  302. * Updates the room invite url.
  303. */
  304. my.updateRoomUrl = function (newRoomUrl) {
  305. roomUrl = newRoomUrl;
  306. // If the invite dialog has been already opened we update the information.
  307. var inviteLink = document.getElementById('inviteLinkRef');
  308. if (inviteLink) {
  309. inviteLink.value = roomUrl;
  310. inviteLink.select();
  311. document.getElementById('jqi_state0_buttonInvite').disabled = false;
  312. }
  313. };
  314. /**
  315. * Disables and enables some of the buttons.
  316. */
  317. my.setupButtonsFromConfig = function () {
  318. if (config.disablePrezi)
  319. {
  320. $("#prezi_button").css({display: "none"});
  321. }
  322. };
  323. /**
  324. * Opens the lock room dialog.
  325. */
  326. my.openLockDialog = function () {
  327. // Only the focus is able to set a shared key.
  328. if (!APP.xmpp.isModerator()) {
  329. if (sharedKey) {
  330. messageHandler.openMessageDialog(null, null,
  331. "dialog.passwordError",
  332. "This conversation is currently protected by" +
  333. " a password. Only the owner of the conference" +
  334. " could set a password.",
  335. false,
  336. "Password");
  337. } else {
  338. messageHandler.openMessageDialog(null, null, "dialog.passwordError2",
  339. "This conversation isn't currently protected by" +
  340. " a password. Only the owner of the conference" +
  341. " could set a password.",
  342. false,
  343. "Password");
  344. }
  345. } else {
  346. if (sharedKey) {
  347. messageHandler.openTwoButtonDialog(null, null,
  348. "dialog.passwordCheck",
  349. "Are you sure you would like to remove your password?",
  350. false,
  351. "dialog.Remove",
  352. function (e, v) {
  353. if (v) {
  354. Toolbar.setSharedKey('');
  355. lockRoom(false);
  356. }
  357. });
  358. } else {
  359. var msg = APP.translation.generateTranslatonHTML(
  360. "dialog.passwordMsg", "Set a password to lock your room");
  361. var yourPassword = APP.translation.translateString(
  362. "dialog.yourPassword", null, "your password");
  363. messageHandler.openTwoButtonDialog(null, null, null,
  364. '<h2>' + msg + '</h2>' +
  365. '<input id="lockKey" type="text"' +
  366. 'placeholder="' + yourPassword + '" autofocus>',
  367. false,
  368. "dialog.Save",
  369. function (e, v) {
  370. if (v) {
  371. var lockKey = document.getElementById('lockKey');
  372. if (lockKey.value) {
  373. Toolbar.setSharedKey(UIUtil.escapeHtml(lockKey.value));
  374. lockRoom(true);
  375. }
  376. }
  377. },
  378. function () {
  379. document.getElementById('lockKey').focus();
  380. }
  381. );
  382. }
  383. }
  384. };
  385. /**
  386. * Opens the invite link dialog.
  387. */
  388. my.openLinkDialog = function () {
  389. var inviteLink;
  390. if (roomUrl === null) {
  391. inviteLink = "Your conference is currently being created...";
  392. } else {
  393. inviteLink = encodeURI(roomUrl);
  394. }
  395. messageHandler.openTwoButtonDialog("dialog.shareLink",
  396. "Share this link with everyone you want to invite", null,
  397. '<input id="inviteLinkRef" type="text" value="' +
  398. inviteLink + '" onclick="this.select();" readonly>',
  399. false,
  400. "dialog.Invite",
  401. function (e, v) {
  402. if (v) {
  403. if (roomUrl) {
  404. inviteParticipants();
  405. }
  406. }
  407. },
  408. function () {
  409. if (roomUrl) {
  410. document.getElementById('inviteLinkRef').select();
  411. } else {
  412. document.getElementById('jqi_state0_buttonInvite')
  413. .disabled = true;
  414. }
  415. }
  416. );
  417. };
  418. /**
  419. * Opens the settings dialog.
  420. */
  421. my.openSettingsDialog = function () {
  422. var settings1 = APP.translation.generateTranslatonHTML(
  423. "dialog.settings1", "Configure your conference");
  424. var settings2 = APP.translation.generateTranslatonHTML(
  425. "dialog.settings2", "Participants join muted");
  426. var settings3 = APP.translation.generateTranslatonHTML(
  427. "dialog.settings3", "Require nicknames<br/><br/>" +
  428. "Set a password to lock your room:");
  429. var yourPassword = APP.translation.translateString(
  430. "dialog.yourPassword", null, "your password");
  431. messageHandler.openTwoButtonDialog(null,
  432. '<h2>' + settings1 + '</h2>' +
  433. '<input type="checkbox" id="initMuted">' +
  434. settings2 + '<br/>' +
  435. '<input type="checkbox" id="requireNicknames">' +
  436. settings3 +
  437. '<input id="lockKey" type="text" placeholder="' + yourPassword +
  438. '" data-i18n="[placeholder]dialog.yourPassword" autofocus>',
  439. null,
  440. null,
  441. false,
  442. "dialog.Save",
  443. function () {
  444. document.getElementById('lockKey').focus();
  445. },
  446. function (e, v) {
  447. if (v) {
  448. if ($('#initMuted').is(":checked")) {
  449. // it is checked
  450. }
  451. if ($('#requireNicknames').is(":checked")) {
  452. // it is checked
  453. }
  454. /*
  455. var lockKey = document.getElementById('lockKey');
  456. if (lockKey.value) {
  457. setSharedKey(lockKey.value);
  458. lockRoom(true);
  459. }
  460. */
  461. }
  462. }
  463. );
  464. };
  465. /**
  466. * Toggles the application in and out of full screen mode
  467. * (a.k.a. presentation mode in Chrome).
  468. */
  469. my.toggleFullScreen = function () {
  470. var fsElement = document.documentElement;
  471. if (!document.mozFullScreen && !document.webkitIsFullScreen) {
  472. //Enter Full Screen
  473. if (fsElement.mozRequestFullScreen) {
  474. fsElement.mozRequestFullScreen();
  475. }
  476. else {
  477. fsElement.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
  478. }
  479. } else {
  480. //Exit Full Screen
  481. if (document.mozCancelFullScreen) {
  482. document.mozCancelFullScreen();
  483. } else {
  484. document.webkitCancelFullScreen();
  485. }
  486. }
  487. };
  488. /**
  489. * Unlocks the lock button state.
  490. */
  491. my.unlockLockButton = function () {
  492. if ($("#lockIcon").hasClass("icon-security-locked"))
  493. UIUtil.buttonClick("#lockIcon", "icon-security icon-security-locked");
  494. };
  495. /**
  496. * Updates the lock button state to locked.
  497. */
  498. my.lockLockButton = function () {
  499. if ($("#lockIcon").hasClass("icon-security"))
  500. UIUtil.buttonClick("#lockIcon", "icon-security icon-security-locked");
  501. };
  502. /**
  503. * Shows or hides authentication button
  504. * @param show <tt>true</tt> to show or <tt>false</tt> to hide
  505. */
  506. my.showAuthenticateButton = function (show) {
  507. if (show) {
  508. $('#authentication').css({display: "inline"});
  509. }
  510. else {
  511. $('#authentication').css({display: "none"});
  512. }
  513. };
  514. // Shows or hides the 'recording' button.
  515. my.showRecordingButton = function (show) {
  516. if (!config.enableRecording) {
  517. return;
  518. }
  519. if (show) {
  520. $('#recording').css({display: "inline"});
  521. }
  522. else {
  523. $('#recording').css({display: "none"});
  524. }
  525. };
  526. // Sets the state of the recording button
  527. my.setRecordingButtonState = function (isRecording) {
  528. if (isRecording) {
  529. $('#recordButton').removeClass("icon-recEnable");
  530. $('#recordButton').addClass("icon-recEnable active");
  531. } else {
  532. $('#recordButton').removeClass("icon-recEnable active");
  533. $('#recordButton').addClass("icon-recEnable");
  534. }
  535. };
  536. // Shows or hides SIP calls button
  537. my.showSipCallButton = function (show) {
  538. if (APP.xmpp.isSipGatewayEnabled() && show) {
  539. $('#sipCallButton').css({display: "inline-block"});
  540. } else {
  541. $('#sipCallButton').css({display: "none"});
  542. }
  543. };
  544. /**
  545. * Displays user authenticated identity name(login).
  546. * @param authIdentity identity name to be displayed.
  547. */
  548. my.setAuthenticatedIdentity = function (authIdentity) {
  549. if (authIdentity) {
  550. $('#toolbar_auth_identity').css({display: "list-item"});
  551. $('#toolbar_auth_identity').text(authIdentity);
  552. } else {
  553. $('#toolbar_auth_identity').css({display: "none"});
  554. }
  555. };
  556. /**
  557. * Shows/hides login button.
  558. * @param show <tt>true</tt> to show
  559. */
  560. my.showLoginButton = function (show) {
  561. if (show) {
  562. $('#toolbar_button_login').css({display: "list-item"});
  563. } else {
  564. $('#toolbar_button_login').css({display: "none"});
  565. }
  566. };
  567. /**
  568. * Shows/hides logout button.
  569. * @param show <tt>true</tt> to show
  570. */
  571. my.showLogoutButton = function (show) {
  572. if (show) {
  573. $('#toolbar_button_logout').css({display: "list-item"});
  574. } else {
  575. $('#toolbar_button_logout').css({display: "none"});
  576. }
  577. };
  578. /**
  579. * Sets the state of the button. The button has blue glow if desktop
  580. * streaming is active.
  581. * @param active the state of the desktop streaming.
  582. */
  583. my.changeDesktopSharingButtonState = function (active) {
  584. var button = $("#desktopsharing > a");
  585. if (active)
  586. {
  587. button.addClass("glow");
  588. }
  589. else
  590. {
  591. button.removeClass("glow");
  592. }
  593. };
  594. return my;
  595. }(Toolbar || {}));
  596. module.exports = Toolbar;