Browse Source

Breakout picture functionality into own directive. Update functions. Create corresponding styles page.

pull/40/head
Evan Theurer 11 years ago
parent
commit
7305d0a9ea
  1. 45
      src/styles/components/_buddypicture.scss
  2. 18
      src/styles/components/_settings.scss
  3. 1
      src/styles/main.scss
  4. 151
      static/js/directives/buddypicture.js
  5. 4
      static/js/directives/directives.js
  6. 99
      static/js/directives/settings.js
  7. 20
      static/partials/buddypicture.html
  8. 23
      static/partials/settings.html

45
src/styles/components/_buddypicture.scss

@ -0,0 +1,45 @@
/*
* 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;
}
.showTakePicture {
position: relative;
.btn {
margin: 5px 0px;
}
}
.btn-takePicture {
position: absolute;
right: 90px;
top: 110px;
}
.countdownPicture {
color: $componentbg;
font-size: 45px;
left: 95px;
position: absolute;
top: 55px;
}
}

18
src/styles/components/_settings.scss

@ -71,24 +71,6 @@
right: 10px; right: 10px;
top: 10px; top: 10px;
} }
.showTakePicture {
position: relative;
.btn {
margin: 5px 0px;
}
}
.btn-takePicture {
position: absolute;
top: 110px;
right: 90px;
}
.countdownToTakePicture {
font-size: 45px;
color: $componentbg;
position: absolute;
top: 55px;
left: 95px;
}
.form-horizontal { .form-horizontal {
.controls { .controls {
@include breakpt($breakpoint-settings-medium, max-width, only screen) { @include breakpt($breakpoint-settings-medium, max-width, only screen) {

1
src/styles/main.scss

@ -35,6 +35,7 @@
@import "components/rightslide"; @import "components/rightslide";
@import "components/bar"; @import "components/bar";
@import "components/buddylist"; @import "components/buddylist";
@import "components/buddypicture";
@import "components/settings"; @import "components/settings";
@import "components/chat"; @import "components/chat";
@import "components/usability"; @import "components/usability";

151
static/js/directives/buddypicture.js

@ -0,0 +1,151 @@
/*
* 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', function($scope, safeApply, $timeout) {
$scope.showTakePicture = false;
$scope.showTakePictureReady = true;
$scope.previewPicture = false;
$scope.countingDown = false;
$scope.video = null;
$scope.canvas = 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 makePicture = function(cntFrom, delayTotal) {
takePictureCountDown(cntFrom, delayTotal);
$timeout(function() {
$scope.previewPicture = true;
$scope.video.pause();
}, delayTotal);
};
$scope.initPicture = function() {
$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($scope.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);
});
};
$scope.cancelPicture = function() {
$scope.showTakePicture = false;
$scope.previewPicture = false;
if (localStream) {
localStream.stop();
localStream = null;
}
};
$scope.retakePicture = function() {
$scope.video.play();
$scope.previewPicture = false;
makePicture(countDownFrom, delayToTakePicture);
};
$scope.takePicture = function() {
makePicture(countDownFrom, delayToTakePicture);
};
$scope.setAsProfilePicture = 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;
}
var x = (46 * aspectRatio - 46) / -2;
$scope.canvas.getContext("2d").drawImage($scope.video, x, 0, 46 * aspectRatio, 46);
$scope.user.buddyPicture = $scope.canvas.toDataURL("image/jpeg");
console.info("Image size", $scope.user.buddyPicture.length);
localStream.stop();
localStream = null;
$scope.showTakePictureReady = true;
$scope.showTakePicture = false;
$scope.previewPicture = false;
safeApply($scope);
};
}];
var link = function($scope, $element) {
$scope.video = $element.find("video").get(0);
$scope.canvas = $element.find("canvas").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([
'directives/onescape', 'directives/onescape',
'directives/statusmessage', 'directives/statusmessage',
'directives/buddylist', 'directives/buddylist',
'directives/buddypicture',
'directives/settings', 'directives/settings',
'directives/chat', 'directives/chat',
'directives/audiovideo', 'directives/audiovideo',
@ -34,13 +35,14 @@ define([
'directives/screenshare', 'directives/screenshare',
'directives/roombar', 'directives/roombar',
'directives/socialshare', '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 = { var directives = {
onEnter: onEnter, onEnter: onEnter,
onEscape: onEscape, onEscape: onEscape,
statusMessage: statusMessage, statusMessage: statusMessage,
buddyList: buddyList, buddyList: buddyList,
buddyPicture: buddyPicture,
settings: settings, settings: settings,
chat: chat, chat: chat,
audioVideo: audioVideo, audioVideo: audioVideo,

99
static/js/directives/settings.js

@ -22,13 +22,10 @@ define(['jquery', 'underscore', 'text!partials/settings.html'], function($, _, t
return ["$compile", "mediaStream", function($compile, mediaStream) { return ["$compile", "mediaStream", function($compile, mediaStream) {
var controller = ['$scope', 'desktopNotify', 'mediaSources', 'safeApply', 'availableLanguages', 'translation', '$timeout', function($scope, desktopNotify, mediaSources, safeApply, availableLanguages, translation, $timeout) { var controller = ['$scope', 'desktopNotify', 'mediaSources', 'safeApply', 'availableLanguages', 'translation', function($scope, desktopNotify, mediaSources, safeApply, availableLanguages, translation) {
$scope.layout.settings = false; $scope.layout.settings = false;
$scope.showAdvancedSettings = true; $scope.showAdvancedSettings = true;
$scope.showTakePicture = false;
$scope.showTakePictureReady = true;
$scope.previewPicture = false;
$scope.rememberSettings = true; $scope.rememberSettings = true;
$scope.desktopNotify = desktopNotify; $scope.desktopNotify = desktopNotify;
$scope.mediaSources = mediaSources; $scope.mediaSources = mediaSources;
@ -47,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. // Make sure to save settings when they are open and the page is reloaded.
$(window).on("unload", function() { $(window).on("unload", function() {
if ($scope.layout.settings) { if ($scope.layout.settings) {
@ -78,98 +73,6 @@ define(['jquery', 'underscore', 'text!partials/settings.html'], function($, _, t
safeApply($scope); safeApply($scope);
}); });
}; };
$scope.takePicture = function(element, take, retake, stop) {
var delayToTakePicture = 3000;
var countDownFrom = 3;
// Counts down from start to 1
var takePictureCountDown = function(start, delayTotal) {
$scope.countdown = {};
$scope.countdown.num = start;
var decrementNum = function(num) {
$timeout(function() {
$scope.countdown.num--;
}, delayTotal/start*num);
}
for(var i = 1; i <= start; i++) {
decrementNum(i);
}
};
if (stop) {
$scope.showTakePicture = false;
$scope.previewPicture = false;
if (localStream) {
localStream.stop();
localStream = null;
}
return;
}
var video = $(element).parent().parent().find("video").get(0);
var makePicture = function() {
takePictureCountDown(countDownFrom, delayToTakePicture);
$timeout(function() {
$scope.previewPicture = true;
video.pause();
}, delayToTakePicture);
};
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 if (take) {
makePicture();
} else if (retake) {
video.play();
$scope.previewPicture = false;
makePicture();
} else {
var canvas = $(element).parent().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;
$scope.previewPicture = false;
safeApply($scope);
}
};
$scope.registerUserid = function(btn) { $scope.registerUserid = function(btn) {

20
static/partials/buddypicture.html

@ -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="countdownPicture" ng-show="countdown.num">
<span ng-bind="countdown.num"></span>
</div>
<video autoplay="autoplay" width="200"></video>
<canvas style="display:none" width="46" height="46"></canvas>
<a class="btn btn-xs btn-success btn-takePicture" ng-disabled="countingDown" ng-show="!previewPicture" ng-click="takePicture()"> {{_('Take')}}</a>
<a class="btn btn-xs btn-success btn-takePicture" 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" ng-click="setAsProfilePicture()"> {{_('Set as Profile Picture')}}</a>
</div>
</div>
<a class="btn btn-small btn-success" ng-show="!showTakePicture" ng-disabled="!showTakePictureReady" ng-click="initPicture()"> {{_('Take picture')}}</a>
<span ng-show="!showTakePictureReady">
<i class="fa fa-spinner fa-spin"></i> {{_('Waiting for camera')}}
</span>
</div>

23
static/partials/settings.html

@ -8,28 +8,7 @@
<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"> <div class="col-xs-8">
<label> <label>
<div style="margin-bottom:5px"> <buddy-picture/>
<img ng-show="user.buddyPicture" ng-src="{{user.buddyPicture}}" alt="" />
</div>
<div class="collapse showTakePicture" collapse="!showTakePicture">
<div class="countdownToTakePicture" ng-show="countdown.num">
<span ng-bind="countdown.num"></span>
</div>
<video autoplay="autoplay" width="200"></video>
<canvas style="display:none" width="46" height="46"></canvas>
<a class="btn btn-xs btn-success btn-takePicture" ng-show="!previewPicture" ng-click="takePicture($event.target, true)"> {{_('Take')}}</a>
<a class="btn btn-xs btn-success btn-takePicture" ng-show="previewPicture" ng-click="takePicture($event.target, false, true)"> {{_('Retake')}}</a>
<div>
<a class="btn btn-small btn-default" ng-click="takePicture($event.target, false, false, true)"> {{_('Cancel')}}</a>
<a class="btn btn-small btn-primary" ng-disabled="!previewPicture" ng-click="takePicture($event.target)"> {{_('Set as Profile Picture')}}</a>
</div>
</div>
<div>
<a class="btn btn-small btn-success" ng-show="!showTakePicture" 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>
</div>
</label> </label>
</div> </div>
</div> </div>

Loading…
Cancel
Save