mirror of https://github.com/BTCPrivate/copay.git
switch between wallets in profile working
This commit is contained in:
parent
ff44897922
commit
ac491d10b0
16
index.html
16
index.html
|
@ -52,22 +52,20 @@
|
|||
</section>
|
||||
</nav>
|
||||
|
||||
<aside class="left-off-canvas-menu">
|
||||
<div ng-include="'views/includes/sidebar-mobile.html'"></div>
|
||||
</aside>
|
||||
|
||||
<!-- <aside class="left-off-canvas-menu"> -->
|
||||
<!-- <div ng-include="'views/includes/sidebar-mobile.html'"></div> -->
|
||||
<!-- </aside> -->
|
||||
<!-- -->
|
||||
<div notifications="right top"></div>
|
||||
|
||||
<div
|
||||
ng-class="{'sidebar' : $root.wallet && $root.wallet.isReady() &&
|
||||
!$root.wallet.isLocked}"
|
||||
ng-include="'views/includes/sidebar.html'"
|
||||
role='navigation'
|
||||
ng-if="$root.wallet && $root.wallet.isReady() &&
|
||||
!$root.wallet.isLocked"></div>
|
||||
class="sidebar"
|
||||
ng-if="$root.iden"></div>
|
||||
|
||||
<section ng-class="{'main' : $root.wallet && $root.wallet.isReady() &&
|
||||
!$root.wallet.isLocked}" ng-view></section>
|
||||
<section ng-class="{'main' : $root.iden && $root.iden.listWallets().length>0}" ng-view></section>
|
||||
|
||||
<a class="exit-off-canvas"></a>
|
||||
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('CreateController',
|
||||
function($scope, $rootScope, $location, $timeout, controllerUtils, backupService, notification) {
|
||||
|
||||
$rootScope.fromSetup = true;
|
||||
$scope.loading = false;
|
||||
$scope.walletPassword = $rootScope.walletPassword;
|
||||
$scope.isMobile = !!window.cordova;
|
||||
$scope.hideAdv = true;
|
||||
$scope.networkName = config.networkName;
|
||||
|
||||
// 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 = _.range(1, config.limits.totalCopayers + 1);
|
||||
|
||||
var updateRCSelect = function(n) {
|
||||
var maxReq = copay.Wallet.getMaxRequiredCopayers(n);
|
||||
$scope.RCValues = _.range(1, maxReq + 1);
|
||||
$scope.requiredCopayers = Math.min(parseInt(n / 2 + 1), maxReq);
|
||||
};
|
||||
|
||||
updateRCSelect($scope.totalCopayers);
|
||||
|
||||
$scope.$watch('totalCopayers', function(tc) {
|
||||
updateRCSelect(tc);
|
||||
});
|
||||
|
||||
$scope.create = function(form) {
|
||||
if (form && form.$invalid) {
|
||||
notification.error('Error', 'Please enter the required fields');
|
||||
return;
|
||||
}
|
||||
$scope.loading = true;
|
||||
var opts = {
|
||||
requiredCopayers: $scope.requiredCopayers,
|
||||
totalCopayers: $scope.totalCopayers,
|
||||
name: $scope.walletName,
|
||||
privateKeyHex: $scope.private,
|
||||
networkName: $scope.networkName,
|
||||
};
|
||||
$rootScope.iden.createWallet(opts, function(err, w) {
|
||||
$rootScope.iden.closeWallet($rootScope.wallet.id, function() {
|
||||
$scope.loading = false;
|
||||
$rootScope.wallet = w;
|
||||
controllerUtils.bindWallet(w, $scope);
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
|
@ -13,10 +13,8 @@ angular.module('copayApp.controllers').controller('CreateProfileController', fun
|
|||
walletDefaults: config.wallet,
|
||||
passphrase: config.passphrase,
|
||||
}, function(err, iden ,w) {
|
||||
$scope.loading = false;
|
||||
$rootScope.iden = iden;
|
||||
$rootScope.wallet = w;
|
||||
|
||||
controllerUtils.bindWallet(w, $scope);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ angular.module('copayApp.controllers').controller('HomeController', function($sc
|
|||
controllerUtils.onErrorDigest(
|
||||
$scope, (err.toString()||'').match('PNOTFOUND') ? 'Profile not found' : 'Unknown error');
|
||||
} else {
|
||||
$scope.loading = false;
|
||||
$rootScope.iden = iden;
|
||||
$rootScope.wallet = w;
|
||||
controllerUtils.bindWallet(w, $scope);
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('JoinController',
|
||||
function($scope, $rootScope, $timeout, identity, controllerUtils, Passphrase, notification) {
|
||||
controllerUtils.redirIfLogged();
|
||||
function($scope, $rootScope, $timeout, controllerUtils, notification) {
|
||||
$rootScope.fromSetup = false;
|
||||
$scope.loading = false;
|
||||
$scope.isMobile = !!window.cordova;
|
||||
|
@ -120,31 +119,32 @@ angular.module('copayApp.controllers').controller('JoinController',
|
|||
|
||||
$scope.loading = true;
|
||||
|
||||
Passphrase.getBase64Async($scope.joinPassword, function(passphrase) {
|
||||
identity.joinCreateSession({
|
||||
secret: $scope.connectionId,
|
||||
nickname: $scope.nickname,
|
||||
passphrase: passphrase,
|
||||
privateHex: $scope.private,
|
||||
}, function(err, w) {
|
||||
$rootScope.iden.joinWallet({
|
||||
secret: $scope.connectionId,
|
||||
nickname: $scope.nickname,
|
||||
privateHex: $scope.private,
|
||||
}, function(err, w) {
|
||||
|
||||
$scope.loading = false;
|
||||
if (err || !w) {
|
||||
if (err === 'joinError')
|
||||
notification.error('Fatal error connecting to Insight server');
|
||||
else if (err === 'walletFull')
|
||||
notification.error('The wallet is full');
|
||||
else if (err === 'badNetwork')
|
||||
notification.error('Network Error', 'Wallet network configuration missmatch');
|
||||
else if (err === 'badSecret')
|
||||
notification.error('Bad secret', 'The secret string you entered is invalid');
|
||||
else
|
||||
notification.error('Unknown error');
|
||||
controllerUtils.onErrorDigest();
|
||||
} else {
|
||||
controllerUtils.startNetwork(w, $scope);
|
||||
}
|
||||
});
|
||||
$scope.loading = false;
|
||||
if (err || !w) {
|
||||
if (err === 'joinError')
|
||||
notification.error('Fatal error connecting to Insight server');
|
||||
else if (err === 'walletFull')
|
||||
notification.error('The wallet is full');
|
||||
else if (err === 'badNetwork')
|
||||
notification.error('Network Error', 'Wallet network configuration missmatch');
|
||||
else if (err === 'badSecret')
|
||||
notification.error('Bad secret', 'The secret string you entered is invalid');
|
||||
else
|
||||
notification.error('Unknown error');
|
||||
controllerUtils.onErrorDigest();
|
||||
} else {
|
||||
$rootScope.iden.closeWallet($rootScope.wallet.id, function() {
|
||||
$scope.loading = false;
|
||||
$rootScope.wallet = w;
|
||||
controllerUtils.bindWallet(w, $scope);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('MoreController',
|
||||
function($scope, $rootScope, $location, $filter, backupService, identity, controllerUtils, notification, rateService) {
|
||||
function($scope, $rootScope, $location, $filter, backupService, controllerUtils, notification, rateService) {
|
||||
var w = $rootScope.wallet;
|
||||
$scope.isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
|
||||
|
||||
|
@ -81,7 +81,7 @@ angular.module('copayApp.controllers').controller('MoreController',
|
|||
};
|
||||
|
||||
$scope.deleteWallet = function() {
|
||||
identity.delete(w.id, function() {
|
||||
$rootScope.iden.deleteWallet(w.id, function() {
|
||||
controllerUtils.logout();
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('OpenController', function($scope, $rootScope, $location, identity, controllerUtils, Passphrase, notification) {
|
||||
angular.module('copayApp.controllers').controller('OpenController', function($scope, $rootScope, $location, controllerUtils, Passphrase, notification) {
|
||||
controllerUtils.redirIfLogged();
|
||||
|
||||
if ($rootScope.pendingPayment) {
|
||||
|
|
|
@ -58,9 +58,9 @@ angular.module('copayApp.controllers').controller('SidebarController', function(
|
|||
}
|
||||
|
||||
if ($rootScope.wallet) {
|
||||
$scope.$on('$idleWarn', function(a,countdown) {
|
||||
if (!(countdown%5))
|
||||
notification.warning('Session will be closed', $filter('translate')('Your session is about to expire due to inactivity in') + ' ' + countdown + ' ' + $filter('translate')('seconds'));
|
||||
$scope.$on('$idleWarn', function(a, countdown) {
|
||||
if (!(countdown % 5))
|
||||
notification.warning('Session will be closed', $filter('translate')('Your session is about to expire due to inactivity in') + ' ' + countdown + ' ' + $filter('translate')('seconds'));
|
||||
});
|
||||
|
||||
$scope.$on('$idleTimeout', function() {
|
||||
|
@ -71,4 +71,21 @@ angular.module('copayApp.controllers').controller('SidebarController', function(
|
|||
$rootScope.wallet.keepAlive();
|
||||
});
|
||||
}
|
||||
|
||||
$scope.switchWallet = function(id) {
|
||||
var iden = $rootScope.iden;
|
||||
controllerUtils.unbindWallet($scope);
|
||||
|
||||
iden.openWallet(id, null, function(err, w) {
|
||||
if (err) {
|
||||
notification.warning('Could not open wallet');
|
||||
} else {
|
||||
iden.closeWallet($rootScope.wallet.id, function() {
|
||||
$scope.loading = false;
|
||||
$rootScope.wallet = w;
|
||||
controllerUtils.bindWallet(w, $scope);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
|
|
|
@ -111,14 +111,13 @@ angular.module('copayApp.directives')
|
|||
};
|
||||
}
|
||||
])
|
||||
.directive('walletSecret', ['walletFactory',
|
||||
function(walletFactory) {
|
||||
.directive('walletSecret', function() {
|
||||
return {
|
||||
require: 'ngModel',
|
||||
link: function(scope, elem, attrs, ctrl) {
|
||||
var validator = function(value) {
|
||||
var a = new Address(value);
|
||||
ctrl.$setValidity('walletSecret', !a.isValid() && Boolean(walletFactory.decodeSecret(value)));
|
||||
ctrl.$setValidity('walletSecret', !a.isValid() && Boolean(copay.Wallet.decodeSecret(value)));
|
||||
return value;
|
||||
};
|
||||
|
||||
|
@ -126,7 +125,7 @@ angular.module('copayApp.directives')
|
|||
}
|
||||
};
|
||||
}
|
||||
])
|
||||
)
|
||||
.directive('loading', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
|
|
|
@ -94,8 +94,8 @@ Identity._walletRead = function(id, s, n, b, skip, cb) {
|
|||
return Wallet.read(id, s, n, b, skip, cb);
|
||||
};
|
||||
|
||||
Identity._walletDelete = function(id, cb) {
|
||||
return Wallet.delete(id, cb);
|
||||
Identity._walletDelete = function(id, s, cb) {
|
||||
return Wallet.delete(id, s, cb);
|
||||
};
|
||||
|
||||
/* for stubbing */
|
||||
|
@ -133,6 +133,7 @@ Identity.create = function(email, password, opts, cb) {
|
|||
requiredCopayers: 1,
|
||||
totalCopayers: 1,
|
||||
password: password,
|
||||
name: 'general',
|
||||
});
|
||||
iden.createWallet(wopts, function(err, w) {
|
||||
return cb(null, iden, w);
|
||||
|
@ -170,10 +171,22 @@ Identity.open = function(email, password, opts, cb) {
|
|||
Identity._openProfile(email, password, iden.storage, function(err, profile) {
|
||||
if (err) return cb(err);
|
||||
iden.profile = profile;
|
||||
var wid = iden.listWallets()[0].id;
|
||||
iden.openWallet(wid, password, function(err, w) {
|
||||
return cb(err, iden, w);
|
||||
})
|
||||
|
||||
var wids = _.pluck(iden.listWallets(), 'id');
|
||||
|
||||
|
||||
while (1) {
|
||||
var wid = wids.shift();
|
||||
if (!wid)
|
||||
return new Error('Could not open any wallet from profile');
|
||||
|
||||
iden.openWallet(wid, password, function(err, w) {
|
||||
if (err)
|
||||
log.info('Cound not open wallet id:' + wid + '. Skipping')
|
||||
else
|
||||
return cb(err, iden, w);
|
||||
})
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
@ -222,6 +235,16 @@ Identity.prototype.store = function(opts, cb) {
|
|||
};
|
||||
|
||||
|
||||
Identity.prototype._cleanUp = function() {
|
||||
log.info('Cleaning Network connections')
|
||||
var self = this;
|
||||
|
||||
_.each(['livenet', 'testnet'], function(n) {
|
||||
self.networks[n].cleanUp();
|
||||
self.blockchains[n].destroy();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc Closes the wallet and disconnects all services
|
||||
*/
|
||||
|
@ -234,12 +257,17 @@ Identity.prototype.close = function(cb) {
|
|||
return cb ? cb() : null;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
_.each(this.openWallets, function(w) {
|
||||
w.close(function(err) {
|
||||
console.log('[Identity.js.239:err:]', err); //TODO
|
||||
if (err) return cb(err);
|
||||
|
||||
if (++i == l && cb)
|
||||
return cb();
|
||||
console.log('[Identity.js.241]', i, l); //TODO
|
||||
if (++i == l) {
|
||||
self._cleanUp();
|
||||
if (cb) return cb();
|
||||
}
|
||||
})
|
||||
});
|
||||
};
|
||||
|
@ -268,6 +296,22 @@ Identity.prototype.importWallet = function(base64, password, skipFields, cb) {
|
|||
w.store(cb);
|
||||
});
|
||||
};
|
||||
|
||||
Identity.prototype.closeWallet = function(wid, cb) {
|
||||
var w = _.findWhere(this.openWallets, function(w) {
|
||||
w.id === wid;
|
||||
});
|
||||
preconditions.checkState(w);
|
||||
|
||||
var self = this;
|
||||
w.close(function(err) {
|
||||
self.openWallets = _.without(self.openWallets, function(id) {
|
||||
id === wid
|
||||
});
|
||||
return cb(err);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc This method prepares options for a new Wallet
|
||||
*
|
||||
|
@ -345,13 +389,15 @@ Identity.prototype.createWallet = function(opts, cb) {
|
|||
var w = Identity._newWallet(opts);
|
||||
this.addWallet(w, function(err) {
|
||||
if (err) return cb(err);
|
||||
self.openWallets.push(w);
|
||||
|
||||
self.profile.setLastOpenedTs(w.id, function(err) {
|
||||
return cb(err, w);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// add open wallet?
|
||||
// add wallet (import)
|
||||
Identity.prototype.addWallet = function(wallet, cb) {
|
||||
preconditions.checkArgument(wallet);
|
||||
preconditions.checkArgument(wallet.getId);
|
||||
|
@ -359,10 +405,11 @@ Identity.prototype.addWallet = function(wallet, cb) {
|
|||
preconditions.checkState(this.profile);
|
||||
|
||||
var self = this;
|
||||
self.profile.addWallet(wallet.id, {}, function(err) {
|
||||
self.profile.addWallet(wallet.getId(), {
|
||||
name: wallet.name
|
||||
}, function(err) {
|
||||
|
||||
if (err) return cb(err);
|
||||
self.openWallets.push(wallet);
|
||||
wallet.store(function(err) {
|
||||
return cb(err);
|
||||
});
|
||||
|
@ -400,15 +447,19 @@ Identity.prototype._checkVersion = function(inVersion) {
|
|||
* @return
|
||||
*/
|
||||
Identity.prototype.openWallet = function(walletId, password, cb) {
|
||||
console.log('[Identity.js.434:openWallet:]', walletId); //TODO
|
||||
preconditions.checkArgument(cb);
|
||||
var self = this;
|
||||
|
||||
self.storage.setPassword(password);
|
||||
if (password)
|
||||
self.storage.setPassword(password);
|
||||
|
||||
// TODO
|
||||
// self.migrateWallet(walletId, password, function() {
|
||||
|
||||
Identity._walletRead(walletId, self.storage, self.networks, self.blockchains, [], function(err, w) {
|
||||
if (err) return cb(err);
|
||||
self.openWallets.push(w);
|
||||
|
||||
w.store(function(err) {
|
||||
self.profile.setLastOpenedTs(walletId, function() {
|
||||
|
@ -421,7 +472,8 @@ Identity.prototype.openWallet = function(walletId, password, cb) {
|
|||
|
||||
|
||||
Identity.prototype.listWallets = function(a) {
|
||||
return this.profile.listWallets();
|
||||
var ret = this.profile.listWallets();
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -468,7 +520,6 @@ Identity.prototype.decodeSecret = function(secret) {
|
|||
*
|
||||
* @param {object} opts
|
||||
* @param {string} opts.secret - the wallet secret
|
||||
* @param {string} opts.password - a password to use to encrypt the wallet for persistance
|
||||
* @param {string} opts.nickname - a nickname for the current user
|
||||
* @param {string} opts.privateHex - the private extended master key
|
||||
* @param {walletCreationCallback} cb - a callback
|
||||
|
@ -476,8 +527,6 @@ Identity.prototype.decodeSecret = function(secret) {
|
|||
Identity.prototype.joinWallet = function(opts, cb) {
|
||||
preconditions.checkArgument(opts);
|
||||
preconditions.checkArgument(opts.secret);
|
||||
preconditions.checkArgument(opts.password);
|
||||
preconditions.checkArgument(opts.nickname);
|
||||
preconditions.checkArgument(cb);
|
||||
var self = this;
|
||||
var decodedSecret = this.decodeSecret(opts.secret);
|
||||
|
@ -534,8 +583,10 @@ Identity.prototype.joinWallet = function(opts, cb) {
|
|||
walletOpts.id = data.walletId;
|
||||
|
||||
walletOpts.privateKey = privateKey;
|
||||
walletOpts.nickname = opts.nickname;
|
||||
walletOpts.password = opts.password;
|
||||
walletOpts.nickname = opts.nickname || self.profile.name;
|
||||
|
||||
if (opts.password)
|
||||
walletOpts.password = opts.password;
|
||||
|
||||
self.createWallet(walletOpts, function(err, w) {
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ function Profile(info, storage) {
|
|||
|
||||
this.hash = info.hash;
|
||||
this.email = info.email;
|
||||
this.extra = info.extra;
|
||||
this.extra = info.extra || {};
|
||||
this.walletInfos = info.walletInfos || {};
|
||||
|
||||
this.key = Profile.key(this.hash);
|
||||
|
@ -69,7 +69,7 @@ Profile.prototype.getWallet = function(walletId, cb) {
|
|||
|
||||
Profile.prototype.listWallets = function(opts, cb) {
|
||||
return _.sortBy(this.walletInfos, function(winfo) {
|
||||
return winfo.lastOpenedTs || winfo.createdTs;
|
||||
return -winfo.lastOpenedTs || -winfo.createdTs;
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -141,4 +141,9 @@ Profile.prototype.store = function(opts, cb) {
|
|||
});
|
||||
};
|
||||
|
||||
|
||||
Profile.prototype.getName = function() {
|
||||
return this.extra.nickname || this.email;
|
||||
};
|
||||
|
||||
module.exports = Profile;
|
||||
|
|
|
@ -183,12 +183,13 @@ Storage.prototype.delete = function(key, cb) {
|
|||
};
|
||||
|
||||
Storage.prototype.deletePrefix = function(prefix, cb) {
|
||||
storage.getFirst(prefix, function(err, v, k) {
|
||||
if (err && !v) return cb(err);
|
||||
var self = this;
|
||||
this.getFirst(prefix, function(err, v, k) {
|
||||
if (err || !v) return cb(err);
|
||||
|
||||
storage.delete(k, function(err) {
|
||||
self.delete(k, function(err) {
|
||||
if (err) return cb(err);
|
||||
storage.deletePrefix(prefix, cb);
|
||||
self.deletePrefix(prefix, cb);
|
||||
})
|
||||
});
|
||||
};
|
||||
|
|
|
@ -241,6 +241,7 @@ Wallet.read = function(walletId, storage, network, blockchain, skipFields, cb) {
|
|||
var w, err;
|
||||
obj.id = walletId;
|
||||
try {
|
||||
log.debug('## OPENING Wallet: ' + walletId);
|
||||
w = self.fromObj(obj, storage, network, blockchain, skipFields);
|
||||
} catch (e) {
|
||||
log.debug("ERROR: ", e.message);
|
||||
|
@ -892,6 +893,7 @@ Wallet.prototype.netStart = function() {
|
|||
self.emit('connectionError');
|
||||
});
|
||||
|
||||
log.debug('Starting wallet networking');
|
||||
net.start(startOpts, function() {
|
||||
self._setBlockchainListeners();
|
||||
self.emit('ready', net.getPeer());
|
||||
|
@ -2536,10 +2538,8 @@ Wallet.prototype.indexDiscovery = function(start, change, copayerIndex, gap, cb)
|
|||
*/
|
||||
Wallet.prototype.close = function(cb) {
|
||||
var self = this;
|
||||
log.debug('## CLOSING Wallet');
|
||||
log.debug('## CLOSING Wallet: ' + this.id);
|
||||
this.lock.release(function() {
|
||||
self.network.cleanUp();
|
||||
self.blockchain.destroy();
|
||||
if (cb) return cb();
|
||||
});
|
||||
};
|
||||
|
|
|
@ -20,7 +20,7 @@ angular
|
|||
})
|
||||
.when('/join', {
|
||||
templateUrl: 'views/join.html',
|
||||
validate: false
|
||||
validate: true
|
||||
})
|
||||
.when('/import', {
|
||||
templateUrl: 'views/import.html',
|
||||
|
|
|
@ -154,13 +154,18 @@ angular.module('copayApp.services')
|
|||
});
|
||||
};
|
||||
|
||||
|
||||
root.unbindWallet = function($scope) {
|
||||
var w =$rootScope.wallet;
|
||||
w.removeAllListeners();
|
||||
};
|
||||
|
||||
root.bindWallet = function(w, $scope) {
|
||||
root.setupRootVariables();
|
||||
root.installWalletHandlers(w, $scope);
|
||||
root.updateAddressList();
|
||||
notification.enableHtml5Mode(); // for chrome: if support, enable it
|
||||
w.netStart();
|
||||
|
||||
};
|
||||
|
||||
// TODO movie this to wallet
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
<div class="waiting-copayers" ng-controller="CopayersController">
|
||||
<div ng-if='$root.wallet && $root.wallet.isReady()' ng-init="goToWallet()"></div>
|
||||
<div class="row" ng-if='$root.wallet && !$root.wallet.isReady() && !loading'>
|
||||
<div class="large-4 columns logo-setup">
|
||||
<img src="img/logo-negative-beta.svg" alt="Copay" width="146" height="59">
|
||||
<div ng-include="'views/includes/version.html'"></div>
|
||||
</div>
|
||||
<div class="large-8 columns line-dashed-setup-v">
|
||||
|
||||
<div class="row collapse m0">
|
||||
<div class="large-6 columns">
|
||||
|
||||
<div class="box-setup oh">
|
||||
<div ng-if="!$root.wallet.publicKeyRing.isComplete()">
|
||||
<img src="img/step-3.png" alt="Step 3" width="157" class="right m15t" ng-if="$root.fromSetup && !isMobile">
|
||||
|
|
|
@ -35,6 +35,22 @@
|
|||
</div>
|
||||
</div>
|
||||
<p translate class="comment" ng-show="totalCopayers>1">(*) The limits are imposed by the bitcoin network.</p>
|
||||
|
||||
<a class="expand small" ng-click="hideAdv=!hideAdv">
|
||||
<i class="fi-widget m3r"></i>
|
||||
<span translate ng-hide="!hideAdv">Show</span>
|
||||
<span translate ng-hide="hideAdv">Hide</span>
|
||||
<span translate>advanced options</span>
|
||||
</a>
|
||||
<div ng-hide="hideAdv" class="m10t">
|
||||
<input id="network-name" type="checkbox" ng-model="networkName" ng-true-value="testnet" ng-false-value="livenet" class="form-control" ng-checked="networkName == 'testnet' ? true : false">
|
||||
<label for="network-name" translate>Use test network</label>
|
||||
|
||||
<p>
|
||||
<input type="text" placeholder="BIP32 master extended private key (hex)" name="private" ng-model="private">
|
||||
</div>
|
||||
|
||||
|
||||
<div class="text-right">
|
||||
<button translate type="submit" class="button secondary m0" ng-disabled="setupForm.$invalid || loading">
|
||||
Create {{requiredCopayers}}-of-{{totalCopayers}} wallet
|
||||
|
|
|
@ -11,13 +11,20 @@
|
|||
<div>
|
||||
Available wallets
|
||||
<ul class="side-nav">
|
||||
<li data-ng-repeat="item in $root.iden.listWallets()" class="nav-item">
|
||||
{{item.id}}
|
||||
<li data-ng-repeat="item in $root.iden.listWallets() track by $index" class="nav-item">
|
||||
<a ng-click="switchWallet(item.id)">
|
||||
{{item.name || item.id}}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item" ui-route="{{create}}">
|
||||
<a href="#!/create">+ {{'Create a new wallet' | translate }}
|
||||
</a>
|
||||
<a href="#!/create">+ {{'Create ' | translate }} </a> <a href="#!/join">+ {{'Join' | translate }} </a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#!/" class="db p20h" title="Close"
|
||||
ng-click="signout()"><i class="size-21 m20r fi-power"></i> {{'Close'|translate}}</a>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
@ -70,10 +77,6 @@
|
|||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#!/" class="db p20h" title="Close"
|
||||
ng-click="signout()"><i class="size-21 m20r fi-power"></i> {{'Close'|translate}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div ng-show="$root.wallet.isShared()" ng-include="'views/includes/peer-list.html'"></div>
|
||||
|
|
148
views/join.html
148
views/join.html
|
@ -3,107 +3,77 @@
|
|||
<i class="size-60 fi-bitcoin-circle icon-rotate spinner"></i>
|
||||
<span translate>Connecting to Insight Wallet Server...</span>
|
||||
</div>
|
||||
<div class="row" ng-show="!loading">
|
||||
<div class="large-4 columns logo-setup">
|
||||
<img src="img/logo-negative-beta.svg" alt="Copay" width="146" height="59">
|
||||
<div ng-include="'views/includes/version.html'"></div>
|
||||
</div>
|
||||
<div class="large-8 columns">
|
||||
<div class="box-setup">
|
||||
<h1 translate class="text-primary line-sidebar-b">Join a Wallet in Creation</h1>
|
||||
<form name="joinForm" ng-submit="join(joinForm)" novalidate>
|
||||
|
||||
<label for="connectionId" class="m10b"><span translate>Wallet Secret</span>
|
||||
<small translate class="has-error" ng-show="joinForm.connectionId.$invalid
|
||||
<h1>{{'Join Wallet'|translate}}</h1>
|
||||
<div class="row collapse m0">
|
||||
<div class="large-6 columns">
|
||||
<div class="box-setup">
|
||||
<h1 translate class="text-primary line-sidebar-b">Join a Wallet in Creation</h1>
|
||||
<form name="joinForm" ng-submit="join(joinForm)" novalidate>
|
||||
|
||||
<label for="connectionId"><span translate>Wallet Secret</span>
|
||||
<small translate class="has-error" ng-show="joinForm.connectionId.$invalid
|
||||
&& !joinForm.connectionId.$pristine">Wallet Secret is not valid!</small>
|
||||
<small translate data-options="disable_for_touch:true"
|
||||
ng-show="joinForm.connectionId.$pristine" class="has-tip
|
||||
text-gray" tooltip="Paste wallet secret here" >Required</small>
|
||||
</label>
|
||||
|
||||
<div class="row collapse">
|
||||
<div class="large-10 medium-10 small-10 columns pr">
|
||||
<input id="connectionId" type="text" class="small-9 columns"
|
||||
placeholder="{{'Paste wallet secret here'|translate}}" name="connectionId" ng-model="connectionId" wallet-secret required>
|
||||
<small class="icon-input" ng-show="joinForm.connectionId.$invalid && !joinForm.connectionId.$pristine"><i class="fi-x"></i></small>
|
||||
<small class="icon-input" ng-show="joinForm.connectionId.$valid
|
||||
&& !joinForm.connectionId.$pristine"><i class="fi-check"></i></small>
|
||||
</div>
|
||||
<div class="small-2 columns" ng-hide="showScanner || disableScanner">
|
||||
<a class="postfix button primary" ng-click="openScanner()"><i class="fi-camera"> </i></a>
|
||||
</div>
|
||||
<div class="small-2 columns" ng-show="showScanner">
|
||||
<a class="postfix button warning" ng-click="cancelScanner()"><i class="fi-x"> </i></a>
|
||||
</div>
|
||||
</div>
|
||||
<small translate data-options="disable_for_touch:true" ng-show="joinForm.connectionId.$pristine" class="has-tip
|
||||
text-gray" tooltip="Paste wallet secret here">Required</small>
|
||||
</label>
|
||||
|
||||
<div id="scanner" class="row" ng-if="showScanner">
|
||||
<div class="text-centered">
|
||||
<canvas id="qr-canvas" width="200" height="150"></canvas>
|
||||
<div ng-show="isMobile">
|
||||
<div id="file-input-wrapper" class="btn btn-primary">
|
||||
<span class="pull-left text-centered">
|
||||
<div class="row collapse">
|
||||
<div class="large-10 medium-10 small-10 columns pr">
|
||||
<input id="connectionId" type="text" class="small-9 columns" placeholder="{{'Paste wallet secret here'|translate}}" name="connectionId" ng-model="connectionId" wallet-secret required>
|
||||
<small class="icon-input" ng-show="joinForm.connectionId.$invalid && !joinForm.connectionId.$pristine"><i class="fi-x"></i></small>
|
||||
<small class="icon-input" ng-show="joinForm.connectionId.$valid
|
||||
&& !joinForm.connectionId.$pristine"><i class="fi-check"></i></small>
|
||||
</div>
|
||||
<div class="small-2 columns" ng-hide="showScanner || disableScanner">
|
||||
<a class="postfix button primary" ng-click="openScanner()"><i class="fi-camera"> </i></a>
|
||||
</div>
|
||||
<div class="small-2 columns" ng-show="showScanner">
|
||||
<a class="postfix button warning" ng-click="cancelScanner()"><i class="fi-x"> </i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="scanner" class="row" ng-if="showScanner">
|
||||
<div class="text-centered">
|
||||
<canvas id="qr-canvas" width="200" height="150"></canvas>
|
||||
<div ng-show="isMobile">
|
||||
<div id="file-input-wrapper" class="btn btn-primary">
|
||||
<span class="pull-left text-centered">
|
||||
<i class="glyphicon glyphicon-refresh icon-rotate"></i>
|
||||
<span translate>Get QR code</span>
|
||||
</span>
|
||||
<input id="qrcode-camera" type="file" capture="camera" accept="image/*">
|
||||
</div>
|
||||
</div>
|
||||
<div ng-hide="isMobile">
|
||||
<video id="qrcode-scanner-video" width="300" height="225" ng-hide="isMobile"></video>
|
||||
</span>
|
||||
<input id="qrcode-camera" type="file" capture="camera" accept="image/*">
|
||||
</div>
|
||||
</div>
|
||||
<div ng-hide="isMobile">
|
||||
<video id="qrcode-scanner-video" width="300" height="225" ng-hide="isMobile"></video>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label translate for="joinPassword" class="m10b">User information</label>
|
||||
<input id="joinPassword" type="text" class="form-control"
|
||||
placeholder="{{'Your name'|translate}}" name="nickname"
|
||||
ng-model="nickname" required>
|
||||
<input type="password" class="form-control"
|
||||
placeholder="{{'Choose your password'|translate}}" name="joinPassword"
|
||||
ng-model="$parent.joinPassword"
|
||||
check-strength="passwordStrength"
|
||||
tooltip-html-unsafe="Password strength:
|
||||
<i>{{passwordStrength}}</i><br/><span class='size-12'>Tip: Use lower and uppercase,
|
||||
numbers and symbols</span>" tooltip-trigger="focus"
|
||||
tooltip-placement="top" required>
|
||||
<a class="expand small" ng-click="hideAdv=!hideAdv">
|
||||
<i class="fi-widget m3r"></i>
|
||||
<span translate ng-hide="!hideAdv">Show</span>
|
||||
<span translate ng-hide="hideAdv">Hide</span>
|
||||
<span translate>advanced options</span>
|
||||
</a>
|
||||
<div ng-hide="hideAdv" class="m10t">
|
||||
<p>
|
||||
<input type="text" placeholder="BIP32 master extended private key (hex)" name="private" ng-model="$parent.private">
|
||||
</div>
|
||||
|
||||
<div class="pr">
|
||||
<input type="password"
|
||||
placeholder="{{'Repeat password'|translate}}"
|
||||
name="joinPasswordConfirm"
|
||||
ng-model="joinPasswordConfirm"
|
||||
match="joinPassword" required>
|
||||
<small class="icon-input" ng-show="joinForm.joinPasswordConfirm.$dirty && joinForm.joinPasswordConfirm.$invalid"><i class="fi-x"></i></small>
|
||||
<p class="m15b text-gray size-12" ng-show="joinForm.joinPasswordConfirm.$dirty && joinForm.joinPasswordConfirm.$invalid">
|
||||
<i class="fi-x m5r"></i>
|
||||
{{'Passwords must match'|translate}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<button translate type="submit" class="button primary m0" ng-disabled="joinForm.$invalid || loading">Join</button>
|
||||
</div>
|
||||
|
||||
<a class="expand small" ng-click="hideAdv=!hideAdv">
|
||||
<i class="fi-widget m3r"></i>
|
||||
<span translate ng-hide="!hideAdv">Show</span>
|
||||
<span translate ng-hide="hideAdv">Hide</span>
|
||||
<span translate>advanced options</span>
|
||||
</a>
|
||||
<div ng-hide="hideAdv" class="m10t">
|
||||
<p>
|
||||
<input type="text"
|
||||
placeholder="BIP32 master extended private key (hex)"
|
||||
name="private"
|
||||
ng-model="$parent.private"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="text-right m20t">
|
||||
<a href="#!/" class="back-button text-primary m20r">« <span translate>Back</span></a>
|
||||
<button translate type="submit" class="button primary m0" ng-disabled="joinForm.$invalid || loading">Join</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- End !loading -->
|
||||
</div>
|
||||
<!-- End !loading -->
|
||||
</div>
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue