webrtc-chat/client-website/js/app.js

440 lines
15 KiB
JavaScript

//
// AngilarJS controller
function SympleChat($scope) {
$scope.client;
$scope.localPlayer;
$scope.remotePlayer;
$scope.remoteVideoPeer;
$scope.handle;
$scope.directUser;
$scope.peers = [];
$scope.messages = [];
$scope.messageText = "";
$scope.errorText = "";
$scope.isLoading = false;
$scope.audioEnabled = true;
$scope.videoEnabled = true;
$scope.isFullscreen = false;
$scope.localVideoPlaying = false;
$(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange', function() {
if (!document.fullscreenElement && // alternative standard method
!document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement ) {
$('.button-fullscreen').addClass('glyphicon-resize-full').removeClass('glyphicon-resize-small');
} else {
$('.button-fullscreen').addClass('glyphicon-resize-small').removeClass('glyphicon-resize-full');
}
});
$(document).ready(function() {
$('[data-toggle="tooltip"]').tooltip();
//
// Client
$scope.client = new Symple.Client(CLIENT_OPTIONS);
$scope.client.on('announce', function(peer) {
//console.log('announce:', peer)
$scope.isLoading = false;
$scope.$apply();
});
$scope.client.on('presence', function(p) {
//console.log('presence:', p)
});
$scope.client.on('message', function(m) {
//console.log('message:', m)
// Normal Message
if (!m.direct || m.direct == $scope.handle) {
$scope.messages.unshift({
user: m.from.user,
data: m.data,
direct: m.direct,
time: Symple.formatTime(new Date)
});
$scope.$apply();
}
else
console.log('dropping message:', m, m.direct)
});
$scope.client.on('command', function(c) {
//console.log('command:', c)
if (c.node == 'call:init') {
if (!c.status) {
if ($scope.remoteVideoPeer || $scope.localVideoPlaying) {
c.status = 501;
$scope.client.respond(c);
return;
}
// Show a dialog to the user asking if they want to accept the call
var e = $('#incoming-call-modal')
e.find('.caller').text('@' + c.from.user)
e.find('.accept').unbind('click').click(function() {
c.status = 200;
$scope.remoteVideoPeer = c.from;
$scope.client.respond(c);
$scope.$apply();
e.modal('hide')
})
e.find('.reject').unbind('click').click(function() {
c.status = 500;
$scope.client.respond(c);
e.modal('hide')
})
e.modal({backdrop:'static',keyboard:false})
e.modal('show')
}
else if (c.status == 200) {
// Handle call accepted
var e = $('#outgoing-call-modal')
e.modal('hide')
$scope.remoteVideoPeer = c.from;
$scope.startLocalVideo();
$scope.$apply();
}
else if (c.status == 500) {
// Handle call rejected
var e = $('#callee-rejected')
e.find('.rejected').text('... rejected your call')
e.modal('show')
}
else if (c.status == 501) {
// Handle call busy
var e = $('#callee-rejected')
e.find('.rejected').text('... is busy')
e.modal('show')
}
else {
alert('Unknown response status')
}
}
else if (c.node == 'call:end') {
if (c.from.user == $scope.remoteVideoPeer.user) {
$scope.toggleCallend();
}
}
});
$scope.client.on('event', function(e) {
//console.log('event:', e)
// Only handle events from the remoteVideoPeer
if (!$scope.remoteVideoPeer || $scope.remoteVideoPeer.id != e.from.id) {
console.log('mismatch event:', e.from, $scope.remoteVideoPeer)
return
}
// ICE SDP
if (e.name == 'call:ice:sdp') {
if (e.sdp.type == 'offer') {
// Create the remote player on offer
if (!$scope.remotePlayer) {
$scope.remotePlayer = createPlayer($scope, 'answerer', '#video .remote-video');
$scope.remotePlayer.play();
}
$scope.remotePlayer.engine.onRemoteSDP(e.sdp);
}
if (e.sdp.type == 'answer') {
$scope.localPlayer.engine.onRemoteSDP(e.sdp);
}
}
// ICE Candidate
else if (e.name == 'call:ice:candidate') {
if (e.origin == 'answerer')
$scope.localPlayer.engine.onRemoteCandidate(e.candidate);
else if (e.origin == 'caller')
$scope.remotePlayer.engine.onRemoteCandidate(e.candidate);
else
alert('Unknown candidate origin');
}
else {
alert('Unknown event: ' + e.name);
}
});
$scope.client.on('disconnect', function() {
console.log('disconnected')
$scope.isLoading = false;
$scope.errorText = 'Disconnected from the server';
$scope.$apply();
});
$scope.client.on('error', function(error, message) {
console.log('connection error:', error, message)
$scope.isLoading = false;
$scope.errorText = 'Cannot connect to the server.';
$scope.$apply();
});
$scope.client.on('addPeer', function(peer) {
console.log('add peer:', peer)
$scope.peers.push(peer);
$scope.$apply();
});
$scope.client.on('removePeer', function(peer) {
console.log('remove peer:', peer)
for (var i =0; i < $scope.peers.length; i++) {
if ($scope.peers[i].id === peer.id) {
$scope.peers.splice(i,1);
$scope.$apply();
break;
}
}
});
// Init handle from URL if available
var handle = getHandleFromURL();
if (handle && handle.length) {
$scope.handle = handle;
$scope.login();
}
var cok = getCookie("username");
if (cok != "") {
$scope.handle=cok;
$scope.login();
}
});
//
// Messaging
$scope.setMessageTarget = function(user) {
console.log('setMessageTarget', user)
$scope.directUser = user ? user : ''
$('#post-message .direct-user').text('@' + $scope.directUser)
$('#post-message .message-text')[0].focus()
}
$scope.sendMessage = function() {
if ($scope.messageText.length == 0) {
return;
}
console.log('sendMessage', $scope.messageText);
$scope.client.sendMessage({
data: $scope.messageText,
direct: $scope.directUser
});
$scope.messages.unshift({
direct: $scope.directUser,
user: $scope.handle,
data: $scope.messageText,
time: Symple.formatTime(new Date)
});
$scope.messageText = "";
};
// Login
$scope.login = function() {
if (!$scope.handle || $scope.handle.length < 3) {
alert('Please enter 3 or more alphanumeric characters.');
return;
}
setCookie("username", $scope.handle, 365);
$scope.client.options.peer.user = $scope.handle;
$scope.client.connect();
$scope.isLoading = true;
$scope.$apply();
}
$scope.logout = function() {
setCookie("username", "", 1);
// $scope.toggleCallend2();
$scope.client.disconnect();
document.location.reload(false);
/*
// should not call $scope.$apply();
// $scope.toggleCallend2();
$scope.client.disconnect();
// $scope.client = undefined;
$scope.handle = undefined;
$scope.peers = [];
$scope.messages = [];
$scope.messageText = "";
$scope.errorText = "";
$scope.$apply();*/
}
//
// Video
$scope.startVideoCall = function(user) {
if (assertGetUserMedia()) {
console.log('startVideoCall', user)
if (user == $scope.handle) {
alert('Cannot video chat with yourself. Please open a new browser window and login with a different handle.');
return;
}
$scope.client.sendCommand({
node: 'call:init',
to: { user: user }
})
var e = $('#outgoing-call-modal')
e.find(".callee").text("@" + user)
e.modal('show')
var f = $('#callee-rejected')
f.find(".rejected").text("")
}
}
$scope.startLocalVideo = function() {
if (assertGetUserMedia()) {
// Init local video player
$scope.localPlayer = createPlayer($scope, 'caller', '#video .local-video');
$scope.localPlayer.play({ localMedia: true, disableAudio: false });
$scope.localPlayer.muteLocal();
// TODO: Set false on session end or Symple error
$scope.localVideoPlaying = true;
// enable controls
/*$('.local-video-wrap').mouseenter(function () {
$('.local-video-control-wrap').stop().fadeIn('100');
});
$('.local-video-wrap').mouseleave(function () {
$('.local-video-control-wrap').stop().fadeOut('100');
});*/
}
}
//
// Helpers
$scope.isLoggedIn = function() {
return $scope.handle != null && $scope.client.online();
}
$scope.isSelfUser = function(u) {
return $scope.handle == u;
}
$scope.getMessageClass = function(m) {
if (m.direct)
return 'list-group-item-warning';
return '';
}
$scope.toggleAudio = function() {
if ($scope.localPlayer != null)
{
if ($scope.audioEnabled) {
$('.button-audio').addClass('glyphicon-volume-off').removeClass('glyphicon-volume-up');
$scope.audioEnabled = false;
} else {
$('.button-audio').addClass('glyphicon-volume-up').removeClass('glyphicon-volume-off');
$scope.audioEnabled = true;
}
$scope.localPlayer.toggleAudio();
}
}
$scope.toggleVideo = function() {
if ($scope.localPlayer != null)
{
if ($scope.videoEnabled) {
$('.button-video').addClass('glyphicon-eye-close').removeClass('glyphicon-eye-open');
$scope.videoEnabled = false;
} else {
$('.button-video').addClass('glyphicon-eye-open').removeClass('glyphicon-eye-close');
$scope.videoEnabled = true;
}
$scope.localPlayer.toggleVideo();
}
}
$scope.toggleFullscreen = function() {
if ($scope.remotePlayer != null)
{
//$scope.remotePlayer.fullscreenVideo();
var video = $('#video-fullscreen');
if (!document.fullscreenElement && // alternative standard method
!document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement ) {
if (video[0].requestFullscreen) {
video[0].requestFullscreen();
} else if (video[0].mozRequestFullScreen) {
video[0].mozRequestFullScreen();
} else if (video[0].webkitRequestFullscreen) {
video[0].webkitRequestFullscreen();
}
} else {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
}
}
}
}
$scope.toggleCallend = function() {
if ($scope.remotePlayer != undefined) {
if ($scope.isFullscreen) {
$scope.toggleFullscreen();
}
$scope.remotePlayer.stop();
$scope.remotePlayer = undefined;
}
if ($scope.localPlayer != undefined) {
if (!$scope.videoEnabled) {
$scope.toggleVideo();
}
if (!$scope.audioEnabled) {
$scope.toggleAudio();
}
$scope.localPlayer.stop();
$scope.localPlayer = undefined;
}
$scope.remoteVideoPeer = undefined;
$scope.localVideoPlaying = false;
$scope.$apply();
}
$scope.toggleCallend2 = function() {
$scope.client.sendCommand({
node: 'call:end',
to: { user: $scope.remoteVideoPeer.user }
});
$scope.toggleCallend();
}
}
function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var expires = "expires="+d.toUTCString();
document.cookie = cname + "=" + cvalue + "; " + expires;
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i=0; i<ca.length; i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1);
if (c.indexOf(name) == 0) return c.substring(name.length,c.length);
}
return "";
}