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.

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