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.

721 lines
23 KiB

  1. /* global Marionette, Backbone, OCA */
  2. /**
  3. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  4. *
  5. * @license GNU AGPL version 3 or any later version
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU Affero General Public License as
  9. * published by the Free Software Foundation, either version 3 of the
  10. * License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Affero General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. *
  20. */
  21. (function(OCA, Marionette, Backbone, _) {
  22. 'use strict';
  23. OCA.SpreedMe = OCA.SpreedMe || {};
  24. var roomChannel = Backbone.Radio.channel('rooms');
  25. var App = Marionette.Application.extend({
  26. OWNER: 1,
  27. MODERATOR: 2,
  28. USER: 3,
  29. GUEST: 4,
  30. USERSELFJOINED: 5,
  31. /** @property {OCA.SpreedMe.Models.Room} activeRoom */
  32. activeRoom: null,
  33. /** @property {OCA.SpreedMe.Models.RoomCollection} _rooms */
  34. _rooms: null,
  35. /** @property {OCA.SpreedMe.Views.RoomListView} _roomsView */
  36. _roomsView: null,
  37. /** @property {OCA.SpreedMe.Models.ParticipantCollection} _participants */
  38. _participants: null,
  39. /** @property {OCA.SpreedMe.Views.ParticipantView} _participantsView */
  40. _participantsView: null,
  41. /** @property {boolean} videoWasEnabledAtLeastOnce */
  42. videoWasEnabledAtLeastOnce: false,
  43. audioDisabled: localStorage.getItem("audioDisabled"),
  44. videoDisabled: localStorage.getItem("videoDisabled"),
  45. _searchTerm: '',
  46. guestNick: null,
  47. _registerPageEvents: function() {
  48. $('#select-participants').select2({
  49. ajax: {
  50. url: OC.linkToOCS('apps/files_sharing/api/v1') + 'sharees',
  51. dataType: 'json',
  52. quietMillis: 100,
  53. data: function (term) {
  54. OCA.SpreedMe.app._searchTerm = term;
  55. return {
  56. format: 'json',
  57. search: term,
  58. perPage: 200,
  59. itemType: 'call'
  60. };
  61. },
  62. results: function (response) {
  63. // TODO improve error case
  64. if (response.ocs.data === undefined) {
  65. console.error('Failure happened', response);
  66. return;
  67. }
  68. var results = [];
  69. $.each(response.ocs.data.exact.users, function(id, user) {
  70. if (oc_current_user === user.value.shareWith) {
  71. return;
  72. }
  73. results.push({ id: user.value.shareWith, displayName: user.label, type: "user"});
  74. });
  75. $.each(response.ocs.data.exact.groups, function(id, group) {
  76. results.push({ id: group.value.shareWith, displayName: group.label + ' ' + t('spreed', '(group)'), type: "group"});
  77. });
  78. $.each(response.ocs.data.users, function(id, user) {
  79. if (oc_current_user === user.value.shareWith) {
  80. return;
  81. }
  82. results.push({ id: user.value.shareWith, displayName: user.label, type: "user"});
  83. });
  84. $.each(response.ocs.data.groups, function(id, group) {
  85. results.push({ id: group.value.shareWith, displayName: group.label + ' ' + t('spreed', '(group)'), type: "group"});
  86. });
  87. //Add custom entry to create a new empty room
  88. if (OCA.SpreedMe.app._searchTerm === '') {
  89. results.unshift({ id: "create-public-room", displayName: t('spreed', 'New public call'), type: "createPublicRoom"});
  90. } else {
  91. results.push({ id: "create-public-room", displayName: t('spreed', 'New public call'), type: "createPublicRoom"});
  92. }
  93. return {
  94. results: results,
  95. more: false
  96. };
  97. }
  98. },
  99. initSelection: function (element, callback) {
  100. console.log(element);
  101. callback({id: element.val()});
  102. },
  103. formatResult: function (element) {
  104. if (element.type === "createPublicRoom") {
  105. return '<span><div class="avatar icon-add"></div>' + escapeHTML(element.displayName) + '</span>';
  106. }
  107. return '<span><div class="avatar" data-user="' + escapeHTML(element.id) + '" data-user-display-name="' + escapeHTML(element.displayName) + '"></div>' + escapeHTML(element.displayName) + '</span>';
  108. },
  109. formatSelection: function () {
  110. return '<span class="select2-default" style="padding-left: 0;">'+OC.L10N.translate('spreed', 'Choose person…')+'</span>';
  111. }
  112. });
  113. $('#select-participants').on("click", function() {
  114. $('.select2-drop').find('.avatar').each(function () {
  115. var element = $(this);
  116. if (element.data('user-display-name')) {
  117. element.avatar(element.data('user'), 32, undefined, false, undefined, element.data('user-display-name'));
  118. } else {
  119. element.avatar(element.data('user'), 32);
  120. }
  121. });
  122. });
  123. $('#select-participants').on("select2-selecting", function(e) {
  124. switch (e.object.type) {
  125. case "user":
  126. OCA.SpreedMe.Calls.createOneToOneVideoCall(e.val);
  127. break;
  128. case "group":
  129. OCA.SpreedMe.Calls.createGroupVideoCall(e.val);
  130. break;
  131. case "createPublicRoom":
  132. OCA.SpreedMe.Calls.createPublicVideoCall();
  133. break;
  134. default:
  135. console.log("Unknown type", e.object.type);
  136. break;
  137. }
  138. });
  139. $('#select-participants').on("select2-loaded", function() {
  140. $('.select2-drop').find('.avatar').each(function () {
  141. var element = $(this);
  142. if (element.data('user-display-name')) {
  143. element.avatar(element.data('user'), 32, undefined, false, undefined, element.data('user-display-name'));
  144. } else {
  145. element.avatar(element.data('user'), 32);
  146. }
  147. });
  148. });
  149. // Initialize button tooltips
  150. $('[data-toggle="tooltip"]').tooltip({trigger: 'hover'}).click(function() {
  151. $(this).tooltip('hide');
  152. });
  153. $('#hideVideo').click(function() {
  154. if(!OCA.SpreedMe.app.videoWasEnabledAtLeastOnce) {
  155. // don't allow clicking the video toggle
  156. // when no video ever was streamed (that
  157. // means that permission wasn't granted
  158. // yet or there is no video available at
  159. // all)
  160. console.log('video can not be enabled - there was no stream available before');
  161. return;
  162. }
  163. if ($(this).hasClass('video-disabled')) {
  164. OCA.SpreedMe.app.enableVideo();
  165. localStorage.removeItem("videoDisabled");
  166. } else {
  167. OCA.SpreedMe.app.disableVideo();
  168. localStorage.setItem("videoDisabled", true);
  169. }
  170. });
  171. $('#mute').click(function() {
  172. if (OCA.SpreedMe.webrtc.webrtc.isAudioEnabled()) {
  173. OCA.SpreedMe.app.disableAudio();
  174. localStorage.setItem("audioDisabled", true);
  175. } else {
  176. OCA.SpreedMe.app.enableAudio();
  177. localStorage.removeItem("audioDisabled");
  178. }
  179. });
  180. $('#video-fullscreen').click(function() {
  181. var fullscreenElem = document.getElementById('app-content');
  182. if (!document.fullscreenElement && !document.mozFullScreenElement &&
  183. !document.webkitFullscreenElement && !document.msFullscreenElement) {
  184. if (fullscreenElem.requestFullscreen) {
  185. fullscreenElem.requestFullscreen();
  186. } else if (fullscreenElem.webkitRequestFullscreen) {
  187. fullscreenElem.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
  188. } else if (fullscreenElem.mozRequestFullScreen) {
  189. fullscreenElem.mozRequestFullScreen();
  190. } else if (fullscreenElem.msRequestFullscreen) {
  191. fullscreenElem.msRequestFullscreen();
  192. }
  193. $(this).attr('data-original-title', 'Exit fullscreen');
  194. } else {
  195. if (document.exitFullscreen) {
  196. document.exitFullscreen();
  197. } else if (document.webkitExitFullscreen) {
  198. document.webkitExitFullscreen();
  199. } else if (document.mozCancelFullScreen) {
  200. document.mozCancelFullScreen();
  201. } else if (document.msExitFullscreen) {
  202. document.msExitFullscreen();
  203. }
  204. $(this).attr('data-original-title', 'Fullscreen');
  205. }
  206. });
  207. var screensharingStopped = function() {
  208. console.log("Screensharing now stopped");
  209. $('#screensharing-button').attr('data-original-title', 'Enable screensharing')
  210. .addClass('screensharing-disabled icon-screen-off-white')
  211. .removeClass('icon-screen-white');
  212. $('#screensharing-menu').toggleClass('open', false);
  213. };
  214. OCA.SpreedMe.webrtc.on('localScreenStopped', function() {
  215. screensharingStopped();
  216. });
  217. $('#screensharing-button').click(function() {
  218. var webrtc = OCA.SpreedMe.webrtc;
  219. if (!webrtc.capabilities.supportScreenSharing) {
  220. if (window.location.protocol === 'https:') {
  221. OC.Notification.showTemporary(t('spreed', 'Screensharing is not supported by your browser.'));
  222. } else {
  223. OC.Notification.showTemporary(t('spreed', 'Screensharing requires the page to be loaded through HTTPS.'));
  224. }
  225. return;
  226. }
  227. if (webrtc.getLocalScreen()) {
  228. $('#screensharing-menu').toggleClass('open');
  229. } else {
  230. var screensharingButton = $(this);
  231. screensharingButton.prop('disabled', true);
  232. webrtc.shareScreen(function(err) {
  233. screensharingButton.prop('disabled', false);
  234. if (!err) {
  235. $('#screensharing-button').attr('data-original-title', 'Screensharing options')
  236. .removeClass('screensharing-disabled icon-screen-off-white')
  237. .addClass('icon-screen-white');
  238. return;
  239. }
  240. switch (err.name) {
  241. case "HTTPS_REQUIRED":
  242. OC.Notification.showTemporary(t('spreed', 'Screensharing requires the page to be loaded through HTTPS.'));
  243. break;
  244. case "PERMISSION_DENIED":
  245. case "NotAllowedError":
  246. case "CEF_GETSCREENMEDIA_CANCELED": // Experimental, may go away in the future.
  247. break;
  248. case "FF52_REQUIRED":
  249. OC.Notification.showTemporary(t('spreed', 'Sharing your screen only works with Firefox version 52 or newer.'));
  250. break;
  251. case "EXTENSION_UNAVAILABLE":
  252. var extensionURL = null;
  253. if (!!window.chrome && !!window.chrome.webstore) {// Chrome
  254. extensionURL = 'https://chrome.google.com/webstore/detail/screensharing-for-nextclo/kepnpjhambipllfmgmbapncekcmabkol';
  255. }
  256. if (extensionURL) {
  257. var text = t('spreed', 'Screensharing extension is required to share your screen.');
  258. var element = $('<a>').attr('href', extensionURL).attr('target','_blank').text(text);
  259. OC.Notification.showTemporary(element, {isHTML: true});
  260. } else {
  261. OC.Notification.showTemporary(t('spreed', 'Please use a different browser like Firefox or Chrome to share your screen.'));
  262. }
  263. break;
  264. default:
  265. OC.Notification.showTemporary(t('spreed', 'An error occurred while starting screensharing.'));
  266. console.log("Could not start screensharing", err);
  267. break;
  268. }
  269. });
  270. }
  271. });
  272. $("#show-screen-button").on('click', function() {
  273. var currentUser = OCA.SpreedMe.webrtc.connection.getSessionid();
  274. OCA.SpreedMe.sharedScreens.switchScreenToId(currentUser);
  275. $('#screensharing-menu').toggleClass('open', false);
  276. });
  277. $("#stop-screen-button").on('click', function() {
  278. OCA.SpreedMe.webrtc.stopScreenShare();
  279. screensharingStopped();
  280. });
  281. $("#guestName").on('click', function() {
  282. $('#guestName').addClass('hidden');
  283. $("#guestNameInput").removeClass('hidden');
  284. $("#guestNameConfirm").removeClass('hidden');
  285. $("#guestNameInput").focus();
  286. });
  287. $('#guestNameConfirm').click(function () {
  288. OCA.SpreedMe.app.changeGuestName();
  289. $('#guestName').toggleClass('hidden');
  290. $("#guestNameInput").toggleClass('hidden');
  291. $("#guestNameConfirm").toggleClass('hidden');
  292. });
  293. $("#guestNameInput").keyup(function (e) {
  294. var hide = false;
  295. if (e.keyCode === 13) { // send new gues name on "enter"
  296. hide = true;
  297. OCA.SpreedMe.app.changeGuestName();
  298. } else if (e.keyCode === 27) { // hide input filed again in ESC
  299. hide = true;
  300. }
  301. if (hide) {
  302. $('#guestName').toggleClass('hidden');
  303. $("#guestNameInput").toggleClass('hidden');
  304. $("#guestNameConfirm").toggleClass('hidden');
  305. }
  306. });
  307. },
  308. _showRoomList: function() {
  309. this._roomsView = new OCA.SpreedMe.Views.RoomListView({
  310. el: '#app-navigation ul',
  311. collection: this._rooms
  312. });
  313. },
  314. _showParticipantList: function() {
  315. this._participants = new OCA.SpreedMe.Models.ParticipantCollection();
  316. this._participantsView = new OCA.SpreedMe.Views.ParticipantView({
  317. el: 'ul#participantWithList',
  318. collection: this._participants
  319. });
  320. },
  321. /**
  322. * @param {string} token
  323. */
  324. _setRoomActive: function(token) {
  325. if (oc_current_user) {
  326. this._rooms.forEach(function(room) {
  327. room.set('active', room.get('token') === token);
  328. });
  329. }
  330. },
  331. addParticipantToRoom: function(token, participant) {
  332. $.post(
  333. OC.linkToOCS('apps/spreed/api/v1/room', 2) + token + '/participants',
  334. {
  335. newParticipant: participant
  336. }
  337. ).done(function() {
  338. this.syncRooms();
  339. }.bind(this));
  340. },
  341. syncRooms: function() {
  342. return this.signaling.syncRooms();
  343. },
  344. syncAndSetActiveRoom: function(token) {
  345. var self = this;
  346. if (oc_current_user) {
  347. this.syncRooms()
  348. .then(function() {
  349. roomChannel.trigger('active', token);
  350. // Disable video when entering a room with more than 5 participants.
  351. self._rooms.forEach(function(room) {
  352. if (room.get('token') === token) {
  353. self.activeRoom = room;
  354. if (Object.keys(room.get('participants')).length > 5) {
  355. self.disableVideo();
  356. }
  357. self.setPageTitle(room.get('displayName'));
  358. }
  359. });
  360. });
  361. } else {
  362. $.ajax({
  363. url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + token,
  364. type: 'GET',
  365. beforeSend: function (request) {
  366. request.setRequestHeader('Accept', 'application/json');
  367. },
  368. success: function(result) {
  369. var data = result.ocs.data;
  370. self.setRoomMessageForGuest(data.participants);
  371. self.setPageTitle(data.displayName);
  372. if (Object.keys(data.participants).length > 5) {
  373. self.disableVideo();
  374. }
  375. }
  376. });
  377. }
  378. },
  379. setPageTitle: function(title){
  380. if (title) {
  381. title += ' - ';
  382. } else {
  383. title = '';
  384. }
  385. title += t('spreed', 'Video calls');
  386. title += ' - ' + oc_defaults.title;
  387. window.document.title = title;
  388. },
  389. setEmptyContentMessage: function(icon, message, messageAdditional) {
  390. //Remove previous icon, avatar or link from emptycontent
  391. var emptyContentIcon = document.getElementById('emptycontent-icon');
  392. emptyContentIcon.removeAttribute('class');
  393. emptyContentIcon.innerHTML = '';
  394. $('#shareRoomInput').addClass('hidden');
  395. $('#shareRoomClipboardButton').addClass('hidden');
  396. $('#emptycontent-icon').addClass(icon);
  397. $('#emptycontent h2').text(message);
  398. if (messageAdditional) {
  399. $('#emptycontent p').text(messageAdditional);
  400. } else {
  401. $('#emptycontent p').text('');
  402. }
  403. },
  404. setRoomMessageForGuest: function(participants) {
  405. var message, messageAdditional;
  406. //Remove previous icon or avatar
  407. var emptyContentIcon = document.getElementById('emptycontent-icon');
  408. emptyContentIcon.removeAttribute('class');
  409. emptyContentIcon.innerHTML = '';
  410. if (Object.keys(participants).length === 1) {
  411. var waitingParticipantId, waitingParticipantName;
  412. $.each(participants, function(id, participant) {
  413. waitingParticipantId = id;
  414. waitingParticipantName = participant.name;
  415. });
  416. // Avatar for username
  417. var avatar = document.createElement('div');
  418. avatar.className = 'avatar room-avatar';
  419. $('#emptycontent-icon').append(avatar);
  420. $('#emptycontent-icon').find('.avatar').each(function () {
  421. if (waitingParticipantName && (waitingParticipantId !== waitingParticipantName)) {
  422. $(this).avatar(waitingParticipantId, 128, undefined, false, undefined, waitingParticipantName);
  423. } else {
  424. $(this).avatar(waitingParticipantId, 128);
  425. }
  426. });
  427. message = t('spreed', 'Waiting for {participantName} to join the call …', {participantName: waitingParticipantName});
  428. messageAdditional = '';
  429. } else {
  430. message = t('spreed', 'Waiting for others to join the call …');
  431. messageAdditional = '';
  432. $('#emptycontent-icon').addClass('icon-contacts-dark');
  433. }
  434. $('#emptycontent h2').text(message);
  435. $('#emptycontent p').text(messageAdditional);
  436. },
  437. initialize: function() {
  438. if (oc_current_user) {
  439. this._rooms = new OCA.SpreedMe.Models.RoomCollection();
  440. this.listenTo(roomChannel, 'active', this._setRoomActive);
  441. }
  442. $(document).on('click', this.onDocumentClick);
  443. OC.Util.History.addOnPopStateHandler(_.bind(this._onPopState, this));
  444. },
  445. onStart: function() {
  446. this.setEmptyContentMessage(
  447. 'icon-video-off',
  448. t('spreed', 'Waiting for camera and microphone permissions'),
  449. t('spreed', 'Please, give your browser access to use your camera and microphone in order to use this app.')
  450. );
  451. if (!oc_current_user) {
  452. this.initGuestName();
  453. }
  454. OCA.SpreedMe.initWebRTC();
  455. },
  456. startSpreed: function(configuration, signaling) {
  457. console.log('Starting spreed …');
  458. var self = this;
  459. this.signaling = signaling;
  460. $(window).unload(function () {
  461. OCA.SpreedMe.Calls.leaveAllCalls();
  462. signaling.disconnect();
  463. });
  464. this.setEmptyContentMessage(
  465. 'icon-video',
  466. t('spreed', 'Looking great today! :)'),
  467. t('spreed', 'Time to call your friends')
  468. );
  469. OCA.SpreedMe.initCalls(signaling);
  470. this._registerPageEvents();
  471. this.initShareRoomClipboard();
  472. var token = $('#app').attr('data-token');
  473. if (token) {
  474. if (OCA.SpreedMe.webrtc.sessionReady) {
  475. OCA.SpreedMe.Calls.join(token);
  476. } else {
  477. OCA.SpreedMe.webrtc.once('connectionReady', function() {
  478. OCA.SpreedMe.Calls.join(token);
  479. });
  480. }
  481. }
  482. OCA.SpreedMe.Calls.showCamera();
  483. if (oc_current_user) {
  484. this._showRoomList();
  485. this.signaling.setRoomCollection(this._rooms)
  486. .then(function(data) {
  487. $('#app-navigation').removeClass('icon-loading');
  488. self._roomsView.render();
  489. if (data.length === 0) {
  490. $('#select-participants').select2('open');
  491. }
  492. });
  493. this._showParticipantList();
  494. }
  495. this.initAudioVideoSettings(configuration);
  496. },
  497. _onPopState: function(params) {
  498. if (!_.isUndefined(params.token)) {
  499. OCA.SpreedMe.Calls.join(params.token);
  500. }
  501. },
  502. onDocumentClick: function(event) {
  503. var uiChannel = Backbone.Radio.channel('ui');
  504. uiChannel.trigger('document:click', event);
  505. },
  506. initAudioVideoSettings: function(configuration) {
  507. if (OCA.SpreedMe.app.audioDisabled) {
  508. OCA.SpreedMe.app.disableAudio();
  509. }
  510. if (configuration.video !== false) {
  511. if (OCA.SpreedMe.app.videoDisabled) {
  512. OCA.SpreedMe.app.disableVideo();
  513. }
  514. } else {
  515. OCA.SpreedMe.app.videoWasEnabledAtLeastOnce = false;
  516. OCA.SpreedMe.app.disableVideo();
  517. }
  518. },
  519. enableAudio: function() {
  520. OCA.SpreedMe.webrtc.unmute();
  521. $('#mute').attr('data-original-title', 'Mute audio')
  522. .removeClass('audio-disabled icon-audio-off-white')
  523. .addClass('icon-audio-white');
  524. OCA.SpreedMe.app.audioDisabled = false;
  525. },
  526. disableAudio: function() {
  527. OCA.SpreedMe.webrtc.mute();
  528. $('#mute').attr('data-original-title', 'Enable audio')
  529. .addClass('audio-disabled icon-audio-off-white')
  530. .removeClass('icon-audio-white');
  531. OCA.SpreedMe.app.audioDisabled = true;
  532. },
  533. enableVideo: function() {
  534. var $hideVideoButton = $('#hideVideo');
  535. var avatarContainer = $hideVideoButton.closest('.videoView').find('.avatar-container');
  536. var localVideo = $hideVideoButton.closest('.videoView').find('#localVideo');
  537. OCA.SpreedMe.webrtc.resumeVideo();
  538. $hideVideoButton.attr('data-original-title', 'Disable video')
  539. .removeClass('video-disabled icon-video-off-white')
  540. .addClass('icon-video-white');
  541. avatarContainer.hide();
  542. localVideo.show();
  543. OCA.SpreedMe.app.videoDisabled = false;
  544. },
  545. hideVideo: function() {
  546. var $hideVideoButton = $('#hideVideo');
  547. var avatarContainer = $hideVideoButton.closest('.videoView').find('.avatar-container');
  548. var localVideo = $hideVideoButton.closest('.videoView').find('#localVideo');
  549. $hideVideoButton.attr('data-original-title', 'Enable video')
  550. .addClass('video-disabled icon-video-off-white')
  551. .removeClass('icon-video-white');
  552. var avatar = avatarContainer.find('.avatar');
  553. var guestName = localStorage.getItem("nick");
  554. if (oc_current_user) {
  555. avatar.avatar(OC.currentUser, 128);
  556. } else if (guestName) {
  557. avatar.imageplaceholder(guestName, undefined, 128);
  558. } else {
  559. avatar.imageplaceholder('?', undefined, 128);
  560. avatar.css('background-color', '#b9b9b9');
  561. OC.Notification.showTemporary(t('spreed', 'You can set your name on the top right of this page so other participants can identify you better.'));
  562. }
  563. avatarContainer.removeClass('hidden');
  564. avatarContainer.show();
  565. localVideo.hide();
  566. },
  567. disableVideo: function() {
  568. OCA.SpreedMe.webrtc.pauseVideo();
  569. OCA.SpreedMe.app.hideVideo();
  570. OCA.SpreedMe.app.videoDisabled = true;
  571. },
  572. initGuestName: function() {
  573. var nick = localStorage.getItem("nick");
  574. if (nick) {
  575. $('#guestName').text(nick);
  576. $('#guestNameInput').val(nick);
  577. OCA.SpreedMe.app.guestNick = nick;
  578. }
  579. },
  580. changeGuestName: function() {
  581. var guestName = $.trim($('#guestNameInput').val());
  582. var lastSavedNick = localStorage.getItem("nick");
  583. if (guestName !== lastSavedNick) {
  584. if (guestName.length > 0 && guestName.length <= 20) {
  585. $('#guestName').text(guestName);
  586. localStorage.setItem("nick", guestName);
  587. OCA.SpreedMe.webrtc.sendDirectlyToAll('status', 'nickChanged', guestName);
  588. } else if (lastSavedNick) {
  589. $('#guestName').text(t('spreed', 'Guest'));
  590. localStorage.removeItem("nick");
  591. OCA.SpreedMe.webrtc.sendDirectlyToAll('status', 'nickChanged', '');
  592. }
  593. }
  594. $('#guestNameInput').val(guestName);
  595. var avatar = $('#localVideoContainer').find('.avatar');
  596. var savedGuestName = localStorage.getItem("nick");
  597. if (savedGuestName) {
  598. avatar.imageplaceholder(savedGuestName, undefined, 128);
  599. } else {
  600. avatar.imageplaceholder('?', undefined, 128);
  601. avatar.css('background-color', '#b9b9b9');
  602. }
  603. },
  604. initShareRoomClipboard: function () {
  605. $('body').find('.shareRoomClipboard').tooltip({
  606. placement: 'bottom',
  607. trigger: 'hover',
  608. title: t('core', 'Copy')
  609. });
  610. var clipboard = new Clipboard('.shareRoomClipboard');
  611. clipboard.on('success', function(e) {
  612. var $input = $(e.trigger);
  613. $input.tooltip('hide')
  614. .attr('data-original-title', t('core', 'Copied!'))
  615. .tooltip('fixTitle')
  616. .tooltip({placement: 'bottom', trigger: 'manual'})
  617. .tooltip('show');
  618. _.delay(function() {
  619. $input.tooltip('hide')
  620. .attr('data-original-title', t('core', 'Copy'))
  621. .tooltip('fixTitle');
  622. }, 3000);
  623. });
  624. clipboard.on('error', function (e) {
  625. var $input = $(e.trigger);
  626. var actionMsg = '';
  627. if (/iPhone|iPad/i.test(navigator.userAgent)) {
  628. actionMsg = t('core', 'Not supported!');
  629. } else if (/Mac/i.test(navigator.userAgent)) {
  630. actionMsg = t('core', 'Press ⌘-C to copy.');
  631. } else {
  632. actionMsg = t('core', 'Press Ctrl-C to copy.');
  633. }
  634. $input.tooltip('hide')
  635. .attr('data-original-title', actionMsg)
  636. .tooltip('fixTitle')
  637. .tooltip({placement: 'bottom', trigger: 'manual'})
  638. .tooltip('show');
  639. _.delay(function () {
  640. $input.tooltip('hide')
  641. .attr('data-original-title', t('spreed', 'Copy'))
  642. .tooltip('fixTitle');
  643. }, 3000);
  644. });
  645. }
  646. });
  647. OCA.SpreedMe.App = App;
  648. })(OCA, Marionette, Backbone, _);