diff --git a/build/build.js b/build/build.js
index 0e0528d2..4ba0524a 100644
--- a/build/build.js
+++ b/build/build.js
@@ -18,6 +18,7 @@
* along with this program. If not, see .
*
*/
+/*jshint -W030 */
({
baseUrl: '../static/js',
mainConfigFile: '../static/js/main.js',
diff --git a/doc/plugin-test-authorize.js b/doc/plugin-test-authorize.js
index bd645962..35f9b5ce 100644
--- a/doc/plugin-test-authorize.js
+++ b/doc/plugin-test-authorize.js
@@ -50,14 +50,14 @@ define(['angular', 'sjcl'], function(angular, sjcl) {
$window.testCreateSuseridLocal = function(key, userid) {
var k = sjcl.codec.utf8String.toBits(key);
- var foo = new sjcl.misc.hmac(k, sjcl.hash.sha256)
- var expiration = parseInt(((new Date).getTime()/1000)+3600, 10);
+ var foo = new sjcl.misc.hmac(k, sjcl.hash.sha256);
+ var expiration = parseInt(((new Date()).getTime()/1000)+3600, 10);
var useridCombo = ""+expiration+":"+userid;
var secret = foo.mac(useridCombo);
var data = {
useridcombo: useridCombo,
secret: sjcl.codec.base64.fromBits(secret)
- }
+ };
lastData = data;
return data;
@@ -86,7 +86,7 @@ define(['angular', 'sjcl'], function(angular, sjcl) {
$window.testLastAuthenticate = function() {
if (!lastNonce || !lastUserid) {
console.log("Run testAuthorize first.");
- return
+ return;
}
mediaStream.api.requestAuthentication(lastUserid, lastNonce);
};
@@ -94,7 +94,7 @@ define(['angular', 'sjcl'], function(angular, sjcl) {
$window.testLastAuthorize = function() {
if (lastData === null) {
console.log("Run testCreateSuseridServer fist.");
- return
+ return;
}
$window.testAuthorize(lastData);
};
@@ -103,6 +103,6 @@ define(['angular', 'sjcl'], function(angular, sjcl) {
}
- }
+ };
-});
\ No newline at end of file
+});
diff --git a/src/styles/components/_buddypicture.scss b/src/styles/components/_buddypicture.scss
new file mode 100644
index 00000000..af2322ab
--- /dev/null
+++ b/src/styles/components/_buddypicture.scss
@@ -0,0 +1,56 @@
+/*
+ * Spreed WebRTC.
+ * Copyright (C) 2013-2014 struktur AG
+ *
+ * This file is part of Spreed WebRTC.
+ *
+ * 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 .
+ *
+ */
+
+.buddyPicture {
+ .picture {
+ display: block;
+ margin-bottom: 5px;
+ }
+ .videoPicture {
+ position: relative;
+ }
+ .preview {
+ left: 0;
+ position: absolute;
+ top: 0;
+ &.previewPicture {
+ position: relative;
+ }
+ }
+ .showTakePicture {
+ .btn {
+ margin: 5px 0px;
+ }
+ }
+ .btn-takePicture,
+ .btn-retakePicture {
+ left: 85px;
+ position: absolute;
+ top: 110px;
+ }
+ .countdownPicture {
+ color: $componentbg;
+ font-size: 45px;
+ left: 90px;
+ position: absolute;
+ top: 55px;
+ }
+}
diff --git a/src/styles/main.scss b/src/styles/main.scss
index 4d9c69bf..90b959ad 100644
--- a/src/styles/main.scss
+++ b/src/styles/main.scss
@@ -35,6 +35,7 @@
@import "components/rightslide";
@import "components/bar";
@import "components/buddylist";
+@import "components/buddypicture";
@import "components/settings";
@import "components/chat";
@import "components/usability";
diff --git a/static/js/directives/buddypicture.js b/static/js/directives/buddypicture.js
new file mode 100644
index 00000000..4e88a1c8
--- /dev/null
+++ b/static/js/directives/buddypicture.js
@@ -0,0 +1,172 @@
+/*
+ * Spreed WebRTC.
+ * Copyright (C) 2013-2014 struktur AG
+ *
+ * This file is part of Spreed WebRTC.
+ *
+ * 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 .
+ *
+ */
+define(['jquery', 'underscore', 'text!partials/buddypicture.html'], function($, _, template) {
+
+ return ["$compile", function($compile) {
+
+ var controller = ['$scope', 'safeApply', '$timeout', '$q', function($scope, safeApply, $timeout, $q) {
+
+ $scope.showTakePicture = false;
+ $scope.waitingForPermission = false;
+ $scope.previewPicture = false;
+ $scope.countingDown = false;
+ $scope.video = null;
+ $scope.canvasPic = null;
+ $scope.canvasPrev = null;
+
+ var localStream = null;
+ var delayToTakePicture = 3000;
+ var countDownFrom = 3;
+
+ // Counts down from start to 1
+ var takePictureCountDown = function(start, delayTotal) {
+ $scope.countingDown = true;
+ $scope.countdown = {};
+ $scope.countdown.num = start;
+ var decrementNum = function(num) {
+ $timeout(function() {
+ $scope.countdown.num--;
+ if($scope.countdown.num === 0) {
+ $scope.countingDown = false;
+ }
+ }, delayTotal/start*num);
+ };
+ for(var i = 1; i <= start; i++) {
+ decrementNum(i);
+ }
+ };
+
+ var getCanvasAspectRatio = function() {
+ var videoWidth = $scope.video.videoWidth;
+ var videoHeight = $scope.video.videoHeight;
+ var aspectRatio = videoWidth/videoHeight;
+ if (!aspectRatio) {
+ // NOTE(longsleep): In Firefox the video size becomes available at sound point later - crap!
+ console.warn("Unable to compute aspectRatio", aspectRatio);
+ aspectRatio = 1.3333333333333333;
+ }
+ return aspectRatio;
+ };
+
+ var writePreviewPic = function() {
+ $scope.canvasPrev.getContext("2d").drawImage($scope.video, 0, 0, $scope.video.width, $scope.video.width/getCanvasAspectRatio());
+ $scope.preview = $scope.canvasPrev.toDataURL("image/jpeg");
+ };
+
+ var makePicture = function(stream, cntFrom, delayTotal) {
+ takePictureCountDown(cntFrom, delayTotal);
+ $timeout(function() {
+ videoStop(stream, $scope.video);
+ writePreviewPic();
+ $scope.previewPicture = true;
+ }, delayTotal);
+ };
+
+ var videoStop = function(stream, video) {
+ if (stream) {
+ video.pause();
+ stream.stop();
+ stream = null;
+ }
+ };
+
+ var videoStart = function() {
+ $scope.waitingForPermission = true;
+ var videoConstraints = true;
+ var videoAllowed = $q.defer();
+ if ($scope.user.settings.cameraId) {
+ videoConstraints = {
+ optional: [{
+ sourceId: $scope.user.settings.cameraId
+ }]
+ };
+ }
+ getUserMedia({
+ video: videoConstraints
+ }, function(stream) {
+ $scope.showTakePicture = true;
+ localStream = stream;
+ $scope.waitingForPermission = false;
+ attachMediaStream($scope.video, stream);
+ safeApply($scope);
+ videoAllowed.resolve(true);
+ }, function(error) {
+ console.error('Failed to get access to local media. Error code was ' + error.code);
+ $scope.waitingForPermission = false;
+ safeApply($scope);
+ videoAllowed.resolve(false);
+ });
+ return videoAllowed.promise;
+ };
+
+ $scope.initPicture = function() {
+ videoStart(localStream);
+ };
+
+ $scope.cancelPicture = function() {
+ $scope.showTakePicture = false;
+ $scope.previewPicture = false;
+ videoStop(localStream, $scope.video);
+ };
+
+ $scope.retakePicture = function() {
+ var permission = videoStart(localStream);
+ permission.then(function(isPermitted) {
+ if(isPermitted) {
+ $scope.previewPicture = false;
+ makePicture(localStream, countDownFrom, delayToTakePicture);
+ }
+ });
+ };
+
+ $scope.takePicture = function() {
+ makePicture(localStream, countDownFrom, delayToTakePicture);
+ };
+
+ $scope.setAsProfilePicture = function() {
+ var x = (46 * getCanvasAspectRatio() - 46) / -2;
+ $scope.canvasPic.getContext("2d").drawImage($scope.video, x, 0, 46 * getCanvasAspectRatio(), 46);
+ $scope.user.buddyPicture = $scope.canvasPic.toDataURL("image/jpeg");
+ console.info("Image size", $scope.user.buddyPicture.length);
+ $scope.cancelPicture();
+ safeApply($scope);
+ };
+
+ }];
+
+ var link = function($scope, $element) {
+ $scope.video = $element.find("video").get(0);
+ $scope.canvasPic = $element.find("canvas#pic").get(0);
+ $scope.canvasPrev = $element.find("canvas#prev").get(0);
+ };
+
+ return {
+ scope: true,
+ restrict: 'E',
+ replace: true,
+ template: template,
+ controller: controller,
+ link: link
+ };
+
+ }];
+
+});
diff --git a/static/js/directives/directives.js b/static/js/directives/directives.js
index 66bfbe79..510fd6e3 100644
--- a/static/js/directives/directives.js
+++ b/static/js/directives/directives.js
@@ -25,6 +25,7 @@ define([
'directives/onescape',
'directives/statusmessage',
'directives/buddylist',
+ 'directives/buddypicture',
'directives/settings',
'directives/chat',
'directives/audiovideo',
@@ -34,13 +35,14 @@ define([
'directives/screenshare',
'directives/roombar',
'directives/socialshare',
- 'directives/page'], function(_, onEnter, onEscape, statusMessage, buddyList, settings, chat, audioVideo, usability, audioLevel, fileInfo, screenshare, roomBar, socialShare, page) {
+ 'directives/page'], function(_, onEnter, onEscape, statusMessage, buddyList, buddyPicture, settings, chat, audioVideo, usability, audioLevel, fileInfo, screenshare, roomBar, socialShare, page) {
var directives = {
onEnter: onEnter,
onEscape: onEscape,
statusMessage: statusMessage,
buddyList: buddyList,
+ buddyPicture: buddyPicture,
settings: settings,
chat: chat,
audioVideo: audioVideo,
diff --git a/static/js/directives/settings.js b/static/js/directives/settings.js
index 69a1b2c9..6716aa05 100644
--- a/static/js/directives/settings.js
+++ b/static/js/directives/settings.js
@@ -26,8 +26,6 @@ define(['jquery', 'underscore', 'text!partials/settings.html'], function($, _, t
$scope.layout.settings = false;
$scope.showAdvancedSettings = true;
- $scope.showTakePicture = false;
- $scope.showTakePictureReady = true;
$scope.rememberSettings = true;
$scope.desktopNotify = desktopNotify;
$scope.mediaSources = mediaSources;
@@ -46,8 +44,6 @@ define(['jquery', 'underscore', 'text!partials/settings.html'], function($, _, t
});
});
- var localStream = null;
-
// Make sure to save settings when they are open and the page is reloaded.
$(window).on("unload", function() {
if ($scope.layout.settings) {
@@ -77,65 +73,6 @@ define(['jquery', 'underscore', 'text!partials/settings.html'], function($, _, t
safeApply($scope);
});
};
- $scope.takePicture = function(element, stop) {
- if (stop) {
- $scope.showTakePicture = false;
- if (localStream) {
- localStream.stop();
- localStream = null;
- }
- } else {
- var video = $(element).parent().find("video").get(0);
- if (!$scope.showTakePicture) {
- $scope.showTakePictureReady = false;
- var videoConstraints = true;
- if ($scope.user.settings.cameraId) {
- videoConstraints = {
- optional: [{
- sourceId: $scope.user.settings.cameraId
- }]
- }
- }
- getUserMedia({
- video: videoConstraints
- }, function(stream) {
- if ($scope.showTakePictureReady) {
- stream.stop()
- return;
- }
- $scope.showTakePicture = true;
- localStream = stream;
- $scope.showTakePictureReady = true;
- attachMediaStream(video, stream);
- safeApply($scope);
- }, function(error) {
- console.error('Failed to get access to local media. Error code was ' + error.code);
- $scope.showTakePictureReady = true;
- safeApply($scope);
- });
- return;
- } else {
- var canvas = $(element).parent().find("canvas").get(0);
- var videoWidth = video.videoWidth;
- var videoHeight = video.videoHeight;
- var aspectRatio = videoWidth / videoHeight;
- if (!aspectRatio) {
- // NOTE(longsleep): In Firefox the video size becomes available at sound point later - crap!
- console.warn("Unable to compute aspectRatio", aspectRatio);
- aspectRatio = 1.3333333333333333;
- }
- var x = (46 * aspectRatio - 46) / -2
- canvas.getContext("2d").drawImage(video, x, 0, 46 * aspectRatio, 46);
- $scope.user.buddyPicture = canvas.toDataURL("image/jpeg");
- console.info("Image size", $scope.user.buddyPicture.length);
- localStream.stop();
- localStream = null;
- $scope.showTakePictureReady = true;
- $scope.showTakePicture = false;
- safeApply($scope);
- }
- }
- };
$scope.registerUserid = function(btn) {
@@ -228,7 +165,7 @@ define(['jquery', 'underscore', 'text!partials/settings.html'], function($, _, t
template: template,
controller: controller,
link: link
- }
+ };
}];
diff --git a/static/partials/buddypicture.html b/static/partials/buddypicture.html
new file mode 100644
index 00000000..fde0b54f
--- /dev/null
+++ b/static/partials/buddypicture.html
@@ -0,0 +1,20 @@
+
diff --git a/static/partials/settings.html b/static/partials/settings.html
index f4d011bb..8a53772d 100644
--- a/static/partials/settings.html
+++ b/static/partials/settings.html
@@ -5,17 +5,10 @@