зеркало из https://github.com/nextcloud/spreed.git
861 строка
27 KiB
JavaScript
861 строка
27 KiB
JavaScript
/* global Marionette, Backbone, OCA */
|
|
|
|
/**
|
|
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
|
|
*
|
|
* @license GNU AGPL version 3 or any later version
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
(function(OC, OCA, Marionette, Backbone, _, $) {
|
|
'use strict';
|
|
|
|
OCA.Talk = OCA.Talk || {};
|
|
|
|
var roomChannel = Backbone.Radio.channel('rooms');
|
|
var localMediaChannel = Backbone.Radio.channel('localMedia');
|
|
|
|
OCA.Talk.Application = Marionette.Application.extend({
|
|
OWNER: 1,
|
|
MODERATOR: 2,
|
|
USER: 3,
|
|
GUEST: 4,
|
|
USERSELFJOINED: 5,
|
|
GUEST_MODERATOR: 6,
|
|
|
|
/* Must stay in sync with values in "lib/Participant.php". */
|
|
NOTIFY_DEFAULT: 0,
|
|
NOTIFY_ALWAYS: 1,
|
|
NOTIFY_MENTION: 2,
|
|
NOTIFY_NEVER: 3,
|
|
|
|
/* Must stay in sync with values in "lib/Room.php". */
|
|
FLAG_DISCONNECTED: 0,
|
|
FLAG_IN_CALL: 1,
|
|
FLAG_WITH_AUDIO: 2,
|
|
FLAG_WITH_VIDEO: 4,
|
|
|
|
/* Must stay in sync with values in "lib/Room.php". */
|
|
ROOM_TYPE_ONE_TO_ONE: 1,
|
|
ROOM_TYPE_GROUP: 2,
|
|
ROOM_TYPE_PUBLIC: 3,
|
|
ROOM_TYPE_CHANGELOG: 4,
|
|
|
|
/** @property {OCA.SpreedMe.Models.Room} activeRoom */
|
|
activeRoom: null,
|
|
|
|
/** @property {String} token */
|
|
token: null,
|
|
|
|
/** @property {OCA.Talk.Connection} connection */
|
|
connection: null,
|
|
|
|
/** @property {OCA.Talk.Signaling.base} signaling */
|
|
signaling: null,
|
|
|
|
/** property {String} selector */
|
|
mainCallElementSelector: '#app-content',
|
|
|
|
/** @property {OCA.SpreedMe.Models.RoomCollection} _rooms */
|
|
_rooms: null,
|
|
/** @property {OCA.SpreedMe.Views.RoomListView} _roomsView */
|
|
_roomsView: null,
|
|
/** @property {OCA.SpreedMe.Models.ParticipantCollection} _participants */
|
|
_participants: null,
|
|
/** @property {OCA.SpreedMe.Views.ParticipantView} _participantsView */
|
|
_participantsView: null,
|
|
/** @property {OCA.SpreedMe.Views.CollectionsView} _collectionsView */
|
|
_collectionsView: null,
|
|
fullscreenDisabled: true,
|
|
_searchTerm: '',
|
|
guestNick: null,
|
|
_registerPageEvents: function() {
|
|
$('#select-participants').select2({
|
|
ajax: {
|
|
url: OC.linkToOCS('core/autocomplete', 2) + 'get',
|
|
dataType: 'json',
|
|
quietMillis: 100,
|
|
data: function (term) {
|
|
this._searchTerm = term;
|
|
return {
|
|
format: 'json',
|
|
search: term,
|
|
itemType: 'call',
|
|
itemId: 'new',
|
|
shareTypes: [OC.Share.SHARE_TYPE_USER, OC.Share.SHARE_TYPE_GROUP]
|
|
};
|
|
}.bind(this),
|
|
results: function (response) {
|
|
// TODO improve error case
|
|
if (response.ocs.data === undefined) {
|
|
console.error('Failure happened', response);
|
|
return;
|
|
}
|
|
|
|
var results = [];
|
|
response.ocs.data.forEach(function(suggestion) {
|
|
results.push({
|
|
id: suggestion.id,
|
|
displayName: suggestion.label,
|
|
type: suggestion.source === 'users' ? 'user' : 'group'
|
|
});
|
|
});
|
|
|
|
// Add custom entry to create a new empty group or public room
|
|
if (OCA.SpreedMe.app._searchTerm === '') {
|
|
results.unshift({
|
|
id: "create-group-room",
|
|
displayName: t('spreed', 'Enter name for a new conversation'),
|
|
type: "createGroupRoom"
|
|
});
|
|
} else {
|
|
var shortenedName = OCA.SpreedMe.app._searchTerm;
|
|
if (OCA.SpreedMe.app._searchTerm.length > 25) {
|
|
shortenedName = shortenedName.substring(0, 25) + '…';
|
|
}
|
|
|
|
results.push({
|
|
id: "create-group-room",
|
|
displayName: shortenedName,
|
|
type: "createGroupRoom"
|
|
});
|
|
results.push({
|
|
id: "create-public-room",
|
|
displayName: shortenedName,
|
|
type: "createPublicRoom"
|
|
});
|
|
}
|
|
|
|
return {
|
|
results: results,
|
|
more: false
|
|
};
|
|
}
|
|
},
|
|
initSelection: function (element, callback) {
|
|
callback({id: element.val()});
|
|
},
|
|
formatResult: function (element) {
|
|
if (element.type === "createPublicRoom") {
|
|
return '<span><div class="avatar icon icon-public"></div>' + t('spreed', '{name} (public)', { name: element.displayName }) + '</span>';
|
|
}
|
|
|
|
if (element.type === "createGroupRoom" || element.type === 'group') {
|
|
return '<span><div class="avatar icon icon-contacts"></div>' + escapeHTML(element.displayName) + '</span>';
|
|
}
|
|
|
|
return '<span><div class="avatar" data-user="' + escapeHTML(element.id) + '" data-user-display-name="' + escapeHTML(element.displayName) + '"></div>' + escapeHTML(element.displayName) + '</span>';
|
|
},
|
|
formatSelection: function () {
|
|
return '<span class="select2-default" style="padding-left: 0;">' + t('spreed', 'New conversation …') + '</span>';
|
|
}
|
|
});
|
|
|
|
$('#select-participants').on('select2-selecting', function(e) {
|
|
switch (e.object.type) {
|
|
case 'user':
|
|
this.connection.createOneToOneVideoCall(e.val);
|
|
break;
|
|
case 'group':
|
|
this.connection.createGroupVideoCall(e.val, '');
|
|
break;
|
|
case 'createPublicRoom':
|
|
if (OCA.SpreedMe.app._searchTerm !== '') {
|
|
this.connection.createPublicVideoCall(OCA.SpreedMe.app._searchTerm);
|
|
}
|
|
break;
|
|
case 'createGroupRoom':
|
|
if (OCA.SpreedMe.app._searchTerm !== '') {
|
|
this.connection.createGroupVideoCall('', OCA.SpreedMe.app._searchTerm);
|
|
}
|
|
break;
|
|
default:
|
|
console.log('Unknown type', e.object.type);
|
|
break;
|
|
}
|
|
}.bind(this));
|
|
|
|
$('#select-participants').on('select2-loaded', function() {
|
|
$('.select2-drop').find('.avatar[data-user]').each(function () {
|
|
var element = $(this);
|
|
if (element.data('user-display-name')) {
|
|
element.avatar(element.data('user'), 32, undefined, false, undefined, element.data('user-display-name'));
|
|
} else {
|
|
element.avatar(element.data('user'), 32);
|
|
}
|
|
});
|
|
});
|
|
|
|
// Initialize button tooltips
|
|
$('[data-toggle="tooltip"]').tooltip({trigger: 'hover'}).click(function() {
|
|
$(this).tooltip('hide');
|
|
});
|
|
|
|
this.registerLocalVideoButtonHandlers();
|
|
|
|
$(document).keyup(this._onKeyUp.bind(this));
|
|
},
|
|
|
|
registerLocalVideoButtonHandlers: function() {
|
|
$('#video-fullscreen').click(function() {
|
|
if (this.fullscreenDisabled) {
|
|
this.enableFullscreen();
|
|
} else {
|
|
this.disableFullscreen();
|
|
}
|
|
}.bind(this));
|
|
},
|
|
|
|
_onKeyUp: function(event) {
|
|
// Define which objects to check for the event properties.
|
|
var key = event.which;
|
|
|
|
// Trigger the event only if no input or textarea is focused
|
|
// and the CTRL key is not pressed
|
|
if ($('input:focus').length === 0 &&
|
|
$('textarea:focus').length === 0 &&
|
|
$('div[contenteditable=true]:focus').length === 0 &&
|
|
!event.ctrlKey) {
|
|
|
|
// Actual shortcut handling
|
|
switch (key) {
|
|
case 86: // 'v'
|
|
event.preventDefault();
|
|
this._mediaControlsView.toggleVideo();
|
|
break;
|
|
case 77: // 'm'
|
|
event.preventDefault();
|
|
this._mediaControlsView.toggleAudio();
|
|
break;
|
|
case 70: // 'f'
|
|
event.preventDefault();
|
|
if (this.fullscreenDisabled) {
|
|
this.enableFullscreen();
|
|
} else {
|
|
this.disableFullscreen();
|
|
}
|
|
break;
|
|
case 67: // 'c'
|
|
event.preventDefault();
|
|
this._sidebarView.selectTab('chat');
|
|
break;
|
|
case 80: // 'p'
|
|
event.preventDefault();
|
|
this._sidebarView.selectTab('participants');
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
|
|
_showRoomList: function() {
|
|
this._roomsView = new OCA.SpreedMe.Views.RoomListView({
|
|
el: '#app-navigation ul',
|
|
collection: this._rooms
|
|
});
|
|
},
|
|
_showParticipantList: function() {
|
|
this._participants = new OCA.SpreedMe.Models.ParticipantCollection();
|
|
this._participantsView = new OCA.SpreedMe.Views.ParticipantView({
|
|
room: this.activeRoom,
|
|
collection: this._participants,
|
|
id: 'participantsTabView'
|
|
});
|
|
|
|
this._participantsListChangedCallback = function() {
|
|
// The "participantListChanged" event can be triggered by the
|
|
// signaling before the room is set in the collection.
|
|
if (this._participants.url) {
|
|
this._participants.fetch();
|
|
}
|
|
}.bind(this);
|
|
|
|
this.signaling.on('participantListChanged', this._participantsListChangedCallback);
|
|
|
|
this._participantsView.listenTo(this._rooms, 'change:active', function(model, active) {
|
|
if (active) {
|
|
this.setRoom(model);
|
|
}
|
|
});
|
|
|
|
this._sidebarView.addTab('participants', { label: t('spreed', 'Participants'), icon: 'icon-contacts-dark' }, this._participantsView);
|
|
|
|
this._collectionsView = new OCA.SpreedMe.Views.CollectionsView({
|
|
room: this.activeRoom,
|
|
id: 'collectionsTabView'
|
|
});
|
|
this._collectionsView.listenTo(this._rooms, 'change:active', function(model, active) {
|
|
if (active) {
|
|
this.setRoom(model);
|
|
}
|
|
});
|
|
this._sidebarView.addTab('collections', { label: t('spreed', 'Collections'), icon: 'icon-category-integration' }, this._collectionsView);
|
|
},
|
|
_hideParticipantList: function() {
|
|
this._sidebarView.removeTab('participants');
|
|
|
|
this.signaling.off('participantListChanged', this._participantsListChangedCallback);
|
|
|
|
delete this._participantsListChangedCallback;
|
|
delete this._participantsView;
|
|
delete this._participants;
|
|
},
|
|
/**
|
|
* @param {string} token
|
|
*/
|
|
_setRoomActive: function(token) {
|
|
if (OC.getCurrentUser().uid) {
|
|
this._rooms.forEach(function(room) {
|
|
room.set('active', room.get('token') === token);
|
|
});
|
|
}
|
|
},
|
|
addParticipantToRoom: function(token, participant, type) {
|
|
$.post(
|
|
OC.linkToOCS('apps/spreed/api/v1/room', 2) + token + '/participants',
|
|
{
|
|
newParticipant: participant,
|
|
source: type
|
|
}
|
|
).done(function() {
|
|
this.signaling.syncRooms();
|
|
}.bind(this));
|
|
},
|
|
syncAndSetActiveRoom: function(token) {
|
|
var self = this;
|
|
this.signaling.syncRooms()
|
|
.then(function() {
|
|
self.stopListening(self.activeRoom, 'change:displayName');
|
|
self.stopListening(self.activeRoom, 'change:participantFlags');
|
|
|
|
if (OC.getCurrentUser().uid) {
|
|
roomChannel.trigger('active', token);
|
|
|
|
self._rooms.forEach(function(room) {
|
|
if (room.get('token') === token) {
|
|
self.activeRoom = room;
|
|
}
|
|
});
|
|
}
|
|
|
|
self._emptyContentView.setActiveRoom(self.activeRoom);
|
|
|
|
self.setPageTitle(self.activeRoom.get('displayName'));
|
|
self.listenTo(self.activeRoom, 'change:displayName', function(model, value) {
|
|
self.setPageTitle(value);
|
|
});
|
|
|
|
self.updateContentsLayout();
|
|
self.listenTo(self.activeRoom, 'change:participantFlags', self.updateContentsLayout);
|
|
|
|
self.updateSidebarWithActiveRoom();
|
|
});
|
|
},
|
|
updateContentsLayout: function() {
|
|
if (!this.activeRoom) {
|
|
// This should never happen, but just in case
|
|
return;
|
|
}
|
|
|
|
var flags = this.activeRoom.get('participantFlags') || 0;
|
|
var inCall = flags & OCA.SpreedMe.app.FLAG_IN_CALL !== 0;
|
|
if (inCall && this._chatViewInMainView === true) {
|
|
this._chatView.$el.detach();
|
|
this._sidebarView.addTab('chat', { label: t('spreed', 'Chat'), icon: 'icon-comment', priority: 100 }, this._chatView);
|
|
this._sidebarView.selectTab('chat');
|
|
this._chatView.reloadMessageList();
|
|
this._chatView.setTooltipContainer(this._chatView.$el);
|
|
this._chatViewInMainView = false;
|
|
} else if (!inCall && !this._chatViewInMainView) {
|
|
this._sidebarView.removeTab('chat');
|
|
this._chatView.$el.prependTo('#app-content-wrapper');
|
|
this._chatView.reloadMessageList();
|
|
this._chatView.setTooltipContainer($('#app'));
|
|
this._chatView.focusChatInput();
|
|
this._chatViewInMainView = true;
|
|
}
|
|
|
|
if (inCall) {
|
|
$('#videos').show();
|
|
$('#screens').show();
|
|
$('#emptycontent').hide();
|
|
} else {
|
|
$('#videos').hide();
|
|
$('#screens').hide();
|
|
$('#emptycontent').show();
|
|
}
|
|
},
|
|
updateSidebarWithActiveRoom: function() {
|
|
this._sidebarView.enable();
|
|
|
|
// The sidebar has a width of 27% of the window width and a minimum
|
|
// width of 300px. Therefore, when the window is 1111px wide or
|
|
// narrower the sidebar will always be 300px wide, and when that
|
|
// happens it will overlap with the content area (the narrower the
|
|
// window the larger the overlap). Due to this the sidebar is opened
|
|
// automatically only if it will not overlap with the content area.
|
|
if (this.activeRoom.get('type') === this.ROOM_TYPE_CHANGELOG) {
|
|
this._sidebarView.close();
|
|
} else if (this.activeRoom.get('type') !== this.ROOM_TYPE_CHANGELOG && $(window).width() > 1111) {
|
|
this._sidebarView.open();
|
|
}
|
|
|
|
var callInfoView = new OCA.SpreedMe.Views.CallInfoView({
|
|
model: this.activeRoom,
|
|
guestNameModel: this._localStorageModel
|
|
});
|
|
this._sidebarView.setCallInfoView(callInfoView);
|
|
|
|
this._chatView.setRoom(this.activeRoom);
|
|
this._messageCollection.setRoomToken(this.activeRoom.get('token'));
|
|
this._messageCollection.receiveMessages();
|
|
},
|
|
setPageTitle: function(title){
|
|
if (title) {
|
|
title += ' - ';
|
|
} else {
|
|
title = '';
|
|
}
|
|
title += t('spreed', 'Talk');
|
|
title += ' - ' + oc_defaults.title;
|
|
window.document.title = title;
|
|
},
|
|
initialize: function() {
|
|
this._emptyContentView = new OCA.SpreedMe.Views.EmptyContentView({
|
|
el: '#app-content-wrapper > #emptycontent',
|
|
});
|
|
|
|
this._sidebarView = new OCA.SpreedMe.Views.SidebarView();
|
|
$('#content').append(this._sidebarView.$el);
|
|
|
|
if (OC.getCurrentUser().uid) {
|
|
this._rooms = new OCA.SpreedMe.Models.RoomCollection();
|
|
this.listenTo(roomChannel, 'active', this._setRoomActive);
|
|
} else {
|
|
this.initGuestName();
|
|
}
|
|
|
|
this._sidebarView.listenTo(roomChannel, 'leaveCurrentRoom', function() {
|
|
this.disable();
|
|
});
|
|
|
|
this._messageCollection = new OCA.SpreedMe.Models.ChatMessageCollection(null, {token: null});
|
|
this._chatView = new OCA.SpreedMe.Views.ChatView({
|
|
collection: this._messageCollection,
|
|
model: this.activeRoom,
|
|
id: 'chatView',
|
|
guestNameModel: this._localStorageModel
|
|
});
|
|
|
|
// Focus the chat input when the chat tab is selected.
|
|
this._chatView.listenTo(this._sidebarView, 'select:tab', function(tabId) {
|
|
if (tabId !== 'chat') {
|
|
return;
|
|
}
|
|
|
|
this._chatView.focusChatInput();
|
|
}.bind(this));
|
|
|
|
// Opening and closing the sidebar detachs its contents to perform
|
|
// the animation; detaching an element and attaching it again resets
|
|
// its scroll position, so the scroll position of the chat view
|
|
// needs to be saved before the sidebar is closed and restored again
|
|
// once the sidebar is opened.
|
|
this._chatView.listenTo(this._sidebarView, 'opened', function() {
|
|
if (this._sidebarView.getCurrentTabId() !== 'chat') {
|
|
return;
|
|
}
|
|
|
|
this._chatView.restoreScrollPosition();
|
|
}.bind(this));
|
|
this._chatView.listenTo(this._sidebarView, 'close', function() {
|
|
if (this._sidebarView.getCurrentTabId() !== 'chat') {
|
|
return;
|
|
}
|
|
|
|
this._chatView.saveScrollPosition();
|
|
}.bind(this));
|
|
|
|
// Selecting a different tab detachs the contents of the previous
|
|
// tab and attachs the contents of the new tab; detaching an element
|
|
// and attaching it again resets its scroll position, so the scroll
|
|
// position of the chat view needs to be saved when the chat tab is
|
|
// unselected and restored again when the chat tab is selected.
|
|
this._chatView.listenTo(this._sidebarView, 'unselect:tab', function(tabId) {
|
|
if (tabId !== 'chat') {
|
|
return;
|
|
}
|
|
|
|
this._chatView.saveScrollPosition();
|
|
}.bind(this));
|
|
this._chatView.listenTo(this._sidebarView, 'select:tab', function(tabId) {
|
|
if (tabId !== 'chat') {
|
|
return;
|
|
}
|
|
|
|
this._chatView.restoreScrollPosition();
|
|
}.bind(this));
|
|
|
|
// Opening or closing the sidebar changes the width of the main
|
|
// view, so if the chat view is in the main view it needs to be
|
|
// reloaded.
|
|
var reloadMessageListOnSidebarVisibilityChange = function() {
|
|
if (!this._chatViewInMainView) {
|
|
return;
|
|
}
|
|
|
|
this._chatView.reloadMessageList();
|
|
}.bind(this);
|
|
this._chatView.listenTo(this._sidebarView, 'opened', reloadMessageListOnSidebarVisibilityChange);
|
|
this._chatView.listenTo(this._sidebarView, 'closed', reloadMessageListOnSidebarVisibilityChange);
|
|
|
|
// Resizing the window can change the size of the chat view, both
|
|
// when it is in the main view and in the sidebar, so the chat view
|
|
// needs to be reloaded. The initial reload is not very heavy, so
|
|
// the handler is not debounced for a snappier feel and to reduce
|
|
// flickering.
|
|
// However, resizing the window below certain width causes the
|
|
// navigation bar to be hidden; an explicit handling is needed in
|
|
// this case because the app navigation (or, more specifically, its
|
|
// Snap object) adds a transition to the app content, so the reload
|
|
// needs to be delayed to give the transition time to end and thus
|
|
// give the app content time to get its final size.
|
|
var reloadMessageListOnWindowResize = function() {
|
|
var chatView = this._chatView;
|
|
|
|
if ($(window).width() >= 768 || !this._chatViewInMainView) {
|
|
chatView.reloadMessageList();
|
|
|
|
return;
|
|
}
|
|
|
|
setTimeout(function() {
|
|
chatView.reloadMessageList();
|
|
}, 300);
|
|
}.bind(this);
|
|
$(window).resize(reloadMessageListOnWindowResize);
|
|
|
|
this._messageCollection.listenTo(roomChannel, 'leaveCurrentRoom', function() {
|
|
this.stopReceivingMessages();
|
|
});
|
|
|
|
this.listenTo(roomChannel, 'leaveCurrentRoom', function() {
|
|
this._chatView.$el.detach();
|
|
this._chatViewInMainView = false;
|
|
|
|
$('#videos').hide();
|
|
$('#screens').hide();
|
|
$('#emptycontent').show();
|
|
});
|
|
|
|
this.listenTo(roomChannel, 'joinRoom', function(token) {
|
|
if (OCA.Talk.PublicShareAuth) {
|
|
return;
|
|
}
|
|
|
|
if (this._popingState) {
|
|
return;
|
|
}
|
|
|
|
OC.Util.History.pushState({
|
|
token: token
|
|
}, OC.generateUrl('/call/' + token));
|
|
});
|
|
|
|
this.listenTo(roomChannel, 'leaveCurrentRoom', function() {
|
|
if (OCA.Talk.PublicShareAuth) {
|
|
return;
|
|
}
|
|
|
|
this.setPageTitle(null);
|
|
|
|
OC.Util.History.replaceState({}, OC.generateUrl('/apps/spreed'));
|
|
});
|
|
|
|
this._localVideoView = new OCA.Talk.Views.LocalVideoView({
|
|
app: this,
|
|
webrtc: OCA.SpreedMe.webrtc,
|
|
sharedScreens: OCA.SpreedMe.sharedScreens,
|
|
});
|
|
this._localVideoView.render();
|
|
// Ensure that the local video is not visible in the initial page.
|
|
this._localVideoView.$el.addClass('hidden');
|
|
$('#videos').append(this._localVideoView.$el);
|
|
|
|
this._mediaControlsView = this._localVideoView._mediaControlsView;
|
|
|
|
$(document).on('click', this.onDocumentClick);
|
|
OC.Util.History.addOnPopStateHandler(_.bind(this._onPopState, this));
|
|
},
|
|
onStart: function() {
|
|
this.signaling = OCA.Talk.Signaling.createConnection();
|
|
this.connection = new OCA.Talk.Connection(this);
|
|
this.token = $('#app').attr('data-token');
|
|
|
|
this.signaling.on('joinRoom', function(/* token */) {
|
|
this.inRoom = true;
|
|
if (this.pendingNickChange) {
|
|
this.setGuestName(this.pendingNickChange);
|
|
delete this.pendingNickChange;
|
|
}
|
|
}.bind(this));
|
|
|
|
this.signaling.on('joinCall', function() {
|
|
// Disable video when joining a call in a room with more than 5
|
|
// participants.
|
|
var participants = this.activeRoom.get('participants');
|
|
if (participants && Object.keys(participants).length > 5) {
|
|
this.setVideoEnabled(false);
|
|
}
|
|
}.bind(this));
|
|
|
|
$(window).unload(function () {
|
|
this.connection.leaveCurrentRoom();
|
|
this.signaling.disconnect();
|
|
}.bind(this));
|
|
|
|
if (OC.getCurrentUser().uid) {
|
|
this._showRoomList();
|
|
this.signaling.setRoomCollection(this._rooms)
|
|
.then(function(data) {
|
|
$('#app-navigation').removeClass('icon-loading');
|
|
this._roomsView.render();
|
|
|
|
if (data.length === 0) {
|
|
$('#select-participants').select2('open');
|
|
}
|
|
}.bind(this));
|
|
|
|
this._showParticipantList();
|
|
} else if (this.token) {
|
|
// The token is always defined in the public page (although not
|
|
// in the public share auth page).
|
|
this.activeRoom = new OCA.SpreedMe.Models.Room({ token: this.token });
|
|
this.signaling.setRoom(this.activeRoom);
|
|
|
|
this.listenTo(this.activeRoom, 'change:participantType', function(model, participantType) {
|
|
if (participantType === OCA.SpreedMe.app.GUEST_MODERATOR) {
|
|
this._showParticipantList();
|
|
// The public page supports only a single room, so the
|
|
// active room has to be explicitly set as it will not
|
|
// be set in a 'change:active' event.
|
|
this._participantsView.setRoom(this.activeRoom);
|
|
} else {
|
|
this._hideParticipantList();
|
|
}
|
|
});
|
|
}
|
|
|
|
this._registerPageEvents();
|
|
this.initShareRoomClipboard();
|
|
|
|
if (this.token) {
|
|
this.connection.joinRoom(this.token);
|
|
}
|
|
},
|
|
setupWebRTC: function() {
|
|
if (!OCA.SpreedMe.webrtc) {
|
|
OCA.SpreedMe.initWebRTC(this);
|
|
this._mediaControlsView.setWebRtc(OCA.SpreedMe.webrtc);
|
|
this._mediaControlsView.setSharedScreens(OCA.SpreedMe.sharedScreens);
|
|
}
|
|
|
|
if (!OCA.SpreedMe.webrtc.capabilities.support) {
|
|
localMediaChannel.trigger('webRtcNotSupported');
|
|
} else {
|
|
localMediaChannel.trigger('waitingForPermissions');
|
|
}
|
|
|
|
OCA.SpreedMe.webrtc.startMedia(this.token);
|
|
},
|
|
startLocalMedia: function(configuration) {
|
|
if (this.callbackAfterMedia) {
|
|
this.callbackAfterMedia(configuration);
|
|
this.callbackAfterMedia = null;
|
|
}
|
|
|
|
this._localVideoView.$el.removeClass('hidden');
|
|
this.initAudioVideoSettings(configuration);
|
|
|
|
localMediaChannel.trigger('startLocalMedia');
|
|
},
|
|
startWithoutLocalMedia: function(configuration) {
|
|
if (this.callbackAfterMedia) {
|
|
this.callbackAfterMedia(null);
|
|
this.callbackAfterMedia = null;
|
|
}
|
|
|
|
this._localVideoView.$el.removeClass('hidden');
|
|
this.initAudioVideoSettings(configuration);
|
|
|
|
if (OCA.SpreedMe.webrtc.capabilities.support) {
|
|
localMediaChannel.trigger('startWithoutLocalMedia');
|
|
}
|
|
},
|
|
_onPopState: function(params) {
|
|
if (!_.isUndefined(params.token)) {
|
|
this._popingState = true;
|
|
this.connection.joinRoom(params.token);
|
|
delete this._popingState;
|
|
}
|
|
},
|
|
onDocumentClick: function(event) {
|
|
var uiChannel = Backbone.Radio.channel('ui');
|
|
|
|
uiChannel.trigger('document:click', event);
|
|
},
|
|
initAudioVideoSettings: function(configuration) {
|
|
if (configuration.audio !== false) {
|
|
this._mediaControlsView.setAudioAvailable(true);
|
|
this._mediaControlsView.setAudioEnabled(this._mediaControlsView.audioEnabled);
|
|
} else {
|
|
this._mediaControlsView.setAudioEnabled(false);
|
|
this._mediaControlsView.setAudioAvailable(false);
|
|
}
|
|
|
|
if (configuration.video !== false) {
|
|
this._mediaControlsView.setVideoAvailable(true);
|
|
this.setVideoEnabled(this._mediaControlsView.videoEnabled);
|
|
} else {
|
|
this.setVideoEnabled(false);
|
|
this._mediaControlsView.setVideoAvailable(false);
|
|
}
|
|
},
|
|
enableFullscreen: function() {
|
|
var fullscreenElem = document.getElementById('content');
|
|
|
|
if (fullscreenElem.requestFullscreen) {
|
|
fullscreenElem.requestFullscreen();
|
|
} else if (fullscreenElem.webkitRequestFullscreen) {
|
|
fullscreenElem.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
|
|
} else if (fullscreenElem.mozRequestFullScreen) {
|
|
fullscreenElem.mozRequestFullScreen();
|
|
} else if (fullscreenElem.msRequestFullscreen) {
|
|
fullscreenElem.msRequestFullscreen();
|
|
}
|
|
$('#video-fullscreen').attr('data-original-title', t('spreed', 'Exit fullscreen (f)'));
|
|
|
|
this.fullscreenDisabled = false;
|
|
},
|
|
disableFullscreen: function() {
|
|
|
|
if (document.exitFullscreen) {
|
|
document.exitFullscreen();
|
|
} else if (document.webkitExitFullscreen) {
|
|
document.webkitExitFullscreen();
|
|
} else if (document.mozCancelFullScreen) {
|
|
document.mozCancelFullScreen();
|
|
} else if (document.msExitFullscreen) {
|
|
document.msExitFullscreen();
|
|
}
|
|
$('#video-fullscreen').attr('data-original-title', t('spreed', 'Fullscreen (f)'));
|
|
|
|
this.fullscreenDisabled = true;
|
|
},
|
|
setVideoEnabled: function(videoEnabled) {
|
|
if (!this._mediaControlsView.setVideoEnabled(videoEnabled)) {
|
|
return;
|
|
}
|
|
|
|
this._localVideoView.setVideoEnabled(videoEnabled);
|
|
},
|
|
// Called from webrtc.js
|
|
disableScreensharingButton: function() {
|
|
this._mediaControlsView.disableScreensharingButton();
|
|
},
|
|
setGuestName: function(name) {
|
|
$.ajax({
|
|
url: OC.linkToOCS('apps/spreed/api/v1/guest', 2) + this.token + '/name',
|
|
type: 'POST',
|
|
data: {
|
|
displayName: name
|
|
},
|
|
beforeSend: function (request) {
|
|
request.setRequestHeader('Accept', 'application/json');
|
|
},
|
|
success: function() {
|
|
this._onChangeGuestName(name);
|
|
}.bind(this)
|
|
});
|
|
},
|
|
initGuestName: function() {
|
|
this._localStorageModel = new OCA.SpreedMe.Models.LocalStorageModel({ nick: '' });
|
|
this._localStorageModel.on('change:nick', function(model, newDisplayName) {
|
|
if (!this.token || !this.inRoom) {
|
|
this.pendingNickChange = newDisplayName;
|
|
return;
|
|
}
|
|
|
|
this.setGuestName(newDisplayName);
|
|
}.bind(this));
|
|
|
|
this._localStorageModel.fetch();
|
|
},
|
|
_onChangeGuestName: function(newDisplayName) {
|
|
this._localVideoView.setAvatar(undefined, newDisplayName);
|
|
|
|
if (OCA.SpreedMe.webrtc) {
|
|
console.log('_onChangeGuestName.webrtc');
|
|
OCA.SpreedMe.webrtc.sendDirectlyToAll('status', 'nickChanged', newDisplayName);
|
|
}
|
|
},
|
|
initShareRoomClipboard: function () {
|
|
$('body').find('.shareRoomClipboard').tooltip({
|
|
placement: 'bottom',
|
|
trigger: 'hover',
|
|
title: t('core', 'Copy')
|
|
});
|
|
|
|
var clipboard = new Clipboard('.shareRoomClipboard');
|
|
clipboard.on('success', function(e) {
|
|
var $input = $(e.trigger);
|
|
$input.tooltip('hide')
|
|
.attr('data-original-title', t('core', 'Copied!'))
|
|
.tooltip('fixTitle')
|
|
.tooltip({placement: 'bottom', trigger: 'manual'})
|
|
.tooltip('show');
|
|
_.delay(function() {
|
|
$input.tooltip('hide')
|
|
.attr('data-original-title', t('core', 'Copy'))
|
|
.tooltip('fixTitle');
|
|
}, 3000);
|
|
});
|
|
clipboard.on('error', function (e) {
|
|
var $input = $(e.trigger);
|
|
var actionMsg = '';
|
|
if (/iPhone|iPad/i.test(navigator.userAgent)) {
|
|
actionMsg = t('core', 'Not supported!');
|
|
} else if (/Mac/i.test(navigator.userAgent)) {
|
|
actionMsg = t('core', 'Press ⌘-C to copy.');
|
|
} else {
|
|
actionMsg = t('core', 'Press Ctrl-C to copy.');
|
|
}
|
|
|
|
$input.tooltip('hide')
|
|
.attr('data-original-title', actionMsg)
|
|
.tooltip('fixTitle')
|
|
.tooltip({placement: 'bottom', trigger: 'manual'})
|
|
.tooltip('show');
|
|
_.delay(function () {
|
|
$input.tooltip('hide')
|
|
.attr('data-original-title', t('spreed', 'Copy'))
|
|
.tooltip('fixTitle');
|
|
}, 3000);
|
|
});
|
|
}
|
|
});
|
|
|
|
})(OC, OCA, Marionette, Backbone, _, $);
|