Fix Conflicts:

css/main.css
This commit is contained in:
Gustavo Cortez 2014-05-01 09:32:21 -03:00
commit ef6385ac65
12 changed files with 212 additions and 103 deletions

View File

@ -152,6 +152,12 @@ h3 {
border-right: 2px dashed #E3E3E3;
}
@media (max-width: 1025px) {
.line-dashed-v {
border: none;
}
}
.line-dashed-h {
margin: 1rem 0;
border-bottom: 2px dashed #E3E3E3;
@ -234,6 +240,7 @@ hr { margin: 2.25rem 0;}
.size-60 { font-size: 60px; }
.size-72 { font-size: 72px; }
.m10t {margin-top: 10px;}
.m10b {margin-bottom: 10px;}
.m10r {margin-right: 10px;}
.m10 {margin: 10px !important;}
.m15 {margin: 15px !important;}
@ -311,6 +318,63 @@ hr { margin: 2.25rem 0;}
padding: 2.7px;
}
.box-setup {
padding: 20px 30px;
border: 1px solid #eee;
background: #fff;
overflow: hidden;
margin-bottom: 10px;
}
.box-setup-copayers {
position: relative;
background: #ffffff;
border: 2px solid #eee;
}
.box-setup-copayers:after, .box-setup-copayers:before {
bottom: 100%;
left: 50%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.box-setup-copayers:after {
border-color: rgba(255, 255, 255, 0);
border-bottom-color: #ffffff;
border-width: 30px;
margin-left: -30px;
}
.box-setup-copayers:before {
border-color: rgba(238, 238, 238, 0);
border-bottom-color: #eee;
border-width: 33px;
margin-left: -33px;
}
.box-setup-copayers-fix {
overflow: hidden;
padding: 10px 10px 0 10px;
}
.box-setup-copay {
width: 60px;
height: 60px;
float: left;
margin-right: 10px;
margin-bottom: 10px;
border: 3px solid #eee;
}
.box-setup-copay-required {
border: 3px solid green;
}
.tx-copayers {
background: #F8F8F8;
-moz-box-shadow: inset 0px 0px 4px 0px rgba(0,0,0,0.05), inset 0px 1px 1px 0px rgba(0,0,0,0.05);
@ -352,3 +416,7 @@ hr { margin: 2.25rem 0;}
width: 200px;
}
a.loading {
background: #fff;
}

View File

@ -18,11 +18,15 @@
<span class="logo"></span>
</div>
<div class="large-9 medium-9 columns text-center p10t" ng-show="$root.wallet">
<div class="large-4 medium-4 columns line-dashed-v">
<div class="large-4 columns line-dashed-v">
<a href="#/addresses" class="has-tip" tooltip-placement="bottom" tooltip="{{$root.wallet.id}}">
<strong><span>{{$root.getWalletDisplay()}}</span></strong>
</a>
<a class="button radius small-icon" href="#" title="Signout" ng-click="signout()"><i class="fi-power"></i></a>
<a class="button radius small-icon" title="Manual Refresh"
ng-disabled="$root.loading"
ng-click="refresh()"><i class="fi-refresh"></i></a>
<a class="button radius small-icon" title="Signout"
ng-click="signout()"><i class="fi-power"></i></a>
</div>
<div class="large-4 medium-4 columns line-dashed-v">
Balance: {{totalBalance || 0}} <i class="fi-bitcoin"></i><br>
@ -196,36 +200,44 @@
</div>
<div ng-show="!loading">
<div class="row">
<div class="large-6 large-centered columns">
<h3>Create new multisig wallet</h3>
<hr>
<div class="small-12 medium-8 medium-centered large-8 large-centered columns box-setup">
<div class="large-6 columns line-dashed-v">
<h6>Select total number of copayers</h6>
<select ng-model="totalCopayers"
ng-options="totalCopayers as totalCopayers for totalCopayers in TCValues">
</select>
</div>
</div>
<div class="row">
<div class="large-6 large-centered columns m30v">
<div class="large-6 columns">
<h6>Select required number of signatures</h6>
<select ng-model="requiredCopayers"
ng-options="requiredCopayers as requiredCopayers for requiredCopayers in RCValues">
</select>
</div>
<div class="large-6 large-centered columns m30v">
<h6>Wallet name (optional)</h6>
<input ng-model="walletName" placeholder="My multisig wallet" class="size-24" style="width:100%">
</div>
<div class="large-6 large-centered columns m30v">
<hr>
</div>
<div class="row">
<div class="small-12 medium-6 medium-centered large-6 large-centered columns m30v">
<div class="box-setup-copayers">
<div class="box-setup-copayers-fix">
<img class="box-setup-copay" ng-repeat="i in getNumber(totalCopayers) track by $index" src="./img/satoshi.gif" alt="Copayer {{$index+1}}-{{totalCopayers}}" ng-class="{'box-setup-copay-required': ($index+1) <= requiredCopayers}">
</div>
</div>
</div>
</div>
<div class="row">
<div class="small-12 medium-6 medium-centered large-6 large-centered columns m30v">
<h6>Wallet name (optional)</h6>
<input type="text" class="form-control" ng-model="walletName" placeholder="Enter wallet name">
</div>
</div>
<div class="row">
<div class="large-12 columns line-dashed">
<button class="button primary radius right" type="button"
ng-click="create(totalCopayers, requiredCopayers, walletName)">
Create {{requiredCopayers}}-of-{{totalCopayers}} wallet
</button>
<div class="left">
<a href="#signin">Go back</a>
</div>
<a class="button secondary radius" href="#signin">Go back</a>
</div>
</div>
</div>
@ -237,21 +249,34 @@
<div class="addresses" data-ng-controller="AddressesController">
<div ng-show='$root.wallet.publicKeyRing.isComplete()'>
<div class="row">
<div class="large-9 columns" ng-if="addrs[0]">
<h3>Addresses (available to spend)</h3>
<div class="large-9 columns" ng-if="addrInfos[0]">
<div class="large-8 columns">
<a class="panel db" ng-repeat="addr in addrs" ng-click="selectAddr(addr)">{{addr}}
<span ng-if="!isMain[addr]">(change)</span>
<span class="right">({{balanceByAddr[addr] || 0}} <i class="fi-bitcoin"></i>)</span></a>
<a class="panel db" ng-repeat="addrInfo in addrInfos"
ng-click="selectAddr(addrInfo.address.toString())">
<span>{{addrInfo.address.toString()}}</span>
<span ng-if="addrInfo.isChange">(change)</span>
<span class="right">
<span ng-if="$root.loading">...</span>
<span ng-if="!$root.loading">{{balanceByAddr[addrInfo.address.toString()] || 0}}</span>
<i class="fi-bitcoin"></i>
</span>
</a>
</div>
<div class="large-4 columns line-dashed-v text-center">
<qrcode size="160" data="{{selectedAddr}}"></qrcode>
<p class="m10t" ng-repeat="addr in addrs" ng-if="selectedAddr==addr"> <strong> {{balanceByAddr[addr]}} <i class="fi-bitcoin"></i> </strong> </p>
<p class="m10t">
<strong>
<span ng-if="$root.loading">...</span>
<span ng-if="!$root.loading">{{balanceByAddr[selectedAddr] || 0}}</span>
<i class="fi-bitcoin"></i>
</strong>
</p>
</div>
</div>
<div class="columns text-center" ng-class="{'large-3' : addrs[0]}">
<div class="columns text-center" ng-class="{'large-3' : !!addrInfos[0]}">
<p> Create a New <strong> Address </strong> </p>
<button class="secondary radius expandi new-address" ng-click="newAddr()" ng-disabled="loading" loading="Creating"> Create </button>
<button class="secondary radius expandi new-address" ng-click="newAddr()"
ng-disabled="loading" loading="Creating"> Create </button>
</div>
</div>
</div>

View File

@ -1,5 +1,8 @@
'use strict';
var copay = require('copay');
var copayApp = window.copayApp = angular.module('copay',[
'ngRoute',
'mm.foundation',

View File

@ -2,36 +2,21 @@
angular.module('copay.addresses').controller('AddressesController',
function($scope, $rootScope, controllerUtils) {
$scope.title = 'Home';
$scope.oneAtATime = true;
$scope.addrBalance = {};
var w = $rootScope.wallet;
var _updateBalance = function () {
controllerUtils.setSocketHandlers();
w.getBalance(true, function (balance, balanceByAddr, isMain) {
if (balanceByAddr && Object.keys(balanceByAddr).length) {
$rootScope.balanceByAddr = balanceByAddr;
$scope.isMain = isMain;
$scope.addrs = Object.keys(balanceByAddr);
$scope.selectedAddr = $scope.addrs[0];
$scope.loading = false;
$rootScope.$digest();
}
});
};
$scope.loading = false;
$scope.newAddr = function() {
$scope.loading = true;
w.generateAddress();
_updateBalance();
controllerUtils.updateBalance(function() {
$scope.loading = false;
$rootScope.$digest();
});
};
$scope.selectAddr = function(addr) {
$scope.selectedAddr = addr;
};
_updateBalance();
w.on('refresh', _updateBalance);
});

View File

@ -40,7 +40,13 @@ angular.module('copay.header').controller('HeaderController',
w.disconnect();
controllerUtils.logout();
}
$rootScope.flashMessage = {};
$scope.clearFlashMessage();
};
$scope.refresh = function() {
controllerUtils.updateBalance(function() {
$rootScope.$digest();
});
};
$scope.clearFlashMessage = function() {

View File

@ -5,6 +5,11 @@ angular.module('copay.setup').controller('SetupController',
$scope.loading = false;
// ng-repeat defined number of times instead of repeating over array?
$scope.getNumber = function(num) {
return new Array(num);
}
$scope.totalCopayers = config.wallet.totalCopayers;
$scope.TCValues = [];
for (var n = 1; n <= config.limits.totalCopayers; n++)

View File

@ -1,5 +1,5 @@
'use strict';
var copay = require('copay');
angular.element(document).ready(function() {
// Init the app
angular.bootstrap(document, ['copay']);

View File

@ -143,7 +143,6 @@ PublicKeyRing.prototype.addCopayer = function (newEpk) {
return newEpk;
};
PublicKeyRing.prototype.getPubKeys = function (index, isChange) {
this._checkKeys();
@ -159,6 +158,7 @@ PublicKeyRing.prototype.getPubKeys = function (index, isChange) {
this.publicKeysCache[path] = pubKeys.map(function(pk){return pk.toString('hex');});
} else {
pubKeys = pubKeys.map(function(s){return new Buffer(s,'hex')});
//console.log('public keys cache HIT');
}
return pubKeys;
@ -183,21 +183,12 @@ PublicKeyRing.prototype.getRedeemScript = function (index, isChange) {
// TODO this could be cached
PublicKeyRing.prototype.getAddress = function (index, isChange) {
this._checkIndexRange(index, isChange);
var script = this.getRedeemScript(index,isChange);
return Address.fromScript(script, this.network.name);
};
// TODO this could be cached
PublicKeyRing.prototype._addScriptMap = function (map, index, isChange) {
this._checkIndexRange(index, isChange);
var script = this.getRedeemScript(index,isChange);
map[Address.fromScript(script, this.network.name).toString()] = script.getBuffer().toString('hex');
};
// TODO this could be cached
PublicKeyRing.prototype.getScriptPubKeyHex = function (index, isChange) {
this._checkIndexRange(index, isChange);
var addr = this.getAddress(index,isChange);
return Script.createP2SH(addr.payload()).getBuffer().toString('hex');
};
@ -218,21 +209,39 @@ PublicKeyRing.prototype.generateAddress = function(isChange) {
};
PublicKeyRing.prototype.getAddresses = function(onlyMain) {
PublicKeyRing.prototype.getAddresses = function(excludeChange) {
return this.getAddressesInfo(excludeChange).map(function(info) {
return info.address;
});
};
PublicKeyRing.prototype.getAddressesInfo = function(excludeChange) {
var ret = [];
for (var i=0; i<this.addressIndex; i++) {
ret.unshift(this.getAddress(i,false));
}
if (!onlyMain) {
if (!excludeChange) {
for (var i=0; i<this.changeAddressIndex; i++) {
ret.unshift(this.getAddress(i,true));
ret.unshift({
address: this.getAddress(i,true),
isChange: true
});
}
}
for (var i=0; i<this.addressIndex; i++) {
ret.unshift({
address: this.getAddress(i,false),
isChange: false
});
}
return ret;
};
// TODO this could be cached
PublicKeyRing.prototype._addScriptMap = function (map, index, isChange) {
var script = this.getRedeemScript(index,isChange);
map[Address.fromScript(script, this.network.name).toString()] = script.getBuffer().toString('hex');
};
PublicKeyRing.prototype.getRedeemScriptMap = function () {
var ret = {};

View File

@ -401,16 +401,19 @@ Wallet.prototype.addSeenToTxProposals = function() {
return ret;
};
Wallet.prototype.getAddresses = function(onlyMain) {
return this.publicKeyRing.getAddresses(onlyMain);
// TODO: remove this method and use getAddressesInfo everywhere
Wallet.prototype.getAddresses = function(excludeChange) {
return this.publicKeyRing.getAddresses(excludeChange);
};
Wallet.prototype.getAddressesStr = function(onlyMain) {
var ret = [];
this.publicKeyRing.getAddresses(onlyMain).forEach(function(a) {
ret.push(a.toString());
Wallet.prototype.getAddressesStr = function(excludeChange) {
return this.getAddresses(excludeChange).map(function(a) {
return a.toString();
});
return ret;
};
Wallet.prototype.getAddressesInfo = function(excludeChange) {
return this.publicKeyRing.getAddressesInfo(excludeChange);
};
Wallet.prototype.addressIsOwn = function(addrStr) {
@ -432,27 +435,21 @@ Wallet.prototype.getBalance = function(safe, cb) {
var balanceByAddr = {};
var isMain = {};
var COIN = bitcore.util.COIN;
var addresses = this.getAddressesStr(true);
if (!addresses.length) return cb(0, []);
// Prefill balanceByAddr with main address
addresses.forEach(function(a) {
balanceByAddr[a] = 0;
isMain[a] = 1;
});
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];
var amt = u.amount * COIN;
balance = balance + amt;
balance += amt;
balanceByAddr[u.address] = (balanceByAddr[u.address] || 0) + amt;
}
// we multiply and divide by COIN to avoid rounding errors when adding
for (var a in balanceByAddr) {
balanceByAddr[a] = balanceByAddr[a] / COIN;
}
return cb(balance / COIN, balanceByAddr, isMain);
balance = balance / COIN;
return cb(balance, balanceByAddr, isMain);
});
};

View File

@ -4,6 +4,8 @@ angular.module('copay.controllerUtils')
.factory('controllerUtils', function($rootScope, $sce, $location, Socket, video) {
var root = {};
$rootScope.videoSrc = {};
$rootScope.loading = false;
$rootScope.getVideoURL = function(copayer) {
var encoded = $rootScope.videoSrc[copayer];
if (!encoded) return;
@ -18,7 +20,6 @@ angular.module('copay.controllerUtils')
};
root.logout = function() {
console.log('### DELETING WALLET'); //TODO
$rootScope.wallet = null;
delete $rootScope['wallet'];
$rootScope.totalBalance = 0;
@ -44,7 +45,7 @@ angular.module('copay.controllerUtils')
return;
}
$rootScope.videoSrc[peerID] = encodeURI(url);
$rootScope.$apply();
$rootScope.$digest();
};
w.on('badMessage', function(peerId) {
$rootScope.flashMessage = {
@ -54,12 +55,15 @@ angular.module('copay.controllerUtils')
});
w.on('created', function(myPeerID) {
video.setOwnPeer(myPeerID, w, handlePeerVideo);
$location.path('addresses');
$rootScope.wallet = w;
root.updateBalance();
$location.path('addresses');
});
w.on('refresh', function() {
root.updateBalance();
root.setSocketHandlers();
root.updateBalance(function() {
$rootScope.$digest();
});
$rootScope.$digest();
});
w.on('publicKeyRingUpdated', function() {
root.setSocketHandlers();
@ -72,21 +76,31 @@ angular.module('copay.controllerUtils')
w.netStart();
};
root.updateBalance = function() {
root.updateBalance = function(cb) {
root.setSocketHandlers();
$rootScope.balanceByAddr = {};
var w = $rootScope.wallet;
if (!w) return;
$rootScope.addrInfos = w.getAddressesInfo();
if ($rootScope.addrInfos.length === 0) return;
$rootScope.loading = true;
w.getBalance(false, function(balance, balanceByAddr) {
console.log('New total balance:', balance);
$rootScope.totalBalance = balance;
$rootScope.balanceByAddr = balanceByAddr;
console.log('New balance:', balance);
w.getBalance(true, function(balance) {
$rootScope.availableBalance = balance;
$rootScope.$digest();
});
$rootScope.selectedAddr = $rootScope.addrInfos[0].address.toString();
$rootScope.loading = false;
if (cb) cb();
});
w.getBalance(true, function(balance) {
console.log('New available balance:', balance);
$rootScope.availableBalance = balance;
$rootScope.loading = false;
if (cb) cb();
});
};
root.setSocketHandlers = function() {
// TODO: optimize this?
Socket.removeAllListeners();
if (!$rootScope.wallet) return;
@ -98,10 +112,11 @@ angular.module('copay.controllerUtils')
addrs.forEach(function(addr) {
Socket.on(addr, function(txid) {
console.log('Received!', txid);
root.updateBalance();
root.updateBalance(function() {
$rootScope.$digest();
});
});
});
};
return root;
});

View File

@ -72,7 +72,7 @@ Video.prototype._addCall = function(mediaConnection, cb) {
}
Video.prototype.close = function() {
if (this.localStream){
if (this.localStream) {
this.localStream.stop();
this.localStream.mozSrcObject = null;
this.localStream.src = "";

View File

@ -1,8 +1,4 @@
'use strict';
var wf;
angular.module('copay.walletFactory').factory('walletFactory', function($rootScope) {
wf = wf || new copay.WalletFactory(config);
return wf;
});
angular.module('copay.walletFactory').value('walletFactory', new copay.WalletFactory(config));