Merge pull request #2036 from matiu/bug/nativation/pin
Bug/nativation/pin
This commit is contained in:
commit
75b23e66bb
24 changed files with 199 additions and 145 deletions
|
|
@ -42,7 +42,7 @@ var defaultConfig = {
|
||||||
|
|
||||||
// local encryption/security config
|
// local encryption/security config
|
||||||
passphraseConfig: {
|
passphraseConfig: {
|
||||||
iterations: 1000,
|
iterations: 5000,
|
||||||
storageSalt: 'mjuBtGybi/4=',
|
storageSalt: 'mjuBtGybi/4=',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<widget id="com.bitpay.copay"
|
<widget id="com.bitpay.copay"
|
||||||
version="0.8.2"
|
version="0.8.3"
|
||||||
android-versionCode="17"
|
android-versionCode="17"
|
||||||
ios-CFBundleVersion="0.8.2">
|
ios-CFBundleVersion="0.8.3">
|
||||||
<name>Copay</name>
|
<name>Copay</name>
|
||||||
<description>
|
<description>
|
||||||
A secure bitcoin wallet for friends and companies.
|
A secure bitcoin wallet for friends and companies.
|
||||||
|
|
|
||||||
|
|
@ -57,11 +57,11 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>vRC0.9.0</string>
|
<string>0.8.3</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>vRC0.9.0</string>
|
<string>0.8.3</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSMainNibFile</key>
|
<key>NSMainNibFile</key>
|
||||||
|
|
|
||||||
12
index.html
12
index.html
|
|
@ -43,7 +43,7 @@
|
||||||
<p class="text-gray size-18">Your session is about to expire due to inactivity in {{countdown}} seconds</p>
|
<p class="text-gray size-18">Your session is about to expire due to inactivity in {{countdown}} seconds</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="off-canvas-wrap" ng-show="!signingOut">
|
<div class="off-canvas-wrap" id="off-canvas-wrap" ng-show="!signingOut">
|
||||||
<div class="inner-wrap">
|
<div class="inner-wrap">
|
||||||
<span class="status" ng-if="$root.reconnecting">
|
<span class="status" ng-if="$root.reconnecting">
|
||||||
<i class="fi-loop icon-rotate"></i>
|
<i class="fi-loop icon-rotate"></i>
|
||||||
|
|
@ -62,7 +62,7 @@
|
||||||
<section class="left-small">
|
<section class="left-small">
|
||||||
<a class="left-off-canvas-toggle menu-icon" ><span></span></a>
|
<a class="left-off-canvas-toggle menu-icon" ><span></span></a>
|
||||||
</section>
|
</section>
|
||||||
<section class="right-small" ng-if="$root.iden && $root.iden.listWallets().length >1">
|
<section class="right-small" ng-show="$root.iden && $root.iden.listWallets().length >1">
|
||||||
<a class="right-off-canvas-toggle p10"><i class="icon-wallet size-24"></i></a>
|
<a class="right-off-canvas-toggle p10"><i class="icon-wallet size-24"></i></a>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
@ -73,13 +73,13 @@
|
||||||
</section>
|
</section>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<aside class="left-off-canvas-menu">
|
<nav class="left-off-canvas-menu" ng-show="$root.iden">
|
||||||
<div ng-include="'views/includes/sidebar-mobile.html'"></div>
|
<div ng-include="'views/includes/sidebar-mobile.html'"></div>
|
||||||
</aside>
|
</nav>
|
||||||
|
|
||||||
<aside class="right-off-canvas-menu" ng-if="$root.iden && $root.iden.listWallets().length >1">
|
<nav class="right-off-canvas-menu" ng-show="$root.iden && $root.iden.listWallets().length >1">
|
||||||
<div ng-include="'views/includes/walletbar-mobile.html'"></div>
|
<div ng-include="'views/includes/walletbar-mobile.html'"></div>
|
||||||
</aside>
|
</nav>
|
||||||
<div
|
<div
|
||||||
ng-if="$root.iden"
|
ng-if="$root.iden"
|
||||||
ng-include="'views/includes/sidebar.html'"
|
ng-include="'views/includes/sidebar.html'"
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,9 @@ angular.module('copayApp.controllers').controller('CreateController',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$rootScope.$digest();
|
$timeout(function(){
|
||||||
|
$rootScope.$digest();
|
||||||
|
},1);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ angular.module('copayApp.controllers').controller('CreateProfileController', fun
|
||||||
$scope.userOrEmail = $scope.useLocalstorage ? form.username.$modelValue : form.email.$modelValue;
|
$scope.userOrEmail = $scope.useLocalstorage ? form.username.$modelValue : form.email.$modelValue;
|
||||||
preconditions.checkState($scope.userOrEmail);
|
preconditions.checkState($scope.userOrEmail);
|
||||||
|
|
||||||
|
$scope.error = null;
|
||||||
$scope.createStep = 'pass';
|
$scope.createStep = 'pass';
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$scope.$digest();
|
$scope.$digest();
|
||||||
|
|
@ -111,6 +112,7 @@ angular.module('copayApp.controllers').controller('CreateProfileController', fun
|
||||||
var msg = err.toString();
|
var msg = err.toString();
|
||||||
if (msg.indexOf('EEXIST') >= 0 || msg.indexOf('BADC') >= 0) {
|
if (msg.indexOf('EEXIST') >= 0 || msg.indexOf('BADC') >= 0) {
|
||||||
msg = 'This profile already exists'
|
msg = 'This profile already exists'
|
||||||
|
$scope.createStep = 'email';
|
||||||
}
|
}
|
||||||
$scope.error = msg;
|
$scope.error = msg;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -156,6 +158,8 @@ angular.module('copayApp.controllers').controller('CreateProfileController', fun
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$scope.saveSettings(function(err) {
|
$scope.saveSettings(function(err) {
|
||||||
|
preconditions.checkState(!err,err);
|
||||||
|
|
||||||
$scope._doCreateProfile($scope.userOrEmail, form.password.$modelValue, function(err) {
|
$scope._doCreateProfile($scope.userOrEmail, form.password.$modelValue, function(err) {
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
form.password.$setViewValue('');
|
form.password.$setViewValue('');
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ angular.module('copayApp.controllers').controller('HeadController', function($sc
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.signout = function() {
|
$scope.signout = function() {
|
||||||
$rootScope.signingOut = true;
|
|
||||||
identityService.signout();
|
identityService.signout();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('HomeController', function($scope, $rootScope, $location, $timeout, notification, identityService, Compatibility, pinService, applicationService, isMobile) {
|
angular.module('copayApp.controllers').controller('HomeController', function($scope, $rootScope, $timeout, go, notification, identityService, Compatibility, pinService, applicationService, isMobile) {
|
||||||
|
|
||||||
// Global functions (TODO should be somewhere else)
|
// Global go. This should be in a better place TODO
|
||||||
|
// We dont do a 'go' directive, to use the benefits of ng-touch with ng-click
|
||||||
$rootScope.go = function (path) {
|
$rootScope.go = function (path) {
|
||||||
$location.path(path);
|
go.go(path);
|
||||||
};
|
};
|
||||||
|
|
||||||
var _credentials, _firstpin;
|
var _credentials, _firstpin;
|
||||||
|
|
@ -66,13 +67,14 @@ angular.module('copayApp.controllers').controller('HomeController', function($sc
|
||||||
$scope.error = 'Please enter the required fields';
|
$scope.error = 'Please enter the required fields';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
$rootScope.starting = true;
|
||||||
|
|
||||||
var credentials = pinService.get(pin, function(err, credentials) {
|
var credentials = pinService.get(pin, function(err, credentials) {
|
||||||
if (err || !credentials) {
|
if (err || !credentials) {
|
||||||
|
$rootScope.starting = false;
|
||||||
$scope.error = 'Wrong PIN';
|
$scope.error = 'Wrong PIN';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$rootScope.starting = true;
|
|
||||||
$scope.open(credentials.email, credentials.password);
|
$scope.open(credentials.email, credentials.password);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -114,7 +116,7 @@ angular.module('copayApp.controllers').controller('HomeController', function($sc
|
||||||
pinService.clear(function() {
|
pinService.clear(function() {
|
||||||
copay.logger.debug('PIN erased');
|
copay.logger.debug('PIN erased');
|
||||||
delete $rootScope['hasPin'];
|
delete $rootScope['hasPin'];
|
||||||
applicationService.reload();
|
applicationService.restart();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -162,7 +164,9 @@ angular.module('copayApp.controllers').controller('HomeController', function($sc
|
||||||
$scope.askForPin = 1;
|
$scope.askForPin = 1;
|
||||||
$rootScope.starting = false;
|
$rootScope.starting = false;
|
||||||
$rootScope.hideNavigation = true;
|
$rootScope.hideNavigation = true;
|
||||||
$rootScope.$digest();
|
$timeout(function(){
|
||||||
|
$rootScope.$digest();
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// no mobile
|
// no mobile
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ angular.module('copayApp.controllers').controller('SettingsController', function
|
||||||
name: 'In the cloud (Insight server)',
|
name: 'In the cloud (Insight server)',
|
||||||
pluginName: 'EncryptedInsightStorage',
|
pluginName: 'EncryptedInsightStorage',
|
||||||
}, {
|
}, {
|
||||||
name: 'In this device (localstorage)',
|
name: 'On this device (localstorage)',
|
||||||
pluginName: 'EncryptedLocalStorage',
|
pluginName: 'EncryptedLocalStorage',
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ angular.module('copayApp.controllers').controller('SidebarController', function(
|
||||||
}];
|
}];
|
||||||
|
|
||||||
$scope.signout = function() {
|
$scope.signout = function() {
|
||||||
$rootScope.signingOut = true;
|
|
||||||
identityService.signout();
|
identityService.signout();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
14
js/init.js
14
js/init.js
|
|
@ -1,13 +1,21 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.element(document).ready(function() {
|
angular.element(document).ready(function() {
|
||||||
var startAngular = function () {
|
var startAngular = function() {
|
||||||
angular.bootstrap(document, ['copayApp']);
|
angular.bootstrap(document, ['copayApp']);
|
||||||
};
|
};
|
||||||
|
/* Cordova specific Init */
|
||||||
if (window.cordova !== undefined) {
|
if (window.cordova !== undefined) {
|
||||||
|
|
||||||
document.addEventListener('deviceready', function() {
|
document.addEventListener('deviceready', function() {
|
||||||
setTimeout(function(){ navigator.splashscreen.hide(); }, 2000);
|
|
||||||
|
document.addEventListener('pause', function() {
|
||||||
|
window.location = '#!';
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
navigator.splashscreen.hide();
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
function handleBitcoinURI(url) {
|
function handleBitcoinURI(url) {
|
||||||
if (!url) return;
|
if (!url) return;
|
||||||
|
|
|
||||||
11
js/routes.js
11
js/routes.js
|
|
@ -113,16 +113,17 @@ angular
|
||||||
$idleProvider.warningDuration(40); // in seconds
|
$idleProvider.warningDuration(40); // in seconds
|
||||||
$keepaliveProvider.interval(30); // in seconds
|
$keepaliveProvider.interval(30); // in seconds
|
||||||
})
|
})
|
||||||
.run(function($rootScope, $location, $idle, gettextCatalog, uriHandler) {
|
.run(function($rootScope, $location, $idle, gettextCatalog, uriHandler, isCordova) {
|
||||||
|
|
||||||
gettextCatalog.currentLanguage = config.defaultLanguage;
|
gettextCatalog.currentLanguage = config.defaultLanguage;
|
||||||
// not for mobileApp
|
|
||||||
if (!window.cordova) {
|
// Register URI handler, not for mobileApp
|
||||||
|
if (!isCordova) {
|
||||||
$idle.watch();
|
$idle.watch();
|
||||||
uriHandler.register();
|
uriHandler.register();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rootScope.$on('$routeChangeStart', function(event, next, current) {
|
$rootScope.$on('$routeChangeStart', function(event, next, current) {
|
||||||
|
|
||||||
|
|
||||||
if (!ls || ls.length < 1) {
|
if (!ls || ls.length < 1) {
|
||||||
$location.path('unsupported');
|
$location.path('unsupported');
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,27 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
angular.module('copayApp.services')
|
angular.module('copayApp.services')
|
||||||
.factory('applicationService', function() {
|
.factory('applicationService', function($rootScope, $location, $timeout, go, isCordova) {
|
||||||
var root = {};
|
var root = {};
|
||||||
var isChromeApp = window.chrome && chrome.runtime && chrome.runtime.id;
|
var isChromeApp = window.chrome && chrome.runtime && chrome.runtime.id;
|
||||||
|
|
||||||
root.restart = function() {
|
root.restart = function() {
|
||||||
|
if (isCordova) {
|
||||||
// Go home reloading the application
|
$rootScope.iden = $rootScope.wallet = undefined;
|
||||||
var hashIndex = window.location.href.indexOf('#!/');
|
go.go('/');
|
||||||
if (isChromeApp) {
|
$timeout(function(){
|
||||||
chrome.runtime.reload();
|
$rootScope.$digest();
|
||||||
|
},1);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
window.location = window.location.href.substr(0, hashIndex);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
root.reload = function() {
|
// Go home reloading the application
|
||||||
window.location.reload();
|
var hashIndex = window.location.href.indexOf('#!/');
|
||||||
|
if (isChromeApp) {
|
||||||
|
chrome.runtime.reload();
|
||||||
|
} else {
|
||||||
|
window.location = window.location.href.substr(0, hashIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
|
|
|
||||||
26
js/services/go.js
Normal file
26
js/services/go.js
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('copayApp.services').factory('go', function($window, $location) {
|
||||||
|
var root = {};
|
||||||
|
|
||||||
|
var hideSidebars = function() {
|
||||||
|
if (typeof document === 'undefined')
|
||||||
|
return;
|
||||||
|
|
||||||
|
// hack to hide sidebars and use ng-click (no href=)
|
||||||
|
var win = angular.element($window);
|
||||||
|
var elem = angular.element(document.querySelector('#off-canvas-wrap'))
|
||||||
|
elem.removeClass('move-right');
|
||||||
|
elem.removeClass('move-left');
|
||||||
|
};
|
||||||
|
|
||||||
|
root.go = function(path) {
|
||||||
|
var parts = path.split('#');
|
||||||
|
$location.path(parts[0]);
|
||||||
|
if (parts[1])
|
||||||
|
$location.hash(parts[1]);
|
||||||
|
hideSidebars();
|
||||||
|
};
|
||||||
|
|
||||||
|
return root;
|
||||||
|
});
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
angular.module('copayApp.services')
|
angular.module('copayApp.services')
|
||||||
.factory('identityService', function($rootScope, $location, $timeout, $filter, pluginManager, notification, pendingTxsService, balanceService, applicationService) {
|
.factory('identityService', function($rootScope, $location, $timeout, $filter, pluginManager, notification, pendingTxsService, balanceService, applicationService, go) {
|
||||||
notification.enableHtml5Mode(); // for chrome: if support, enable it
|
notification.enableHtml5Mode(); // for chrome: if support, enable it
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
|
|
@ -328,11 +328,13 @@ angular.module('copayApp.services')
|
||||||
};
|
};
|
||||||
|
|
||||||
root.signout = function() {
|
root.signout = function() {
|
||||||
|
$rootScope.signingOut = true;
|
||||||
if ($rootScope.iden) {
|
if ($rootScope.iden) {
|
||||||
$rootScope.iden.store({
|
$rootScope.iden.store({
|
||||||
noWallets: true
|
noWallets: true
|
||||||
}, function() {
|
}, function() {
|
||||||
$rootScope.iden.close();
|
$rootScope.signingOut = false;
|
||||||
|
$rootScope.iden.close(); // Will trigger 'closed'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
3
js/services/isCordova.js
Normal file
3
js/services/isCordova.js
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('copayApp.services').value('isCordova', window.cordova ? true : false);
|
||||||
|
|
@ -5,7 +5,7 @@ angular.module('copayApp.services')
|
||||||
|
|
||||||
var KEY = 'pinDATA';
|
var KEY = 'pinDATA';
|
||||||
var SALT = '4gllotIKguqi0EkIslC0';
|
var SALT = '4gllotIKguqi0EkIslC0';
|
||||||
var ITER = 2000;
|
var ITER = 5000;
|
||||||
|
|
||||||
var ls = localstorageService;
|
var ls = localstorageService;
|
||||||
var root = {};
|
var root = {};
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ module.exports = {
|
||||||
try {
|
try {
|
||||||
return sjcl.decrypt(key, sjclEncryptedJson);
|
return sjcl.decrypt(key, sjclEncryptedJson);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.info('Decryption failed due to error: ' + e.message);
|
log.debug('Decryption failed due to error: ' + e.message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "copay",
|
"name": "copay",
|
||||||
"description": "A multisignature wallet",
|
"description": "A multisignature wallet",
|
||||||
"author": "BitPay",
|
"author": "BitPay",
|
||||||
"version": "0.8.2",
|
"version": "0.8.3",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"wallet",
|
"wallet",
|
||||||
"copay",
|
"copay",
|
||||||
|
|
@ -41,7 +41,8 @@
|
||||||
"setup-shell": "node shell/scripts/download-atom-shell.js",
|
"setup-shell": "node shell/scripts/download-atom-shell.js",
|
||||||
"postinstall": "./node_modules/.bin/grunt",
|
"postinstall": "./node_modules/.bin/grunt",
|
||||||
"sign": "gpg -u 1112CFA1 --output browser-extensions/firefox/copay.xpi.sig --detach-sig browser-extensions/firefox/copay.xpi; gpg -u 1112CFA1 --output browser-extensions/chrome/copay-chrome-extension.zip.sig --detach-sig browser-extensions/chrome/copay-chrome-extension.zip",
|
"sign": "gpg -u 1112CFA1 --output browser-extensions/firefox/copay.xpi.sig --detach-sig browser-extensions/firefox/copay.xpi; gpg -u 1112CFA1 --output browser-extensions/chrome/copay-chrome-extension.zip.sig --detach-sig browser-extensions/chrome/copay-chrome-extension.zip",
|
||||||
"verify": "gpg --verify browser-extensions/firefox/copay.xpi.sig browser-extensions/firefox/copay.xpi; gpg --verify browser-extensions/chrome/copay-chrome-extension.zip.sig browser-extensions/chrome/copay-chrome-extension.zip"
|
"verify": "gpg --verify browser-extensions/firefox/copay.xpi.sig browser-extensions/firefox/copay.xpi; gpg --verify browser-extensions/chrome/copay-chrome-extension.zip.sig browser-extensions/chrome/copay-chrome-extension.zip",
|
||||||
|
"ios": "cordova/build.sh && cd cordova/project && cordova build ios && open platforms/ios/Copay.xcodeproj"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"angular-gravatar": "*",
|
"angular-gravatar": "*",
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ describe('crypto utils', function() {
|
||||||
});
|
});
|
||||||
it('should generate a passphrase using default salt/iter', function() {
|
it('should generate a passphrase using default salt/iter', function() {
|
||||||
var phrase = cryptoUtils.kdf('Pwd123!@#$%^&*(){}[]\|/?.>,<=+-_`~åéþ䲤þçæ¶');
|
var phrase = cryptoUtils.kdf('Pwd123!@#$%^&*(){}[]\|/?.>,<=+-_`~åéþ䲤þçæ¶');
|
||||||
var expected = 'ml+mMtjgcvL2pdfDwQqW2qONRNjZ3YD8KnGeV3aFjyOoM0ByOmoREw9zBvowC/ZXsfrezbRXX/W/XIzKOqdrXA==';
|
var expected = 'n9QYDBJvRCHfpAfp8X/Z1XDA00CnZtnehLKOVrtNYTLt9H+hlcyaZgbAGGgJ/dVRCsVtIBzYwaACNPckknMiCg==';
|
||||||
phrase.should.equal(expected);
|
phrase.should.equal(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,34 @@
|
||||||
<div class="large-5 large-centered medium-6 medium-centered columns m20b" ng-show="!loading && !askForPin">
|
<div class="large-5 large-centered medium-6 medium-centered columns m20b" ng-show="!loading && !askForPin">
|
||||||
<div class="logo-setup hide-for-small-only">
|
<div class="logo-setup hide-for-small-only">
|
||||||
<img src="img/logo-negative-beta.svg" alt="Copay" width="100">
|
<img src="img/logo-negative-beta.svg" alt="Copay" width="100">
|
||||||
<div ng-include="'views/includes/version.html'"></div>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
|
<div class="clipo" ng-show="createStep == 'storage' ">
|
||||||
|
<img src="img/clipo-signup1.png" alt="clipo" width="311">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-show="createStep == 'email'">
|
||||||
|
<div class="clipo" ng-if="useLocalstorage">
|
||||||
|
<img src="img/clipo-signup2-1.png" alt="clipo" width="373">
|
||||||
|
</div>
|
||||||
|
<div class="clipo" ng-if="!useLocalstorage">
|
||||||
|
<img src="img/clipo-signup2.png" alt="clipo" width="373">
|
||||||
|
</div>
|
||||||
|
<h2 ng-if="!useLocalstorage"> Creating in the cloud </h2>
|
||||||
|
<h2 ng-if="useLocalstorage"> Creating on this device </h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-show="createStep == 'pass'">
|
||||||
|
<div class="clipo">
|
||||||
|
<img src="img/clipo-signup3.png" alt="clipo" width="380">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 ng-if="useLocalstorage"> Creating on this device </h2>
|
||||||
|
<h2 ng-if="!useLocalstorage"> Creating in the cloud </h2>
|
||||||
|
<div class="text-gray text-center m20b">{{userOrEmail}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="box-notification" ng-show="error">
|
<div class="box-notification" ng-show="error">
|
||||||
<div class="box-icon error">
|
<div class="box-icon error">
|
||||||
<i class="fi-x size-24"></i>
|
<i class="fi-x size-24"></i>
|
||||||
|
|
@ -37,54 +62,52 @@
|
||||||
|
|
||||||
|
|
||||||
<form ng-show="createStep == 'storage' " novalidate>
|
<form ng-show="createStep == 'storage' " novalidate>
|
||||||
<div class="clipo">
|
|
||||||
<img src="img/clipo-signup1.png" alt="clipo" width="311">
|
|
||||||
</div>
|
|
||||||
<tabset>
|
<tabset>
|
||||||
<tab style="width: 50%;" select="selectStorage('remote')">
|
<tab style="width: 50%;" select="selectStorage('remote')">
|
||||||
<tab-heading>
|
<tab-heading>
|
||||||
<span class="text-bold">In the Cloud </span><br>
|
<span class="text-bold">In the Cloud </span>
|
||||||
|
<br>
|
||||||
<span class="size-10 text-gray">( Recommended )</span>
|
<span class="size-10 text-gray">( Recommended )</span>
|
||||||
</tab-heading>
|
</tab-heading>
|
||||||
<div class="content-item">
|
<div class="content-item">
|
||||||
<div class="bg-circle"><i class="icon-wallet"></i>
|
<div class="bg-circle"><i class="icon-wallet"></i>
|
||||||
</div>
|
|
||||||
<span class="text-gray">Access your wallets anywhere</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="content-item">
|
<span class="text-gray">Access your wallets anywhere</span>
|
||||||
<div class="bg-circle"><i class="icon-download"></i>
|
</div>
|
||||||
</div>
|
<div class="content-item">
|
||||||
<span class="text-gray">Backups managed by the server</span>
|
<div class="bg-circle"><i class="icon-download"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="content-item line-none">
|
<span class="text-gray">Backups managed by the server</span>
|
||||||
<div class="bg-circle"><i class="icon-email"></i>
|
</div>
|
||||||
</div>
|
<div class="content-item line-none">
|
||||||
<span class="text-gray">Email address confirmation needed</span>
|
<div class="bg-circle"><i class="icon-email"></i>
|
||||||
</div>
|
</div>
|
||||||
|
<span class="text-gray">Email address confirmation needed</span>
|
||||||
|
</div>
|
||||||
</tab>
|
</tab>
|
||||||
<tab style="width: 50%;" select="selectStorage('local')">
|
<tab style="width: 50%;" select="selectStorage('local')">
|
||||||
<tab-heading>
|
<tab-heading>
|
||||||
<div class="m5t text-bold">On this Device </div>
|
<div class="m5t text-bold">On this Device</div>
|
||||||
</tab-heading>
|
</tab-heading>
|
||||||
<div class="content-item">
|
<div class="content-item">
|
||||||
<div class="bg-circle"><i class="icon-locked"></i>
|
<div class="bg-circle"><i class="icon-locked"></i>
|
||||||
</div>
|
|
||||||
<span class="text-gray">Your private keys never leave this device</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="content-item">
|
<span class="text-gray">Your private keys never leave this device</span>
|
||||||
<div class="bg-circle"><i class="icon-person"></i>
|
</div>
|
||||||
</div>
|
<div class="content-item">
|
||||||
<span class="text-gray">No email required</span>
|
<div class="bg-circle"><i class="icon-person"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="content-item line-none">
|
<span class="text-gray">No email required</span>
|
||||||
<div class="bg-circle"><i class="icon-download"></i>
|
</div>
|
||||||
</div>
|
<div class="content-item line-none">
|
||||||
<span class="text-gray">Need to be careful with backups</span>
|
<div class="bg-circle"><i class="icon-download"></i>
|
||||||
</div>
|
</div>
|
||||||
|
<span class="text-gray">Need to be careful with backups</span>
|
||||||
|
</div>
|
||||||
</tab>
|
</tab>
|
||||||
</tabset>
|
</tabset>
|
||||||
|
|
||||||
<button translate class="button primary radius expand m0" ng-click="goToEmail()">
|
<button translate class="button primary radius expand m0" ng-click="goToEmail()">
|
||||||
<span ng-if="!useLocalstorage"> Create in the cloud</span>
|
<span ng-if="!useLocalstorage"> Create in the cloud</span>
|
||||||
<span ng-if="useLocalstorage"> Create on this device</span>
|
<span ng-if="useLocalstorage"> Create on this device</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -97,25 +120,14 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<a class="text-gray" href="https://copay.io/profile-storage"
|
<a class="text-gray" href="https://copay.io/profile-storage" <span translate>Learn more about this option</span>
|
||||||
<span translate>Learn more about this option</span>
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<form ng-show="createStep == 'email'" name="emailForm" ng-submit="setEmailOrUsername(emailForm)" novalidate>
|
<form ng-show="createStep == 'email'" name="emailForm" ng-submit="setEmailOrUsername(emailForm)" novalidate>
|
||||||
<div class="clipo" ng-if="useLocalstorage">
|
|
||||||
<img src="img/clipo-signup2-1.png" alt="clipo" width="373">
|
|
||||||
</div>
|
|
||||||
<div class="clipo" ng-if="!useLocalstorage">
|
|
||||||
<img src="img/clipo-signup2.png" alt="clipo" width="373">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 ng-if="!useLocalstorage"> Creating in the cloud </h2>
|
|
||||||
<h2 ng-if="useLocalstorage"> Creating on this device </h2>
|
|
||||||
|
|
||||||
<div class="input" ng-if="useEmail">
|
<div class="input" ng-if="useEmail">
|
||||||
<input type="email" ng-model="email" class="form-control fi-email" name="email" placeholder="Email" required auto-focus="!isMobile">
|
<input type="email" ng-model="email" class="form-control fi-email" name="email" placeholder="Email" required auto-focus="!isMobile">
|
||||||
<i class="icon-email"></i>
|
<i class="icon-email"></i>
|
||||||
|
|
@ -128,7 +140,8 @@
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
<div class="" ng-show="!emailForm.email.$invalid &&
|
<div class="" ng-show="!emailForm.email.$invalid &&
|
||||||
!emailForm.email.$pristine"><i class="fi-check"></i></div>
|
!emailForm.email.$pristine"><i class="fi-check"></i>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -139,9 +152,7 @@
|
||||||
|
|
||||||
<button translate type="submit" class="button primary radius expand m0" ng-disabled="(useEmail && emailForm.email.$invalid) || (!useEmail && emailForm.username.$invalid)">
|
<button translate type="submit" class="button primary radius expand m0" ng-disabled="(useEmail && emailForm.email.$invalid) || (!useEmail && emailForm.username.$invalid)">
|
||||||
Next
|
Next
|
||||||
</button
|
</button>
|
||||||
|
|
||||||
>
|
|
||||||
<div class="box-setup-footer">
|
<div class="box-setup-footer">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<a class="text-gray" ng-click="setStep('storage')">
|
<a class="text-gray" ng-click="setStep('storage')">
|
||||||
|
|
@ -150,19 +161,10 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<form ng-show="createStep == 'pass'" name="passForm" ng-submit="createProfile(passForm)" novalidate>
|
<form ng-show="createStep == 'pass'" name="passForm" ng-submit="createProfile(passForm)" novalidate>
|
||||||
<div class="clipo">
|
|
||||||
<img src="img/clipo-signup3.png" alt="clipo" width="380">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 ng-if="useLocalstorage"> Creating on this device </h2>
|
|
||||||
<h2 ng-if="!useLocalstorage"> Creating in the cloud </h2>
|
|
||||||
<div class="text-gray text-center m20b"> {{userOrEmail}} </div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<input id="password" type="password" ng-model="$parent.password" class="form-control" name="password" placeholder="{{'Choose a password'|translate}}" check-strength="passwordStrength" tooltip-html-unsafe="Password strength: <b>{{passwordStrength}}</b><br/><span class='size-12'>Tip: Use lower and uppercase, numbers and symbols</span>" tooltip-trigger="focus" required tooltip-placement="top">
|
<input id="password" type="password" ng-model="$parent.password" class="form-control" name="password" placeholder="{{'Choose a password'|translate}}" check-strength="passwordStrength" tooltip-html-unsafe="Password strength: <b>{{passwordStrength}}</b><br/><span class='size-12'>Tip: Use lower and uppercase, numbers and symbols</span>" tooltip-trigger="focus" required tooltip-placement="top">
|
||||||
<i class="icon-locked"></i>
|
<i class="icon-locked"></i>
|
||||||
|
|
@ -180,7 +182,8 @@
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
<div class="" ng-show="passForm.repeatpassword.$dirty &&
|
<div class="" ng-show="passForm.repeatpassword.$dirty &&
|
||||||
!passForm.repeatpassword.$invalid"><i class="fi-check"></i></div>
|
!passForm.repeatpassword.$invalid"><i class="fi-check"></i>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -202,45 +205,43 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="large-4 large-centered medium-6 medium-centered columns m20b" ng-show="!loading && askForPin">
|
<div class="large-4 large-centered medium-6 medium-centered columns m20b" ng-show="!loading && askForPin">
|
||||||
<div class="box-setup">
|
<h2><span translate>Set up a </span> <b> PIN </b>?</h2>
|
||||||
<h1><span translate>Set up a </span> <b> PIN </b>?</h1>
|
<p class="size-14 text-gray">Enter a 4-digit number for easier access from this device</p>
|
||||||
<p class="size-14">Enter a 4-digit number for easier access from this device</p>
|
|
||||||
|
|
||||||
<div class="box-notification" ng-show="error">
|
<div class="box-notification" ng-show="error">
|
||||||
<div class="box-icon error">
|
<div class="box-icon error">
|
||||||
<i class="fi-x size-24"></i>
|
<i class="fi-x size-24"></i>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-warning size-14">
|
<span class="text-warning size-14">
|
||||||
{{error|translate}}
|
{{error|translate}}
|
||||||
</span>
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form name="setPinForm" ng-submit="createPin(setPinForm)" novalidate>
|
||||||
|
<div class="input" ng-show="askForPin == 1">
|
||||||
|
<input id="newpin" type="tel" ng-model="newpin" class="form-control" ng-maxlength="4" ng-minlength="4" maxlength="4" ng-pattern="/^[0-9]{1,4}$/" placeholder="PIN" name="newpin" required show-focus="askForPin == 1">
|
||||||
|
<i class="icon-locked"></i>
|
||||||
|
</div>
|
||||||
|
<div class="input" ng-show="askForPin == 2">
|
||||||
|
<input id="repeatpin" type="tel" ng-model="repeatpin" class="form-control" ng-maxlength="4" ng-minlength="4" maxlength="4" ng-pattern="/^[0-9]{1,4}$/" placeholder="Confirm your PIN" name="repeatpin" required show-focus="askForPin == 2">
|
||||||
|
<i class="icon-locked"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form name="setPinForm" ng-submit="createPin(setPinForm)" novalidate>
|
<div class="box-setup-footer row collapse">
|
||||||
<div class="input" ng-show="askForPin == 1">
|
<div class="large-6 medium-6 small-6 columns">
|
||||||
<input id="newpin" type="tel" ng-model="newpin" class="form-control" ng-maxlength="4" ng-minlength="4" maxlength="4" ng-pattern="/^[0-9]{1,4}$/" placeholder="PIN" name="newpin" required show-focus="askForPin == 1">
|
<a class="button secondary radius m0" ng-click="createDefaultWallet()">
|
||||||
<i class="icon-locked"></i>
|
<span translate>Skip</span>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="input" ng-show="askForPin == 2">
|
<div class="large-6 medium-6 small-6 columns text-right">
|
||||||
<input id="repeatpin" type="tel" ng-model="repeatpin" class="form-control" ng-maxlength="4" ng-minlength="4" maxlength="4" ng-pattern="/^[0-9]{1,4}$/" placeholder="Confirm your PIN" name="repeatpin" required show-focus="askForPin == 2">
|
<button translate type="submit" class="button primary radius expand m0" ng-disabled="setPinForm.$invalid || error">
|
||||||
<i class="icon-locked"></i>
|
OK
|
||||||
</div>
|
</button>
|
||||||
|
|
||||||
<div class="box-setup-footer row collapse">
|
|
||||||
<div class="large-6 medium-6 small-6 columns">
|
|
||||||
<a class="button secondary radius m0" ng-click="createDefaultWallet()">
|
|
||||||
<span translate>Skip</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="large-6 medium-6 small-6 columns text-right">
|
|
||||||
<button translate type="submit" class="button primary radius expand m0" ng-disabled="setPinForm.$invalid || error">
|
|
||||||
OK
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
<div class="large-5 large-centered medium-7 medium-centered columns" ng-show="!$root.starting">
|
<div class="large-5 large-centered medium-7 medium-centered columns" ng-show="!$root.starting">
|
||||||
<div class="logo-setup" ng-show="!$root.iden">
|
<div class="logo-setup" ng-show="!$root.iden">
|
||||||
<img src="img/logo-negative-beta.svg" alt="Copay" width="100">
|
<img src="img/logo-negative-beta.svg" alt="Copay" width="100">
|
||||||
<div ng-include="'views/includes/version.html'"></div>
|
<div class="text-gray" ng-include="'views/includes/version.html'"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="p10 box-setup bg-success m10b text-white" ng-show="confirmedEmail">
|
<div class="p10 box-setup bg-success m10b text-white" ng-show="confirmedEmail">
|
||||||
|
|
@ -115,7 +115,6 @@
|
||||||
<div class="clipo">
|
<div class="clipo">
|
||||||
<img src="img/clipo-signin.png" alt="clipo" width="310">
|
<img src="img/clipo-signin.png" alt="clipo" width="310">
|
||||||
</div>
|
</div>
|
||||||
<h2 translate>Sign in to Copay</h2>
|
|
||||||
<div class="p10 m20b size-14 box-setup bg-success text-white" ng-show="anyWallet && !confirmedEmail && !error">
|
<div class="p10 m20b size-14 box-setup bg-success text-white" ng-show="anyWallet && !confirmedEmail && !error">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<i class="size-36 fi-alert m10r"></i>
|
<i class="size-36 fi-alert m10r"></i>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<div>
|
<div>
|
||||||
<ul class="off-canvas-list">
|
<ul class="off-canvas-list">
|
||||||
<li>
|
<li>
|
||||||
<a href="#!/profile" class="db p20h nav-item text-center" title="Create new wallet">
|
<a ng-click="$root.go('profile')" class="db p20h nav-item text-center" title="Create new wallet">
|
||||||
<div class="photo-container m20t">
|
<div class="photo-container m20t">
|
||||||
<img gravatar-src="'{{$root.iden.getName()}}'" gravatar-size="35">
|
<img gravatar-src="'{{$root.iden.getName()}}'" gravatar-size="35">
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -14,23 +14,23 @@
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#!/create" class="db p20h nav-item" title="Create new wallet">
|
<a ng-click="$root.go('create')" class="db p20h nav-item" title="Create new wallet">
|
||||||
<i class="size-24 m20r fi-plus"></i> {{'Create new wallet' | translate }}</a>
|
<i class="size-24 m20r fi-plus"></i> {{'Create new wallet' | translate }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#!/join" class="db p20h nav-item" title="Join shared wallet">
|
<a ng-click="$root.go('join')" class="db p20h nav-item" title="Join shared wallet">
|
||||||
<i class="size-24 m20r fi-torsos-all"></i> {{'Join shared wallet' | translate }}</a>
|
<i class="size-24 m20r fi-torsos-all"></i> {{'Join shared wallet' | translate }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#!/import" class="db p20h nav-item" title="Import wallet">
|
<a ng-click="$root.go('import')" class="db p20h nav-item" title="Import wallet">
|
||||||
<i class="size-24 m20r fi-download"></i> {{'Import a wallet' | translate }}</a>
|
<i class="size-24 m20r fi-download"></i> {{'Import a wallet' | translate }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li ng-if="$root.wallet">
|
<li ng-if="$root.wallet">
|
||||||
<a href="#!/more" class="db p20h nav-item" title="Settings">
|
<a ng-click="$root.go('more')" class="db p20h nav-item" title="Settings">
|
||||||
<i class="size-24 m20r fi-widget"></i> {{'Wallet Settings' | translate }}</a>
|
<i class="size-24 m20r fi-widget"></i> {{'Wallet Settings' | translate }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#!/" class="db p20h nav-item" title="Close" ng-click="signout()">
|
<a class="db p20h nav-item" title="Close" ng-click="signout()">
|
||||||
<span ng-if="!$root.hasPin"><i class="size-24 m20r fi-power"></i> {{'Close'|translate}}</span>
|
<span ng-if="!$root.hasPin"><i class="size-24 m20r fi-power"></i> {{'Close'|translate}}</span>
|
||||||
<span ng-if="$root.hasPin"><i class="size-24 m20r fi-lock"></i> {{'Lock'|translate}}</span>
|
<span ng-if="$root.hasPin"><i class="size-24 m20r fi-lock"></i> {{'Lock'|translate}}</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
<div class="avatar-wallet">{{(item.name || item.id) | limitTo: 1}}</div>
|
<div class="avatar-wallet">{{(item.name || item.id) | limitTo: 1}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col2">
|
<div class="col2">
|
||||||
<a href="#!/homeWallet#{{item.id}}" class="size-12 wallet-item">
|
<a ng-click="$root.go('/homeWallet#{{item.id}}')" class="size-12 wallet-item">
|
||||||
<div class="oh">
|
<div class="oh">
|
||||||
<div class="right size-10 type-wallet">
|
<div class="right size-10 type-wallet">
|
||||||
[ {{item.requiredCopayers}} of {{item.totalCopayers}} ]</div>
|
[ {{item.requiredCopayers}} of {{item.totalCopayers}} ]</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue