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;
}
.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">
<div class="row">
<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>
</div>
</div>
<div class="row">
<div class="large-12 columns p70l">
{{$root.wallet.publicKeyRing.requiredCopayers}} copayers needed for signing transactions
<ul class="no-bullet">
<li class="panel" ng-repeat="copayer in $root.wallet.network.connectedCopayers()">
<span ng-if="copayer === $root.wallet.getMyCopayerId()"> You </span>
{{copayer}}
<span>
<i class="fi-check size-16 panel-sign right p5h br100"></i>
</span>
</li>
</ul>
</div>
</div>
<div class="row">
<div class="large-4 columns"
ng-repeat="copayer in $root.wallet.getRegisteredPeerIds()">
<video
ng-class="($root.wallet.getOnlinePeerIDs().indexOf(copayer) != -1) ? 'online' : 'offline'"
class="video-small"
autoplay ng-show="$root.videoSrc[copayer]"
ng-src="{{$root.getVideoURL(copayer)}}"
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>
</script>
@ -511,6 +519,7 @@
<script src="js/directives.js"></script>
<script src="js/filters.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/controllerUtils.js"></script>

View file

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

View file

@ -1,14 +1,14 @@
'use strict';
var imports = require('soop').imports();
var imports = require('soop').imports();
var bitcore = require('bitcore');
var coinUtil = bitcore.util;
var bitcore = require('bitcore');
var coinUtil = bitcore.util;
var buffertools = bitcore.buffertools;
var Builder = bitcore.TransactionBuilder;
var http = require('http');
var EventEmitter= imports.EventEmitter || require('events').EventEmitter;
var copay = copay || require('../../../copay');
var Builder = bitcore.TransactionBuilder;
var http = require('http');
var EventEmitter = imports.EventEmitter || require('events').EventEmitter;
var copay = copay || require('../../../copay');
function Wallet(opts) {
var self = this;
@ -17,12 +17,12 @@ function Wallet(opts) {
['storage', 'network', 'blockchain',
'requiredCopayers', 'totalCopayers', 'spendUnconfirmed',
'publicKeyRing', 'txProposals', 'privateKey'
].forEach( function(k){
].forEach(function(k) {
if (typeof opts[k] === 'undefined') throw new Error('missing key:' + k);
self[k] = opts[k];
});
this.log('creating '+opts.requiredCopayers+' of '+opts.totalCopayers+' wallet');
this.log('creating ' + opts.requiredCopayers + ' of ' + opts.totalCopayers + ' wallet');
this.id = opts.id || Wallet.getRandomId();
this.name = opts.name;
@ -32,11 +32,11 @@ function Wallet(opts) {
}
Wallet.parent=EventEmitter;
Wallet.prototype.log = function(){
Wallet.parent = EventEmitter;
Wallet.prototype.log = function() {
if (!this.verbose) return;
if (console)
console.log.apply(console, arguments);
console.log.apply(console, arguments);
};
Wallet.getRandomId = function() {
@ -45,14 +45,14 @@ Wallet.getRandomId = function() {
};
Wallet.prototype._handlePublicKeyRing = function(senderId, data, isInbound) {
this.log('RECV PUBLICKEYRING:',data);
this.log('RECV PUBLICKEYRING:', data);
var shouldSend = false;
var recipients, pkr = this.publicKeyRing;
var inPKR = copay.PublicKeyRing.fromObj(data.publicKeyRing);
var hasChanged = pkr.merge(inPKR, true);
if (hasChanged) {
if (hasChanged) {
this.log('### BROADCASTING PKR');
recipients = null;
shouldSend = true;
@ -72,15 +72,15 @@ Wallet.prototype._handlePublicKeyRing = function(senderId, data, isInbound) {
Wallet.prototype._handleTxProposals = function(senderId, data, isInbound) {
this.log('RECV TXPROPOSAL:',data); //TODO
this.log('RECV TXPROPOSAL:', data); //TODO
var shouldSend = false;
var recipients;
var inTxp = copay.TxProposals.fromObj(data.txProposals);
var mergeInfo = this.txProposals.merge(inTxp, true);
var addSeen = this.addSeenToTxProposals();
if (mergeInfo.hasChanged || addSeen) {
this.log('### BROADCASTING txProposals. ' );
if (mergeInfo.hasChanged || addSeen) {
this.log('### BROADCASTING txProposals. ');
recipients = null;
shouldSend = true;
}
@ -91,21 +91,21 @@ Wallet.prototype._handleTxProposals = function(senderId, data, isInbound) {
// shouldSend = true;
// }
if (shouldSend)
if (shouldSend)
this.sendTxProposals(recipients);
this.store();
};
Wallet.prototype._handleData = function(senderId, data, isInbound) {
// TODO check message signature
if (this.id !== data.walletId) {
this.emit('badMessage',senderId);
this.emit('badMessage', senderId);
this.log('badMessage FROM:', senderId); //TODO
return;
}
this.log('[Wallet.js.98]' , data.type); //TODO
switch(data.type) {
this.log('[Wallet.js.98]', data.type); //TODO
switch (data.type) {
// This handler is repeaded on WalletFactory (#join). TODO
case 'walletId':
this.sendWalletReady(senderId);
@ -116,10 +116,10 @@ Wallet.prototype._handleData = function(senderId, data, isInbound) {
break;
case 'publicKeyRing':
this._handlePublicKeyRing(senderId, data, isInbound);
break;
break;
case 'txProposals':
this._handleTxProposals(senderId, data, isInbound);
break;
break;
}
};
@ -127,12 +127,13 @@ Wallet.prototype._handleNetworkChange = function(newCopayerId) {
if (newCopayerId) {
this.log('#### Setting new PEER:', newCopayerId);
this.sendWalletId(newCopayerId);
this.emit('peer', this.network.peerFromCopayer(newCopayerId));
}
this.emit('refresh');
};
Wallet.prototype._optsToObj = function () {
Wallet.prototype._optsToObj = function() {
var obj = {
id: this.id,
spendUnconfirmed: this.spendUnconfirmed,
@ -158,9 +159,9 @@ Wallet.prototype.netStart = function() {
var self = this;
var net = this.network;
net.removeAllListeners();
net.on('networkChange', self._handleNetworkChange.bind(self) );
net.on('data', self._handleData.bind(self) );
net.on('open', function() {}); // TODO
net.on('networkChange', self._handleNetworkChange.bind(self));
net.on('data', self._handleData.bind(self));
net.on('open', function() {}); // TODO
net.on('openError', function() {
self.log('[Wallet.js.132:openError:] GOT openError'); //TODO
self.emit('openError');
@ -170,27 +171,42 @@ Wallet.prototype.netStart = function() {
});
var myId = self.getMyCopayerId();
var startOpts = {
var startOpts = {
copayerId: myId,
signingKeyHex: self.privateKey.getSigningKey(),
};
net.start(startOpts, function() {
self.emit('created');
for (var i=0; i<self.publicKeyRing.registeredCopayers(); i++) {
self.emit('created', net.getPeer());
var registered = self.getRegisteredPeerIds();
for (var i = 0; i < self.publicKeyRing.registeredCopayers(); i++) {
var otherId = self.getCopayerId(i);
if (otherId !== myId) {
net.connectTo(otherId);
}
if (self.firstCopayerId){
self.sendWalletReady(self.firstCopayerId);
self.firstCopayerId = null;
}
self.emit('refresh');
if (self.firstCopayerId) {
self.sendWalletReady(self.firstCopayerId);
self.firstCopayerId = null;
}
self.emit('refresh');
}
});
};
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) {
this.log('[Wallet.js.135:store:]'); //TODO
var wallet = this.toObj();
@ -198,8 +214,7 @@ Wallet.prototype.store = function(isSync) {
if (isSync) {
this.log('Wallet stored.'); //TODO
}
else {
} else {
this.log('Wallet stored. REFRESH Emitted'); //TODO
this.emit('refresh');
}
@ -230,10 +245,10 @@ Wallet.fromObj = function(wallet) {
};
Wallet.prototype.sendTxProposals = function(recipients) {
this.log('### SENDING txProposals TO:', recipients||'All', this.txProposals);
this.log('### SENDING txProposals TO:', recipients || 'All', this.txProposals);
this.network.send( recipients, {
type: 'txProposals',
this.network.send(recipients, {
type: 'txProposals',
txProposals: this.txProposals.toObj(),
walletId: this.id,
});
@ -243,18 +258,18 @@ Wallet.prototype.sendTxProposals = function(recipients) {
Wallet.prototype.sendWalletReady = function(recipients) {
this.log('### SENDING WalletReady TO:', recipients);
this.network.send( recipients, {
type: 'walletReady',
this.network.send(recipients, {
type: 'walletReady',
walletId: this.id,
});
this.emit('walletReady');
};
Wallet.prototype.sendWalletId = function(recipients) {
this.log('### SENDING walletId TO:', recipients||'All', this.walletId);
this.log('### SENDING walletId TO:', recipients || 'All', this.walletId);
this.network.send(recipients, {
type: 'walletId',
this.network.send(recipients, {
type: 'walletId',
walletId: this.id,
opts: this._optsToObj()
});
@ -262,10 +277,10 @@ Wallet.prototype.sendWalletId = function(recipients) {
Wallet.prototype.sendPublicKeyRing = function(recipients) {
this.log('### SENDING publicKeyRing TO:', recipients||'All', this.publicKeyRing.toObj());
this.log('### SENDING publicKeyRing TO:', recipients || 'All', this.publicKeyRing.toObj());
this.network.send(recipients, {
type: 'publicKeyRing',
this.network.send(recipients, {
type: 'publicKeyRing',
publicKeyRing: this.publicKeyRing.toObj(),
walletId: this.id,
});
@ -283,12 +298,12 @@ Wallet.prototype.generateAddress = function(isChange) {
Wallet.prototype.getTxProposals = function() {
var ret = [];
for(var k in this.txProposals.txps) {
for (var k in this.txProposals.txps) {
var i = this.txProposals.getTxProposal(k);
i.signedByUs = i.signedBy[this.getMyCopayerId()]?true:false;
i.rejectedByUs = i.rejectedBy[this.getMyCopayerId()]?true:false;
if (this.totalCopayers-i.rejectCount < this.requiredCopayers)
i.finallyRejected=true;
i.signedByUs = i.signedBy[this.getMyCopayerId()] ? true : false;
i.rejectedByUs = i.rejectedBy[this.getMyCopayerId()] ? true : false;
if (this.totalCopayers - i.rejectCount < this.requiredCopayers)
i.finallyRejected = true;
ret.push(i);
}
@ -297,7 +312,7 @@ Wallet.prototype.getTxProposals = function() {
Wallet.prototype.reject = function(ntxid) {
var myId=this.getMyCopayerId();
var myId = this.getMyCopayerId();
var txp = this.txProposals.txps[ntxid];
if (!txp || txp.rejectedBy[myId] || txp.signedBy[myId]) return;
@ -309,7 +324,7 @@ Wallet.prototype.reject = function(ntxid) {
Wallet.prototype.sign = function(ntxid) {
var self = this;
var myId=this.getMyCopayerId();
var myId = this.getMyCopayerId();
var txp = self.txProposals.txps[ntxid];
if (!txp || txp.rejectedBy[myId] || txp.signedBy[myId]) return;
@ -321,7 +336,7 @@ Wallet.prototype.sign = function(ntxid) {
b.sign(keys);
var ret = false;
if (b.signaturesAdded > before) {
if (b.signaturesAdded > before) {
txp.signedBy[myId] = Date.now();
this.sendTxProposals();
this.store(true);
@ -339,12 +354,12 @@ Wallet.prototype.sendTx = function(ntxid, cb) {
this.log('[Wallet.js.231] BROADCASTING TX!!!'); //TODO
var txHex = tx.serialize().toString('hex');
this.log('[Wallet.js.261:txHex:]',txHex); //TODO
this.log('[Wallet.js.261:txHex:]', txHex); //TODO
var self = this;
this.blockchain.sendRawTransaction(txHex, function(txid) {
self.log('BITCOND txid:',txid); //TODO
self.log('BITCOND txid:', txid); //TODO
if (txid) {
self.txProposals.setSent(ntxid, txid);
}
@ -355,10 +370,10 @@ Wallet.prototype.sendTx = function(ntxid, cb) {
};
Wallet.prototype.addSeenToTxProposals = function() {
var ret=false;
var myId=this.getMyCopayerId();
var ret = false;
var myId = this.getMyCopayerId();
for(var k in this.txProposals.txps) {
for (var k in this.txProposals.txps) {
var txp = this.txProposals.txps[k];
if (!txp.seenBy[myId]) {
@ -386,9 +401,9 @@ Wallet.prototype.addressIsOwn = function(addrStr) {
var l = addrList.length;
var ret = false;
for(var i=0; i<l; i++) {
for (var i = 0; i < l; i++) {
if (addrList[i] === addrStr) {
ret = true;
ret = true;
break;
}
}
@ -402,23 +417,23 @@ Wallet.prototype.getBalance = function(safe, cb) {
var COIN = bitcore.util.COIN;
var addresses = this.getAddressesStr(true);
if (!addresses.length) return cb(0,[]);
if (!addresses.length) return cb(0, []);
// Prefill balanceByAddr with main address
addresses.forEach(function(a){
balanceByAddr[a]=0;
isMain[a]=1;
addresses.forEach(function(a) {
balanceByAddr[a] = 0;
isMain[a] = 1;
});
var f = safe ? this.getSafeUnspent.bind(this):this.getUnspent.bind(this);
var f = safe ? this.getSafeUnspent.bind(this) : this.getUnspent.bind(this);
f(function(utxos) {
for(var i=0;i<utxos.length; i++) {
var u= utxos[i];
for (var i = 0; i < utxos.length; i++) {
var u = utxos[i];
var amt = u.amount * COIN;
balance = balance + amt;
balanceByAddr[u.address] = (balanceByAddr[u.address]||0) + amt;
balanceByAddr[u.address] = (balanceByAddr[u.address] || 0) + amt;
}
for(var a in balanceByAddr){
balanceByAddr[a] = balanceByAddr[a]/COIN;
for (var a in balanceByAddr) {
balanceByAddr[a] = balanceByAddr[a] / COIN;
}
return cb(balance / COIN, balanceByAddr, isMain);
});
@ -434,12 +449,12 @@ Wallet.prototype.getSafeUnspent = function(cb) {
var self = this;
this.blockchain.getUnspent(this.getAddressesStr(), function(unspentList) {
var ret=[];
var ret = [];
var maxRejectCount = self.totalCopayers - self.requiredCopayers;
var uu = self.txProposals.getUsedUnspent(maxRejectCount);
for(var i in unspentList){
if (uu.indexOf(unspentList[i].txid) === -1)
for (var i in unspentList) {
if (uu.indexOf(unspentList[i].txid) === -1)
ret.push(unspentList[i]);
}
@ -462,7 +477,7 @@ Wallet.prototype.createTx = function(toAddress, amountSatStr, opts, cb) {
self.getSafeUnspent(function(unspentList) {
if (self.createTxSync(toAddress, amountSatStr, unspentList, opts)) {
self.sendPublicKeyRing(); // Change Address
self.sendPublicKeyRing(); // Change Address
self.sendTxProposals();
self.store();
}
@ -471,29 +486,33 @@ Wallet.prototype.createTx = function(toAddress, amountSatStr, opts, cb) {
};
Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) {
var pkr = this.publicKeyRing;
var pkr = this.publicKeyRing;
var priv = this.privateKey;
opts = opts || {};
var amountSat = bitcore.bignum(amountSatStr);
if (! pkr.isComplete() ) {
if (!pkr.isComplete()) {
throw new Error('publicKeyRing is not complete');
}
if (!opts.remainderOut) {
opts.remainderOut ={ address: this.generateAddress(true).toString() };
opts.remainderOut = {
address: this.generateAddress(true).toString()
};
}
var b = new Builder(opts)
.setUnspent(utxos)
.setHashToScriptMap(pkr.getRedeemScriptMap())
.setOutputs([{address: toAddress, amountSat: amountSat}])
;
.setOutputs([{
address: toAddress,
amountSat: amountSat
}]);
var signRet;
var signRet;
if (priv) {
b.sign( priv.getAll(pkr.addressIndex, pkr.changeAddressIndex) );
b.sign(priv.getAll(pkr.addressIndex, pkr.changeAddressIndex));
}
var myId = this.getMyCopayerId();
var now = Date.now();
@ -506,8 +525,8 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) {
var data = {
signedBy: me,
seenBy: meSeen,
creator: myId,
seenBy: meSeen,
creator: myId,
createdTs: now,
builder: b,
};
@ -522,8 +541,12 @@ Wallet.prototype.connectTo = function(peerId) {
Wallet.prototype.disconnect = function() {
console.log('[Wallet.js.524] DISC'); //TODO
console.log('[Wallet.js.524] DISC'); //TODO
this.network.disconnect();
};
Wallet.prototype.getNetwork = function() {
return this.network;
};
module.exports = require('soop')(Wallet);

View file

@ -13,29 +13,32 @@ var Key = bitcore.Key;
* when an unknown data type arrives
*
* Provides
* send(toPeerIds, {data}, cb?)
*
*/
function Network(opts) {
var self = this;
opts = opts || {};
this.peerId = opts.peerId;
this.apiKey = opts.apiKey || 'lwjd5qra8257b9';
this.debug = opts.debug || 3;
this.maxPeers = opts.maxPeers || 10;
this.opts = { key: opts.key };
opts = opts || {};
this.peerId = opts.peerId;
this.apiKey = opts.apiKey || 'lwjd5qra8257b9';
this.debug = opts.debug || 3;
this.maxPeers = opts.maxPeers || 10;
this.opts = {
key: opts.key
};
this.connections = {};
this.copayerForPeer = {};
// For using your own peerJs server
['port', 'host', 'path', 'debug'].forEach(function(k) {
if (opts[k]) self.opts[k]=opts[k];
if (opts[k]) self.opts[k] = opts[k];
});
this.connectedPeers = [];
this.started = false;
}
Network.parent=EventEmitter;
Network.parent = EventEmitter;
// Array helpers
Network._arrayDiff = function(a, b) {
@ -71,7 +74,6 @@ Network._arrayRemove = function(el, array) {
return array;
};
Network.prototype.connectedCopayers = function() {
var ret =[];
for(var i in this.connectedPeers){
@ -134,7 +136,7 @@ Network.prototype._onData = function(data, isInbound, peerId) {
payload= dataObj.payload;
} catch (e) {
console.log('### ERROR ON DATA: "%s" ', data, isInbound, e);
console.log('### ERROR ON DATA: "%s" ', data, isInbound, e);
return;
};
@ -187,8 +189,6 @@ Network.prototype._onData = function(data, isInbound, peerId) {
}
};
Network.prototype._checkAnyPeer = function() {
if (!this.connectedPeers.length) {
console.log('EMIT openError: no more peers, not even you!');
@ -198,7 +198,7 @@ Network.prototype._checkAnyPeer = function() {
}
Network.prototype._setupConnectionHandlers = function(dataConn, isInbound) {
var self=this;
var self = this;
dataConn.on('open', function() {
if (!Network._inArray(dataConn.peer, self.connectedPeers)
@ -220,7 +220,7 @@ Network.prototype._setupConnectionHandlers = function(dataConn, isInbound) {
});
dataConn.on('error', function(e) {
console.log('### DATA ERROR',e ); //TODO
console.log('### DATA ERROR', e); //TODO
self._onClose(dataConn.peer);
self._checkAnyPeer();
self.emit('dataError');
@ -229,7 +229,7 @@ Network.prototype._setupConnectionHandlers = function(dataConn, isInbound) {
dataConn.on('close', function() {
if (self.closing) return;
console.log('### CLOSE RECV FROM:', dataConn.peer);
console.log('### CLOSE RECV FROM:', dataConn.peer);
self._onClose(dataConn.peer);
self._checkAnyPeer();
});
@ -241,7 +241,7 @@ Network.prototype._notifyNetworkChange = function(newCopayerId) {
};
Network.prototype._setupPeerHandlers = function(openCallback) {
var self=this;
var self = this;
var p = this.peer;
p.on('open', function() {
@ -267,8 +267,7 @@ Network.prototype._setupPeerHandlers = function(openCallback) {
console.log('### CLOSING CONN FROM:' + dataConn.peer);
dataConn.close();
});
}
else {
} else {
self._setupConnectionHandlers(dataConn, true);
}
});
@ -284,7 +283,7 @@ Network.prototype._addCopayerMap = function(peerId, copayerId) {
Network.prototype.setCopayerId = function(copayerId) {
if (this.started) {
throw new Error ('network already started: can not change peerId')
throw new Error('network already started: can not change peerId')
}
this.copayerId = copayerId;
this.copayerIdBuf = new Buffer(copayerId,'hex');
@ -321,7 +320,7 @@ Network.prototype.start = function(opts, openCallback) {
console.log('CREATING PEER INSTANCE:', this.peerId); //TODO
this.peer = new Peer(this.peerId, this.opts);
this._setupPeerHandlers(openCallback);
for (var i = 0; i<opts.connectedPeers.length; i++) {
for (var i = 0; i < opts.connectedPeers.length; i++) {
var otherPeerId = opts.connectedPeers[i];
this.connectTo(otherPeerId);
}
@ -348,6 +347,13 @@ Network.prototype._sign = function(payload, copayerId) {
).toString('hex');
}
return ret;
}
Network.prototype.getOnlinePeerIDs = function() {
return this.connectedPeers;
};
Network.prototype.getPeer = function() {
return this.peer;
};
Network.prototype._sendToOne = function(copayerId, payload, cb) {

View file

@ -1,80 +1,101 @@
'use strict';
angular.module('copay.controllerUtils').factory('controllerUtils', function ($rootScope, $location, Socket) {
var root = {};
angular.module('copay.controllerUtils')
.factory('controllerUtils', function($rootScope, $sce, $location, Socket, video) {
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() {
console.log('### DELETING WALLET'); //TODO
$rootScope.wallet = null;
delete $rootScope['wallet'];
$rootScope.totalBalance = 0;
$location.path('signin');
};
root.logout = function() {
console.log('### DELETING WALLET'); //TODO
$rootScope.wallet = null;
delete $rootScope['wallet'];
$rootScope.totalBalance = 0;
$location.path('signin');
};
root.onError = function(scope) {
if (scope) scope.loading = false;
$rootScope.flashMessage = {type:'error', message: 'Could not connect to peer'};
root.logout();
}
root.onErrorDigest = function(scope) {
root.onError(scope);
$rootScope.$digest();
}
root.setupUxHandlers = function(w) {
w.on('badMessage', function(peerId) {
$rootScope.flashMessage = {type:'error', message: 'Received wrong message from peer id:' + peerId};
});
w.on('created', function() {
$location.path('peer');
$rootScope.wallet = w;
root.updateBalance();
});
w.on('refresh', function() {
console.log('[controllerUtils.js] Refreshing'); //TODO
root.updateBalance();
});
w.on('openError', root.onErrorDigest);
w.on('close', root.onErrorDigest);
w.netStart();
};
root.updateBalance = function() {
var w = $rootScope.wallet;
if (!w) return;
w.getBalance(false,function(balance, balanceByAddr) {
$rootScope.totalBalance = balance;
$rootScope.balanceByAddr = balanceByAddr;
console.log('New balance:', balance);
w.getBalance(true,function(balance) {
$rootScope.availableBalance = balance;
$rootScope.$digest();
});
});
};
root.setSocketHandlers = function() {
Socket.removeAllListeners();
var addrs = $rootScope.wallet.getAddressesStr();
for(var i = 0; i < addrs.length; i++) {
console.log('### SUBSCRIBE TO', addrs[i]);
Socket.emit('subscribe', addrs[i]);
root.onError = function(scope) {
if (scope) scope.loading = false;
$rootScope.flashMessage = {
type: 'error',
message: 'Could not connect to peer: ' +
scope
};
root.logout();
}
console.log('[controllerUtils.js.64]'); //TODO
addrs.forEach(function(addr) {
Socket.on(addr, function(txid) {
console.log('Received!', txid);
root.onErrorDigest = function(scope) {
root.onError(scope);
$rootScope.$digest();
}
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) {
$rootScope.flashMessage = {
type: 'error',
message: 'Received wrong message from peer id:' + peerId
};
});
w.on('created', function(myPeerID) {
video.setOwnPeer(myPeerID, w, handlePeerVideo);
$location.path('peer');
$rootScope.wallet = w;
root.updateBalance();
});
});
};
w.on('refresh', function() {
console.log('[controllerUtils.js] Refreshing'); //TODO
root.updateBalance();
});
w.on('openError', root.onErrorDigest);
w.on('peer', function(peerID) {
video.callPeer(peerID, handlePeerVideo);
});
w.on('close', root.onErrorDigest);
w.netStart();
};
return root;
});
root.updateBalance = function() {
var w = $rootScope.wallet;
if (!w) return;
w.getBalance(false, function(balance, balanceByAddr) {
$rootScope.totalBalance = balance;
$rootScope.balanceByAddr = balanceByAddr;
console.log('New balance:', balance);
w.getBalance(true, function(balance) {
$rootScope.availableBalance = balance;
$rootScope.$digest();
});
});
};
root.setSocketHandlers = function() {
Socket.removeAllListeners();
var addrs = $rootScope.wallet.getAddressesStr();
for (var i = 0; i < addrs.length; i++) {
console.log('### SUBSCRIBE TO', addrs[i]);
Socket.emit('subscribe', addrs[i]);
}
console.log('[controllerUtils.js.64]'); //TODO
addrs.forEach(function(addr) {
Socket.on(addr, function(txid) {
console.log('Received!', txid);
root.updateBalance();
});
});
};
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());