Merge pull request #185 from maraoz/add/video

Adds video for copayers
This commit is contained in:
Matias Alejo Garcia 2014-04-24 22:04:19 -03:00
commit 3e8b1e33b9
8 changed files with 335 additions and 191 deletions

View file

@ -277,3 +277,18 @@ button.secondary:hover { background-color: #FFDF00 !important;}
border: 2px red solid; border: 2px red solid;
} }
.video-small {
width: 120px;
height: 120px;
margin: 20px;
display: inline;
float:left;
}
.online {
border: 10px solid green;
}
.offline {
border: 10px solid gray;
}

BIN
img/satoshi.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -205,21 +205,29 @@
<script type="text/ng-template" id="peer.html"> <script type="text/ng-template" id="peer.html">
<div class="row"> <div class="row">
<div class="large-12 columns p70l"> <div class="large-12 columns p70l">
<h3 class="panel-title">Online Copayers: {{$root.wallet.network.connectedCopayers().length}}</h3>
<p class="text-info" ng-show="$root.wallet.publicKeyRing.requiredCopayers >$root.wallet.network.connectedCopayers()"> <i class="fi-alert size-28"></i> <p class="text-info" ng-show="$root.wallet.publicKeyRing.requiredCopayers >$root.wallet.network.connectedCopayers()"> <i class="fi-alert size-28"></i>
</div>
</div>
<div class="row">
<div class="large-12 columns p70l">
{{$root.wallet.publicKeyRing.requiredCopayers}} copayers needed for signing transactions {{$root.wallet.publicKeyRing.requiredCopayers}} copayers needed for signing transactions
</div>
</div>
<ul class="no-bullet"> <div class="row">
<li class="panel" ng-repeat="copayer in $root.wallet.network.connectedCopayers()"> <div class="large-4 columns"
<span ng-if="copayer === $root.wallet.getMyCopayerId()"> You </span> ng-repeat="copayer in $root.wallet.getRegisteredPeerIds()">
{{copayer}} <video
<span> ng-class="($root.wallet.getOnlinePeerIDs().indexOf(copayer) != -1) ? 'online' : 'offline'"
<i class="fi-check size-16 panel-sign right p5h br100"></i> class="video-small"
</span> autoplay ng-show="$root.videoSrc[copayer]"
</li> ng-src="{{$root.getVideoURL(copayer)}}"
</ul> id="{{copayer + '-video'}}" muted="true"
title="{{copayer + (copayer == $root.wallet.network.peerId?' (You)':'')}}" ></video>
<img ng-show="!$root.videoSrc[copayer]"
ng-class="($root.wallet.getOnlinePeerIDs().indexOf(copayer) != -1) ? 'online' : 'offline'"
class="video-small"
src="/img/satoshi.gif"
title="{{copayer + (copayer == $root.wallet.network.peerId?' (You)':'')}}" />
</div> </div>
</div> </div>
</script> </script>
@ -511,6 +519,7 @@
<script src="js/directives.js"></script> <script src="js/directives.js"></script>
<script src="js/filters.js"></script> <script src="js/filters.js"></script>
<script src="js/services/socket.js"></script> <script src="js/services/socket.js"></script>
<script src="js/services/video.js"></script>
<script src="js/services/walletFactory.js"></script> <script src="js/services/walletFactory.js"></script>
<script src="js/services/controllerUtils.js"></script> <script src="js/services/controllerUtils.js"></script>

View file

@ -14,7 +14,8 @@ var copayApp = window.copayApp = angular.module('copay',[
'copay.socket', 'copay.socket',
'copay.controllerUtils', 'copay.controllerUtils',
'copay.setup', 'copay.setup',
'copay.directives' 'copay.directives',
'copay.video'
]); ]);
angular.module('copay.header', []); angular.module('copay.header', []);
@ -28,4 +29,5 @@ angular.module('copay.signin', []);
angular.module('copay.setup', []); angular.module('copay.setup', []);
angular.module('copay.socket', []); angular.module('copay.socket', []);
angular.module('copay.directives', []); angular.module('copay.directives', []);
angular.module('copay.video', []);

View file

@ -127,6 +127,7 @@ Wallet.prototype._handleNetworkChange = function(newCopayerId) {
if (newCopayerId) { if (newCopayerId) {
this.log('#### Setting new PEER:', newCopayerId); this.log('#### Setting new PEER:', newCopayerId);
this.sendWalletId(newCopayerId); this.sendWalletId(newCopayerId);
this.emit('peer', this.network.peerFromCopayer(newCopayerId));
} }
this.emit('refresh'); this.emit('refresh');
}; };
@ -176,7 +177,8 @@ Wallet.prototype.netStart = function() {
}; };
net.start(startOpts, function() { net.start(startOpts, function() {
self.emit('created'); self.emit('created', net.getPeer());
var registered = self.getRegisteredPeerIds();
for (var i = 0; i < self.publicKeyRing.registeredCopayers(); i++) { for (var i = 0; i < self.publicKeyRing.registeredCopayers(); i++) {
var otherId = self.getCopayerId(i); var otherId = self.getCopayerId(i);
if (otherId !== myId) { if (otherId !== myId) {
@ -191,6 +193,20 @@ Wallet.prototype.netStart = function() {
}); });
}; };
Wallet.prototype.getOnlinePeerIDs = function() {
return this.network.getOnlinePeerIDs();
};
Wallet.prototype.getRegisteredPeerIds = function() {
var ret = [];
for (var i = 0; i < this.publicKeyRing.registeredCopayers(); i++) {
var cid = this.getCopayerId(i)
var pid = this.network.peerFromCopayer(cid);
ret.push(pid);
}
return ret;
};
Wallet.prototype.store = function(isSync) { Wallet.prototype.store = function(isSync) {
this.log('[Wallet.js.135:store:]'); //TODO this.log('[Wallet.js.135:store:]'); //TODO
var wallet = this.toObj(); var wallet = this.toObj();
@ -198,8 +214,7 @@ Wallet.prototype.store = function(isSync) {
if (isSync) { if (isSync) {
this.log('Wallet stored.'); //TODO this.log('Wallet stored.'); //TODO
} } else {
else {
this.log('Wallet stored. REFRESH Emitted'); //TODO this.log('Wallet stored. REFRESH Emitted'); //TODO
this.emit('refresh'); this.emit('refresh');
} }
@ -482,14 +497,18 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) {
} }
if (!opts.remainderOut) { if (!opts.remainderOut) {
opts.remainderOut ={ address: this.generateAddress(true).toString() }; opts.remainderOut = {
address: this.generateAddress(true).toString()
};
} }
var b = new Builder(opts) var b = new Builder(opts)
.setUnspent(utxos) .setUnspent(utxos)
.setHashToScriptMap(pkr.getRedeemScriptMap()) .setHashToScriptMap(pkr.getRedeemScriptMap())
.setOutputs([{address: toAddress, amountSat: amountSat}]) .setOutputs([{
; address: toAddress,
amountSat: amountSat
}]);
var signRet; var signRet;
if (priv) { if (priv) {
@ -526,4 +545,8 @@ console.log('[Wallet.js.524] DISC'); //TODO
this.network.disconnect(); this.network.disconnect();
}; };
Wallet.prototype.getNetwork = function() {
return this.network;
};
module.exports = require('soop')(Wallet); module.exports = require('soop')(Wallet);

View file

@ -13,6 +13,7 @@ var Key = bitcore.Key;
* when an unknown data type arrives * when an unknown data type arrives
* *
* Provides * Provides
* send(toPeerIds, {data}, cb?)
* *
*/ */
@ -23,7 +24,9 @@ function Network(opts) {
this.apiKey = opts.apiKey || 'lwjd5qra8257b9'; this.apiKey = opts.apiKey || 'lwjd5qra8257b9';
this.debug = opts.debug || 3; this.debug = opts.debug || 3;
this.maxPeers = opts.maxPeers || 10; this.maxPeers = opts.maxPeers || 10;
this.opts = { key: opts.key }; this.opts = {
key: opts.key
};
this.connections = {}; this.connections = {};
this.copayerForPeer = {}; this.copayerForPeer = {};
@ -71,7 +74,6 @@ Network._arrayRemove = function(el, array) {
return array; return array;
}; };
Network.prototype.connectedCopayers = function() { Network.prototype.connectedCopayers = function() {
var ret =[]; var ret =[];
for(var i in this.connectedPeers){ for(var i in this.connectedPeers){
@ -187,8 +189,6 @@ Network.prototype._onData = function(data, isInbound, peerId) {
} }
}; };
Network.prototype._checkAnyPeer = function() { Network.prototype._checkAnyPeer = function() {
if (!this.connectedPeers.length) { if (!this.connectedPeers.length) {
console.log('EMIT openError: no more peers, not even you!'); console.log('EMIT openError: no more peers, not even you!');
@ -267,8 +267,7 @@ Network.prototype._setupPeerHandlers = function(openCallback) {
console.log('### CLOSING CONN FROM:' + dataConn.peer); console.log('### CLOSING CONN FROM:' + dataConn.peer);
dataConn.close(); dataConn.close();
}); });
} } else {
else {
self._setupConnectionHandlers(dataConn, true); self._setupConnectionHandlers(dataConn, true);
} }
}); });
@ -348,6 +347,13 @@ Network.prototype._sign = function(payload, copayerId) {
).toString('hex'); ).toString('hex');
} }
return ret; return ret;
}
Network.prototype.getOnlinePeerIDs = function() {
return this.connectedPeers;
};
Network.prototype.getPeer = function() {
return this.peer;
}; };
Network.prototype._sendToOne = function(copayerId, payload, cb) { Network.prototype._sendToOne = function(copayerId, payload, cb) {

View file

@ -1,7 +1,16 @@
'use strict'; 'use strict';
angular.module('copay.controllerUtils').factory('controllerUtils', function ($rootScope, $location, Socket) { angular.module('copay.controllerUtils')
.factory('controllerUtils', function($rootScope, $sce, $location, Socket, video) {
var root = {}; var root = {};
$rootScope.videoSrc = {};
$rootScope.getVideoURL = function(copayer) {
var encoded = $rootScope.videoSrc[copayer];
if (!encoded) return;
var url = decodeURI(encoded);
var trusted = $sce.trustAsResourceUrl(url);
return trusted;
};
root.logout = function() { root.logout = function() {
console.log('### DELETING WALLET'); //TODO console.log('### DELETING WALLET'); //TODO
@ -13,7 +22,11 @@ angular.module('copay.controllerUtils').factory('controllerUtils', function ($ro
root.onError = function(scope) { root.onError = function(scope) {
if (scope) scope.loading = false; if (scope) scope.loading = false;
$rootScope.flashMessage = {type:'error', message: 'Could not connect to peer'}; $rootScope.flashMessage = {
type: 'error',
message: 'Could not connect to peer: ' +
scope
};
root.logout(); root.logout();
} }
@ -21,24 +34,34 @@ angular.module('copay.controllerUtils').factory('controllerUtils', function ($ro
root.onError(scope); root.onError(scope);
$rootScope.$digest(); $rootScope.$digest();
} }
root.setupUxHandlers = function(w) { root.setupUxHandlers = function(w) {
var handlePeerVideo = function(err, peerID, url) {
if (err) {
return;
}
$rootScope.videoSrc[peerID] = encodeURI(url);
$rootScope.$apply();
};
w.on('badMessage', function(peerId) { w.on('badMessage', function(peerId) {
$rootScope.flashMessage = {type:'error', message: 'Received wrong message from peer id:' + peerId}; $rootScope.flashMessage = {
type: 'error',
message: 'Received wrong message from peer id:' + peerId
};
}); });
w.on('created', function(myPeerID) {
w.on('created', function() { video.setOwnPeer(myPeerID, w, handlePeerVideo);
$location.path('peer'); $location.path('peer');
$rootScope.wallet = w; $rootScope.wallet = w;
root.updateBalance(); root.updateBalance();
}); });
w.on('refresh', function() { w.on('refresh', function() {
console.log('[controllerUtils.js] Refreshing'); //TODO console.log('[controllerUtils.js] Refreshing'); //TODO
root.updateBalance(); root.updateBalance();
}); });
w.on('openError', root.onErrorDigest); w.on('openError', root.onErrorDigest);
w.on('peer', function(peerID) {
video.callPeer(peerID, handlePeerVideo);
});
w.on('close', root.onErrorDigest); w.on('close', root.onErrorDigest);
w.netStart(); w.netStart();
}; };
@ -46,7 +69,6 @@ angular.module('copay.controllerUtils').factory('controllerUtils', function ($ro
root.updateBalance = function() { root.updateBalance = function() {
var w = $rootScope.wallet; var w = $rootScope.wallet;
if (!w) return; if (!w) return;
w.getBalance(false, function(balance, balanceByAddr) { w.getBalance(false, function(balance, balanceByAddr) {
$rootScope.totalBalance = balance; $rootScope.totalBalance = balance;
$rootScope.balanceByAddr = balanceByAddr; $rootScope.balanceByAddr = balanceByAddr;
@ -77,4 +99,3 @@ console.log('[controllerUtils.js.64]'); //TODO
return root; return root;
}); });

68
js/services/video.js Normal file
View file

@ -0,0 +1,68 @@
'use strict';
var Video = function() {
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;
this.mediaConnections = {};
};
Video.prototype.setOwnPeer = function(peer, wallet, cb) {
var self = this;
navigator.getUserMedia({
audio: true,
video: true
}, function(stream) {
// This is called when user accepts using webcam
self.localStream = stream;
var online = wallet.getOnlinePeerIDs();
for (var i = 0; i < online.length; i++) {
var o = online[i];
var mc = self.mediaConnections[o];
if (o !== peer.id) {
self.callPeer(o, cb);
}
}
cb(null, peer.id, URL.createObjectURL(stream));
}, function() {
cb(new Error('Failed to access the webcam and microphone.'));
});
// Receiving a call
peer.on('call', function(mediaConnection) {
if (self.localStream) {
mediaConnection.answer(self.localStream);
} else {
mediaConnection.answer();
}
self.mediaConnections[mediaConnection.peer] = mediaConnection;
self._addCall(mediaConnection, cb);
});
this.peer = peer;
};
Video.prototype.callPeer = function(peerID, cb) {
if (this.localStream) {
var mediaConnection = this.peer.call(peerID, this.localStream);
this._addCall(mediaConnection, cb);
}
};
Video.prototype._addCall = function(mediaConnection, cb) {
var peerID = mediaConnection.peer;
// Wait for stream on the call, then set peer video display
mediaConnection.on('stream', function(stream) {
cb(null, peerID, URL.createObjectURL(stream));
});
mediaConnection.on('close', function() {
});
mediaConnection.on('error', function() {
});
}
angular.module('copay.video').value('video', new Video());