Browse Source

Merge pull request #40 from theurere/take-picture

Take buddy picture - new flow
pull/49/head
Simon Eisenmann 12 years ago
parent
commit
1bf456f9c5
  1. 1
      build/build.js
  2. 14
      doc/plugin-test-authorize.js
  3. 56
      src/styles/components/_buddypicture.scss
  4. 1
      src/styles/main.scss
  5. 172
      static/js/directives/buddypicture.js
  6. 4
      static/js/directives/directives.js
  7. 65
      static/js/directives/settings.js
  8. 20
      static/partials/buddypicture.html
  9. 11
      static/partials/settings.html

1
build/build.js

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*jshint -W030 */
({
baseUrl: '../static/js',
mainConfigFile: '../static/js/main.js',

14
doc/plugin-test-authorize.js

@ -50,14 +50,14 @@ define(['angular', 'sjcl'], function(angular, sjcl) { @@ -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) { @@ -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) { @@ -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) { @@ -103,6 +103,6 @@ define(['angular', 'sjcl'], function(angular, sjcl) {
}
}
};
});
});

56
src/styles/components/_buddypicture.scss

@ -0,0 +1,56 @@ @@ -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 <http://www.gnu.org/licenses/>.
*
*/
.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;
}
}

1
src/styles/main.scss

@ -35,6 +35,7 @@ @@ -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";

172
static/js/directives/buddypicture.js

@ -0,0 +1,172 @@ @@ -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 <http://www.gnu.org/licenses/>.
*
*/
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
};
}];
});

4
static/js/directives/directives.js

@ -25,6 +25,7 @@ define([ @@ -25,6 +25,7 @@ define([
'directives/onescape',
'directives/statusmessage',
'directives/buddylist',
'directives/buddypicture',
'directives/settings',
'directives/chat',
'directives/audiovideo',
@ -34,13 +35,14 @@ define([ @@ -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,

65
static/js/directives/settings.js

@ -26,8 +26,6 @@ define(['jquery', 'underscore', 'text!partials/settings.html'], function($, _, t @@ -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 @@ -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 @@ -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 @@ -228,7 +165,7 @@ define(['jquery', 'underscore', 'text!partials/settings.html'], function($, _, t
template: template,
controller: controller,
link: link
}
};
}];

20
static/partials/buddypicture.html

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
<div class="buddyPicture">
<img class="picture" ng-show="user.buddyPicture" ng-src="{{user.buddyPicture}}" alt="" />
<div class="collapse showTakePicture" collapse="!showTakePicture">
<div class="videoPicture">
<div class="countdownPicture" ng-show="countdown.num" ng-bind="countdown.num"></div>
<video ng-show="!previewPicture" autoplay="autoplay" width="200"></video>
<canvas id="pic" style="display:none" width="46" height="46"></canvas>
<canvas id="prev" style="display:none" width="200"></canvas>
<img class="preview" ng-class="{previewPicture: previewPicture}" ng-show="previewPicture" ng-src="{{preview}}" width="200" alt="" />
<a class="btn btn-xs btn-success btn-takePicture" ng-disabled="countingDown || waitingForPermission" ng-show="!previewPicture" ng-click="takePicture()"> {{_('Take')}}</a>
<a class="btn btn-xs btn-success btn-retakePicture" ng-disabled="waitingForPermission" ng-show="previewPicture" ng-click="retakePicture()"> {{_('Retake')}}</a>
</div>
<a class="btn btn-small btn-default" ng-click="cancelPicture()"> {{_('Cancel')}}</a>
<a class="btn btn-small btn-primary" ng-disabled="!previewPicture || waitingForPermission" ng-click="setAsProfilePicture()"> {{_('Set as Profile Picture')}}</a>
</div>
<a class="btn btn-small btn-success" ng-show="!showTakePicture" ng-disabled="waitingForPermission" ng-click="initPicture()"> {{_('Take picture')}}</a>
<span ng-show="waitingForPermission">
<i class="fa fa-spinner fa-spin"></i> {{_('Waiting for camera')}}
</span>
</div>

11
static/partials/settings.html

@ -5,17 +5,10 @@ @@ -5,17 +5,10 @@
<legend>{{_('Settings')}}</legend>
<div class="form-group">
<label class="col-xs-4 control-label">{{_('Your picture')}}</label>
<label class="col-xs-4 control-label">{{_('Your picture')}}</label>
<div class="col-xs-8">
<label>
<div style="margin-bottom:5px">
<img ng-show="user.buddyPicture" ng-src="{{user.buddyPicture}}" alt="" />
</div>
<div class="collapse" collapse="!showTakePicture">
<video autoplay="autoplay" width="200"></video>
<canvas style="display:none" width="46" height="46"></canvas>
</div>
<a class="btn btn-small btn-success" ng-disabled="!showTakePictureReady" ng-click="takePicture($event.target)"> {{_('Take picture')}}</a> <span ng-show="!showTakePictureReady"><i class="fa fa-spinner fa-spin"></i> {{_('Waiting for camera')}}</span><a class="btn btn-small btn-default" ng-show="showTakePicture" ng-click="takePicture($event.target, true)"> {{_('Cancel')}}</a>
<buddy-picture/>
</label>
</div>
</div>

Loading…
Cancel
Save