Browse Source

Merge pull request #351 from nextcloud/centralize-room-api

Move room/call API to central location
pull/365/head
Ivan Sein 9 years ago
committed by GitHub
parent
commit
599fa66473
  1. 81
      js/app.js
  2. 87
      js/calls.js
  3. 243
      js/signaling.js
  4. 21
      js/views/roomlistview.js
  5. 176
      js/webrtc.js
  6. 2
      templates/index-public.php
  7. 2
      templates/index.php

81
js/app.js

@ -112,9 +112,9 @@
$('#edit-roomname').on("change", function(e) {
if (e.added.type === "user") {
OCA.SpreedMe.Rooms.createOneToOneVideoCall(e.val);
OCA.SpreedMe.Calls.createOneToOneVideoCall(e.val);
} else if (e.added.type === "group") {
OCA.SpreedMe.Rooms.createGroupVideoCall(e.val);
OCA.SpreedMe.Calls.createGroupVideoCall(e.val);
}
$('.select2-drop').find('.avatar').each(function () {
@ -140,7 +140,7 @@
$('#edit-roomname').on("select2-selecting", function(e) {
if (e.object.type === "createPublicRoom") {
OCA.SpreedMe.Rooms.createPublicVideoCall();
OCA.SpreedMe.Calls.createPublicVideoCall();
}
});
@ -339,20 +339,6 @@
collection: this._rooms
});
},
_pollForRoomChanges: function() {
// Load the list of rooms all 10 seconds
var self = this;
setInterval(function() {
self.syncRooms();
}, 10000);
},
_startPing: function() {
// Send a ping to the server all 5 seconds to ensure that the connection is
// still alive.
setInterval(function() {
OCA.SpreedMe.Rooms.ping();
}, 5000);
},
/**
* @param {string} token
*/
@ -363,16 +349,24 @@
});
}
},
addParticipantToRoom: function(token, participant) {
$.post(
OC.linkToOCS('apps/spreed/api/v1/room', 2) + token + '/participants',
{
newParticipant: participant
}
).done(function() {
this.syncRooms();
}.bind(this));
},
syncRooms: function() {
if (oc_current_user) {
this._rooms.fetch();
}
return this.signaling.syncRooms();
},
syncAndSetActiveRoom: function(token) {
var self = this;
if (oc_current_user) {
this._rooms.fetch({
success: function() {
this.syncRooms()
.then(function() {
roomChannel.trigger('active', token);
// Disable video when entering a room with more than 5 participants.
self._rooms.forEach(function(room) {
@ -383,8 +377,7 @@
self.setPageTitle(room.get('displayName'));
}
});
}
});
});
} else {
$.ajax({
url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + token,
@ -492,9 +485,15 @@
OCA.SpreedMe.initWebRTC();
},
startSpreed: function(configuration) {
startSpreed: function(configuration, signaling) {
console.log('Starting spreed …');
var self = this;
this.signaling = signaling;
$(window).unload(function () {
OCA.SpreedMe.Calls.leaveAllCalls();
signaling.disconnect();
});
this.setEmptyContentMessage(
'icon-video',
@ -502,43 +501,41 @@
t('spreed', 'Time to call your friends')
);
if (oc_current_user) {
OCA.SpreedMe.initRooms();
OCA.SpreedMe.Rooms.leaveAllRooms();
}
OCA.SpreedMe.initCalls(signaling);
this._registerPageEvents();
this.initShareRoomClipboard();
var token = $('#app').attr('data-token');
if (token) {
OCA.SpreedMe.Rooms.join(token);
if (OCA.SpreedMe.webrtc.sessionReady) {
OCA.SpreedMe.Calls.join(token);
} else {
OCA.SpreedMe.webrtc.once('connectionReady', function() {
OCA.SpreedMe.Calls.join(token);
});
}
}
OCA.SpreedMe.Rooms.showCamera();
OCA.SpreedMe.Calls.showCamera();
if (oc_current_user) {
this._showRoomList();
this._rooms.fetch({
success: function(data) {
this.signaling.setRoomCollection(this._rooms)
.then(function(data) {
$('#app-navigation').removeClass('icon-loading');
self._roomsView.render();
if (data.length === 0) {
$('#edit-roomname').select2('open');
}
}
});
this._pollForRoomChanges();
});
}
this._startPing();
this.initAudioVideoSettings(configuration);
},
_onPopState: function(params) {
if (!_.isUndefined(params.token)) {
OCA.SpreedMe.Rooms.join(params.token);
OCA.SpreedMe.Calls.join(params.token);
}
},
onDocumentClick: function(event) {
@ -703,7 +700,3 @@
OCA.SpreedMe.App = App;
})(OCA, Marionette, Backbone, _);
$(window).unload(function () {
OCA.SpreedMe.Rooms.leaveAllRooms();
});

87
js/rooms.js → js/calls.js

@ -6,32 +6,35 @@
OCA.SpreedMe = OCA.SpreedMe || {};
function initRooms() {
var signaling;
function initCalls(signaling_connection) {
signaling = signaling_connection;
var editRoomname = $('#edit-roomname');
editRoomname.keyup(function () {
editRoomname.tooltip('hide');
editRoomname.removeClass('error');
});
OCA.SpreedMe.Calls.leaveAllCalls();
}
var currentRoom = '';
var pingFails = 0;
Backbone.Radio.channel('rooms');
OCA.SpreedMe.Rooms = {
OCA.SpreedMe.Calls = {
showCamera: function() {
$('.videoView').removeClass('hidden');
},
_createRoomSuccessHandle: function(ocsResponse) {
var data = ocsResponse.ocs.data;
_createCallSuccessHandle: function(ocsResponse) {
var token = ocsResponse.ocs.data.token;
OC.Util.History.pushState({
token: data.token
}, OC.generateUrl('/call/' + data.token));
this.join(data.token);
token: token
}, OC.generateUrl('/call/' + token));
this.join(token);
},
createOneToOneVideoCall: function(recipientUserId) {
console.log(recipientUserId);
console.log("Creating one-to-one video call", recipientUserId);
$.ajax({
url: OC.linkToOCS('apps/spreed/api/v1', 2) + 'room',
type: 'POST',
@ -42,11 +45,11 @@
beforeSend: function (request) {
request.setRequestHeader('Accept', 'application/json');
},
success: _.bind(this._createRoomSuccessHandle, this)
success: _.bind(this._createCallSuccessHandle, this)
});
},
createGroupVideoCall: function(groupId) {
console.log(groupId);
console.log("Creating group video call", groupId);
$.ajax({
url: OC.linkToOCS('apps/spreed/api/v1', 2) + 'room',
type: 'POST',
@ -57,7 +60,7 @@
beforeSend: function (request) {
request.setRequestHeader('Accept', 'application/json');
},
success: _.bind(this._createRoomSuccessHandle, this)
success: _.bind(this._createCallSuccessHandle, this)
});
},
createPublicVideoCall: function() {
@ -71,11 +74,11 @@
beforeSend: function (request) {
request.setRequestHeader('Accept', 'application/json');
},
success: _.bind(this._createRoomSuccessHandle, this)
success: _.bind(this._createCallSuccessHandle, this)
});
},
join: function(token) {
if (OCA.SpreedMe.Rooms.currentRoom() === token) {
if (signaling.currentCallToken === token) {
return;
}
@ -84,59 +87,19 @@
$('#app-content').addClass('icon-loading');
OCA.SpreedMe.webrtc.leaveRoom();
currentRoom = token;
OCA.SpreedMe.webrtc.joinRoom(token);
OCA.SpreedMe.Rooms.ping();
},
leaveCurrentRoom: function() {
leaveCurrentCall: function(deleter) {
OCA.SpreedMe.webrtc.leaveRoom();
OC.Util.History.pushState({}, OC.generateUrl('/apps/spreed'));
$('#app-content').removeClass('incall');
currentRoom = '';
},
currentRoom: function() {
return currentRoom;
},
peers: function(token) {
return $.ajax({
beforeSend: function (request) {
request.setRequestHeader('Accept', 'application/json');
},
url: OC.linkToOCS('apps/spreed/api/v1/call', 2) + token
});
this.showRoomDeletedMessage(deleter);
},
ping: function() {
if (OCA.SpreedMe.Rooms.currentRoom() === '') {
return;
leaveAllCalls: function() {
if (signaling) {
// We currently only support a single active call.
signaling.leaveCurrentCall();
}
$.ajax({
url: OC.linkToOCS('apps/spreed/api/v1/call', 2) + OCA.SpreedMe.Rooms.currentRoom() + '/ping',
method: 'POST'
}).done(function() {
pingFails = 0;
}).fail(function(xhr) {
// If there is an error when pinging, retry for 3 times.
if (xhr.status !== 404 && pingFails < 3) {
pingFails++;
return;
}
OCA.SpreedMe.Rooms.leaveCurrentRoom();
OCA.SpreedMe.Rooms.showRoomDeletedMessage(false);
});
},
leaveAllRooms: function() {
var token = OCA.SpreedMe.Rooms.currentRoom();
if (!token) {
return;
}
$.ajax({
url: OC.linkToOCS('apps/spreed/api/v1/call', 2) + token,
method: 'DELETE',
async: false
});
},
showRoomDeletedMessage: function(deleter) {
if (deleter) {
@ -154,6 +117,6 @@
}
};
OCA.SpreedMe.initRooms = initRooms;
OCA.SpreedMe.initCalls = initCalls;
})(OCA, OC, $);

243
js/signaling.js

@ -5,6 +5,7 @@
function SignalingBase() {
this.sessionId = '';
this.currentCallToken = null;
this.handlers = {};
}
@ -38,9 +39,55 @@
};
SignalingBase.prototype.disconnect = function() {
console.log('disconnect');
this.sessionId = '';
this.currentCallToken = null;
};
SignalingBase.prototype.emit = function(ev, data) {
switch (ev) {
case 'join':
var callback = arguments[2];
var token = data;
this.joinCall(token, callback);
break;
case 'leave':
this.leaveCurrentCall();
break;
case 'message':
this.sendCallMessage(data);
break;
}
};
SignalingBase.prototype.leaveCurrentCall = function() {
if (this.currentCallToken) {
this.leaveCall(this.currentCallToken);
this.currentCallToken = null;
}
};
SignalingBase.prototype.leaveAllCalls = function() {
// Override if necessary.
};
SignalingBase.prototype.setRoomCollection = function(rooms) {
this.roomCollection = rooms;
return this.syncRooms();
};
SignalingBase.prototype.syncRooms = function() {
var defer = $.Deferred();
if (this.roomCollection && oc_current_user) {
this.roomCollection.fetch({
success: function(data) {
defer.resolve(data);
}
});
} else {
defer.resolve([]);
}
return defer;
};
// Connection to the internal signaling server provided by the app.
function InternalSignaling() {
@ -48,6 +95,9 @@
this.spreedArrayConnection = [];
this._openEventSource();
this.pingFails = 0;
this.pingInterval = null;
this.sendInterval = window.setInterval(function(){
this.sendPendingMessages();
}.bind(this), 500);
@ -66,6 +116,14 @@
window.clearInterval(this.sendInterval);
this.sendInterval = null;
}
if (this.pingInterval) {
window.clearInterval(this.pingInterval);
this.pingInterval = null;
}
if (this.roomPoller) {
window.clearInterval(this.roomPoller);
this.roomPoller = null;
}
SignalingBase.prototype.disconnect.apply(this, arguments);
};
@ -99,57 +157,99 @@
}.bind(this));
};
InternalSignaling.prototype.emit = function(ev, data) {
switch (ev) {
case 'join':
// The client is joining a new room, in this case we need
// to do the following:
//
// 1. Get a list of connected clients to the room
// 2. Return the list of connected clients
// 3. Connect to the room with the clients as list here
//
// The clients will then use the message command to exchange
// their signalling information.
var callback = arguments[2];
$.ajax({
url: OC.linkToOCS('apps/spreed/api/v1/call', 2) + data,
type: 'POST',
beforeSend: function (request) {
request.setRequestHeader('Accept', 'application/json');
},
success: function (result) {
this.sessionId = result.ocs.data.sessionId;
OCA.SpreedMe.Rooms.peers(data).then(function(result) {
var roomDescription = {
'clients': {}
InternalSignaling.prototype.joinCall = function(token, callback) {
// The client is joining a new call, in this case we need
// to do the following:
//
// 1. Join the call as participant.
// 2. Get a list of other connected clients in the call.
// 3. Pass information about other clients to the callback.
//
// The clients will then use the message command to exchange
// their signalling information.
$.ajax({
url: OC.linkToOCS('apps/spreed/api/v1/call', 2) + token,
type: 'POST',
beforeSend: function (request) {
request.setRequestHeader('Accept', 'application/json');
},
success: function (result) {
console.log("Joined", result);
this.sessionId = result.ocs.data.sessionId;
this.currentCallToken = token;
this._startPingCall();
this._getCallPeers(token).then(function(peers) {
var callDescription = {
'clients': {}
};
peers.forEach(function(element) {
if (this.sessionId !== element['sessionId']) {
callDescription['clients'][element['sessionId']] = {
'video': true
};
}
}.bind(this));
callback('', callDescription);
}.bind(this));
}.bind(this)
});
};
result.ocs.data.forEach(function(element) {
if (this.sessionId !== element['sessionId']) {
roomDescription['clients'][element['sessionId']] = {
'video': true
};
}
}.bind(this));
callback('', roomDescription);
}.bind(this));
}.bind(this)
});
break;
case 'message':
if(data.type === 'answer') {
console.log("ANSWER", data);
} else if(data.type === 'offer') {
console.log("OFFER", data);
}
this.spreedArrayConnection.push({
ev: ev,
fn: JSON.stringify(data),
sessionId: this.sessionId
});
break;
InternalSignaling.prototype.leaveCall = function(token) {
if (token === this.currentCallToken) {
this._stopPingCall();
}
$.ajax({
url: OC.linkToOCS('apps/spreed/api/v1/call', 2) + token,
method: 'DELETE',
async: false
});
};
InternalSignaling.prototype.sendCallMessage = function(data) {
if(data.type === 'answer') {
console.log("ANSWER", data);
} else if(data.type === 'offer') {
console.log("OFFER", data);
}
this.spreedArrayConnection.push({
ev: "message",
fn: JSON.stringify(data),
sessionId: this.sessionId
});
};
InternalSignaling.prototype.setRoomCollection = function(/*rooms*/) {
this._pollForRoomChanges();
return SignalingBase.prototype.setRoomCollection.apply(this, arguments);
};
InternalSignaling.prototype._pollForRoomChanges = function() {
if (this.roomPoller) {
window.clearInterval(this.roomPoller);
}
this.roomPoller = window.setInterval(function() {
this.syncRooms();
}.bind(this), 10000);
};
/**
* @private
*/
InternalSignaling.prototype._getCallPeers = function(token) {
var defer = $.Deferred();
$.ajax({
beforeSend: function (request) {
request.setRequestHeader('Accept', 'application/json');
},
url: OC.linkToOCS('apps/spreed/api/v1/call', 2) + token,
success: function (result) {
var peers = result.ocs.data;
defer.resolve(peers);
}
});
return defer;
};
/**
@ -192,6 +292,51 @@
this.spreedArrayConnection = [];
};
/**
* @private
*/
InternalSignaling.prototype._startPingCall = function() {
this._pingCall();
// Send a ping to the server all 5 seconds to ensure that the connection
// is still alive.
this.pingInterval = window.setInterval(function() {
this._pingCall();
}.bind(this), 5000);
};
/**
* @private
*/
InternalSignaling.prototype._stopPingCall = function() {
if (this.pingInterval) {
window.clearInterval(this.pingInterval);
this.pingInterval = null;
}
};
/**
* @private
*/
InternalSignaling.prototype._pingCall = function() {
if (!this.currentCallToken) {
return;
}
$.ajax({
url: OC.linkToOCS('apps/spreed/api/v1/call', 2) + this.currentCallToken + '/ping',
method: 'POST'
}).done(function() {
this.pingFails = 0;
}.bind(this)).fail(function(xhr) {
// If there is an error when pinging, retry for 3 times.
if (xhr.status !== 404 && this.pingFails < 3) {
this.pingFails++;
return;
}
OCA.SpreedMe.Calls.leaveCurrentCall(false);
}.bind(this));
};
OCA.SpreedMe.createSignalingConnection = function() {
// TODO(fancycode): Create different type of signaling connection
// depending on configuration.

21
js/views/roomlistview.js

@ -316,11 +316,9 @@
}
},
leaveRoom: function() {
//If user is in that room, it should leave that room first.
// If user is in that room, it should leave the associated call first.
if (this.model.get('active')) {
OCA.SpreedMe.Rooms.leaveCurrentRoom();
OCA.SpreedMe.Rooms.showRoomDeletedMessage(true);
OC.Util.History.pushState({}, OC.generateUrl('/apps/spreed'));
OCA.SpreedMe.Calls.leaveCurrentCall(true);
}
this.$el.slideUp();
@ -353,7 +351,7 @@
joinRoom: function(e) {
e.preventDefault();
var token = this.ui.room.attr('data-token');
OCA.SpreedMe.Rooms.join(token);
OCA.SpreedMe.Calls.join(token);
OC.Util.History.pushState({
token: token
@ -569,16 +567,9 @@
}
});
this.ui.personSelectorInput.on('change', function(e) {
var app = OCA.SpreedMe.app;
$.post(
OC.linkToOCS('apps/spreed/api/v1/room', 2) + _this.model.get('token') + '/participants',
{
newParticipant: e.val
}
).done(function() {
app.syncRooms();
});
var token = _this.model.get('token');
var participant = e.val;
OCA.SpreedMe.app.addParticipantToRoom(token, participant);
$('.select2-drop').find('.avatar').each(function () {
var element = $(this);

176
js/webrtc.js

@ -2,7 +2,7 @@
/* global SimpleWebRTC, OC, OCA: false */
var webrtc;
var spreedMappingTable = [];
var spreedMappingTable = {};
var spreedPeerConnectionTable = [];
(function(OCA, OC) {
@ -10,9 +10,97 @@ var spreedPeerConnectionTable = [];
OCA.SpreedMe = OCA.SpreedMe || {};
var previousUsersInRoom = [];
function updateParticipantsUI(currentUsersNo) {
'use strict';
if (!currentUsersNo) {
currentUsersNo = 1;
}
var appContentElement = $('#app-content'),
participantsClass = 'participants-' + currentUsersNo;
if (!appContentElement.hasClass(participantsClass) && !appContentElement.hasClass('screensharing')) {
appContentElement.attr('class', '').addClass(participantsClass);
if (currentUsersNo > 1) {
appContentElement.addClass('incall');
} else {
appContentElement.removeClass('incall');
}
}
}
function usersChanged(newUsers, disconnectedSessionIds) {
'use strict';
var currentSessionId = webrtc.connection.getSessionid();
newUsers.forEach(function(user) {
// TODO(fancycode): Adjust property name of internal PHP backend to be all lowercase.
var sessionId = user.sessionId || user.sessionid;
if (!sessionId || sessionId === currentSessionId || previousUsersInRoom.indexOf(sessionId) !== -1) {
return;
}
previousUsersInRoom.push(sessionId);
// TODO(fancycode): Adjust property name of internal PHP backend to be all lowercase.
spreedMappingTable[sessionId] = user.userId || user.userid;
var videoContainer = $(OCA.SpreedMe.videos.getContainerId(sessionId));
if (videoContainer.length === 0) {
OCA.SpreedMe.videos.add(sessionId);
}
var peer;
// To avoid overloading the user joining a room (who previously called
// all the other participants), we decide who calls who by comparing
// the session ids of the users: "larger" ids call "smaller" ones.
if (sessionId < currentSessionId && !webrtc.webrtc.getPeers(sessionId, 'video').length) {
console.log("Starting call with", user);
peer = webrtc.webrtc.createPeer({
id: sessionId,
type: "video",
enableDataChannels: true,
receiveMedia: {
offerToReceiveAudio: 1,
offerToReceiveVideo: 1
}
});
webrtc.emit('createdPeer', peer);
peer.start();
}
//Send shared screen to new participants
if (webrtc.getLocalScreen() && !webrtc.webrtc.getPeers(sessionId, 'screen').length) {
peer = webrtc.webrtc.createPeer({
id: sessionId,
type: 'screen',
sharemyscreen: true,
enableDataChannels: false,
receiveMedia: {
offerToReceiveAudio: 0,
offerToReceiveVideo: 0
},
broadcaster: currentSessionId,
});
webrtc.emit('createdPeer', peer);
peer.start();
}
});
disconnectedSessionIds.forEach(function(sessionId) {
console.log('XXX Remove peer', sessionId);
OCA.SpreedMe.webrtc.removePeers(sessionId);
OCA.SpreedMe.speakers.remove(sessionId, true);
OCA.SpreedMe.videos.remove(sessionId);
delete spreedMappingTable[sessionId];
});
previousUsersInRoom = previousUsersInRoom.diff(disconnectedSessionIds);
updateParticipantsUI(previousUsersInRoom.length + 1);
}
function initWebRTC() {
'use strict';
var previousUsersInRoom = [];
Array.prototype.diff = function(a) {
return this.filter(function(i) {
return a.indexOf(i) < 0;
@ -20,69 +108,37 @@ var spreedPeerConnectionTable = [];
};
var signaling = OCA.SpreedMe.createSignalingConnection();
signaling.on('usersJoined', function(users) {
usersChanged(users, []);
});
signaling.on('usersLeft', function(users) {
usersChanged([], users);
});
signaling.on('usersInRoom', function(users) {
// The passed list are the users that are currently in the room,
// i.e. that are in the call and should call each other.
var currentSessionId = webrtc.connection.getSessionid();
var currentUsersInRoom = [];
var webrtc = OCA.SpreedMe.webrtc;
var currentUser = webrtc.connection.getSessionid();
var userMapping = {};
users.forEach(function(user) {
var sessionId = user['sessionId'];
currentUsersInRoom.push(sessionId);
spreedMappingTable[sessionId] = user['userId'];
if (sessionId && currentUser !== sessionId) {
var videoContainer = $(OCA.SpreedMe.videos.getContainerId(sessionId));
if (videoContainer.length === 0) {
OCA.SpreedMe.videos.add(sessionId);
}
}
});
var currentUsersNo = currentUsersInRoom.length;
if(currentUsersNo === 0) {
currentUsersNo = 1;
}
var appContentElement = $('#app-content'),
participantsClass = 'participants-' + currentUsersNo;
if (!appContentElement.hasClass(participantsClass) && !appContentElement.hasClass('screensharing')) {
appContentElement.attr('class', '').addClass(participantsClass);
if (currentUsersNo > 1) {
appContentElement.addClass('incall');
} else {
appContentElement.removeClass('incall');
var sessionId = user['sessionId'] || user.sessionid;
if (sessionId === currentSessionId) {
return;
}
}
//Send shared screen to new participants
if (webrtc.getLocalScreen()) {
var newUsers = currentUsersInRoom.diff(previousUsersInRoom);
newUsers.forEach(function(user) {
if (user !== currentUser) {
var peer = webrtc.webrtc.createPeer({
id: user,
type: 'screen',
sharemyscreen: true,
enableDataChannels: false,
receiveMedia: {
offerToReceiveAudio: 0,
offerToReceiveVideo: 0
},
broadcaster: currentUser,
});
webrtc.emit('createdPeer', peer);
peer.start();
}
});
}
currentUsersInRoom.push(sessionId);
userMapping[sessionId] = user;
});
var disconnectedUsers = previousUsersInRoom.diff(currentUsersInRoom);
disconnectedUsers.forEach(function(user) {
console.log('XXX Remove peer', user);
OCA.SpreedMe.webrtc.removePeers(user);
OCA.SpreedMe.speakers.remove(user, true);
OCA.SpreedMe.videos.remove(user);
var newSessionIds = currentUsersInRoom.diff(previousUsersInRoom);
var disconnectedSessionIds = previousUsersInRoom.diff(currentUsersInRoom);
var newUsers = [];
newSessionIds.forEach(function(sessionId) {
newUsers.push(userMapping[sessionId]);
});
previousUsersInRoom = currentUsersInRoom;
if (newUsers.length || disconnectedSessionIds.length) {
usersChanged(newUsers, disconnectedSessionIds);
}
});
var nick = OC.getCurrentUser()['displayName'];
@ -533,7 +589,7 @@ var spreedPeerConnectionTable = [];
});
OCA.SpreedMe.webrtc.on('localMediaStarted', function (configuration) {
OCA.SpreedMe.app.startSpreed(configuration);
OCA.SpreedMe.app.startSpreed(configuration, signaling);
});
OCA.SpreedMe.webrtc.on('localMediaError', function(error) {
@ -626,7 +682,7 @@ var spreedPeerConnectionTable = [];
var nameIndicator = videoContainer.find('.nameIndicator');
var avatar = videoContainer.find('.avatar');
if (userId.length) {
if (userId && userId.length) {
avatar.avatar(userId, 128);
nameIndicator.text(peer.nick);
} else if (peer.nick) {

2
templates/index-public.php

@ -18,7 +18,7 @@ script(
'simplewebrtc',
'webrtc',
'signaling',
'rooms',
'calls',
'app',
'init',
]

2
templates/index.php

@ -18,7 +18,7 @@ script(
'simplewebrtc',
'webrtc',
'signaling',
'rooms',
'calls',
'app',
'init',
]

Loading…
Cancel
Save