@@ -211,41 +186,38 @@
ng-submit="bitpayCard.sendFunds()"
novalidate>
-
diff --git a/public/views/buyAndSell.html b/public/views/buyAndSell.html
index 597a8c73c..03e1e09c9 100644
--- a/public/views/buyAndSell.html
+++ b/public/views/buyAndSell.html
@@ -2,7 +2,7 @@
Buy and sell
@@ -10,11 +10,11 @@
-
+
-
+
diff --git a/public/views/includes/menu-toggle.html b/public/views/includes/menu-toggle.html
deleted file mode 100644
index dcb1b5cff..000000000
--- a/public/views/includes/menu-toggle.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/public/views/modals/bitpay-card-confirmation.html b/public/views/modals/bitpay-card-confirmation.html
index 6d6160bb4..5cb65067c 100644
--- a/public/views/modals/bitpay-card-confirmation.html
+++ b/public/views/modals/bitpay-card-confirmation.html
@@ -1,18 +1,20 @@
-
-
-
-
Are you sure you would like to log out of your Bitpay Card account?
-
You will need to log back for fill in your Bitpay Card.
-
-
+
+
+
+
Are you sure you would like to log out of your Bitpay Card account?
+
You will need to log back for fill in your Bitpay Card.
+
+
+
+
+
+
+
+
-
-
-
-
-
+
diff --git a/public/views/preferencesBitpayCard.html b/public/views/preferencesBitpayCard.html
index 01551563a..b281f8fcb 100644
--- a/public/views/preferencesBitpayCard.html
+++ b/public/views/preferencesBitpayCard.html
@@ -1,19 +1,19 @@
-
-
+
+
+
+
+
+ Preferences
+
-
-
diff --git a/public/views/tab-home.html b/public/views/tab-home.html
index 1b1d41471..5fbb422c2 100644
--- a/public/views/tab-home.html
+++ b/public/views/tab-home.html
@@ -3,7 +3,7 @@
Home
-
+
Payment Proposals
@@ -56,12 +56,10 @@
-
-
-
- -
+
+
{{item.name || item.id}}
@@ -74,27 +72,23 @@
{{item.status.availableBalanceStr}}
-
-
+
Next steps
- -
+
-
BitPay Card
- -
+
-
Buy and Sell
- -
+
-
Gift Cards
-
- bla bla
-
diff --git a/src/js/controllers/bitpayCard.js b/src/js/controllers/bitpayCard.js
index e4d35f8f0..4e1897d28 100644
--- a/src/js/controllers/bitpayCard.js
+++ b/src/js/controllers/bitpayCard.js
@@ -5,8 +5,7 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi
var self = this;
var client;
- var network = 'livenet';
- self.sandbox = network == 'testnet' ? true : false;
+ self.sandbox = bitpayCardService.getEnvironment() == 'testnet' ? true : false;
if (platformInfo.isCordova && StatusBar.isVisible) {
StatusBar.backgroundColorByHexString("#293C92");
@@ -71,7 +70,6 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi
this.update = function() {
var dateRange = setDateRange($scope.dateRange);
self.loadingSession = true;
- bitpayCardService.setCredentials(network);
bitpayCardService.isAuthenticated(function(err, bpSession) {
self.loadingSession = false;
if (err) {
@@ -110,14 +108,16 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi
$scope.dateRange = 'last30Days';
self.update();
- self.allWallets = profileService.getWallets(network);
- client = profileService.focusedClient;
-
- if (!client) return;
+ var network = bitpayCardService.getEnvironment();
+ self.allWallets = profileService.getWallets({
+ network: network,
+ n: 1,
+ onlyComplete: true
+ });
if (lodash.isEmpty(self.allWallets)) return;
- if (client.credentials.network != network) return;
+ client = self.allWallets[0];
if (client.credentials.n > 1)
self.isMultisigWallet = true;
diff --git a/src/js/controllers/modals/bitpayCardConfirmation.js b/src/js/controllers/modals/bitpayCardConfirmation.js
index 2ac75c25f..1ccd5455f 100644
--- a/src/js/controllers/modals/bitpayCardConfirmation.js
+++ b/src/js/controllers/modals/bitpayCardConfirmation.js
@@ -1,10 +1,10 @@
'use strict';
-angular.module('copayApp.controllers').controller('bitpayCardConfirmationController', function($scope, $timeout, go, bitpayCardService) {
+angular.module('copayApp.controllers').controller('bitpayCardConfirmationController', function($scope, $timeout, $state, bitpayCardService) {
$scope.ok = function() {
bitpayCardService.logout(function() {
- go.path('bitpayCard');
+ $state.go('bitpayCard.main');
});
$scope.cancel();
};
diff --git a/src/js/controllers/tab-home.js b/src/js/controllers/tab-home.js
index 376dbb5d7..3f3374903 100644
--- a/src/js/controllers/tab-home.js
+++ b/src/js/controllers/tab-home.js
@@ -4,7 +4,9 @@ angular.module('copayApp.controllers').controller('tabHomeController',
function($rootScope, $timeout, $scope, $state, lodash, profileService, walletService, configService, txFormatService, $ionicModal, $log, platformInfo) {
var self = this;
- self.glideraEnabled = configService.getSync().glidera.enabled;
+ self.setWallets = function() {
+ $scope.wallets = profileService.getWallets();
+ };
var setPendingTxps = function(txps) {
@@ -144,14 +146,13 @@ angular.module('copayApp.controllers').controller('tabHomeController',
});
});
- var config = configService.getSync().wallet;
-
var GLIDERA_LOCK_TIME = 6 * 60 * 60;
var glideraActive = true; // TODO TODO TODO
// isGlidera flag is a security measure so glidera status is not
// only determined by the tx.message
$scope.openTxpModal = function(tx) {
+ var config = configService.getSync().wallet;
var scope = $rootScope.$new(true);
scope.tx = tx;
scope.wallet = tx.wallet;
@@ -167,12 +168,12 @@ angular.module('copayApp.controllers').controller('tabHomeController',
});
};
- $scope.init = function() {
+ configService.whenAvailable(function() {
var config = configService.getSync();
- var isWindowsPhoneApp = platformInfo.isWP && isCordova;
var glideraEnabled = config.glidera.enabled;
var coinbaseEnabled = config.coinbase.enabled;
+ var isWindowsPhoneApp = platformInfo.isWP && isCordova;
$scope.buyAndSellEnabled = !isWindowsPhoneApp && (glideraEnabled || coinbaseEnabled);
- }
+ });
});
diff --git a/src/js/controllers/tab-send.js b/src/js/controllers/tab-send.js
index a7ab420f9..7ee23f697 100644
--- a/src/js/controllers/tab-send.js
+++ b/src/js/controllers/tab-send.js
@@ -1,6 +1,6 @@
'use strict';
-angular.module('copayApp.controllers').controller('tabSendController', function($scope, $ionicModal, $log, $timeout, addressbookService, profileService, configService, lodash, $state, walletService) {
+angular.module('copayApp.controllers').controller('tabSendController', function($scope, $ionicModal, $log, $timeout, addressbookService, profileService, lodash, $state, walletService) {
var originalList;
diff --git a/src/js/directives/directives.js b/src/js/directives/directives.js
index b095dda5c..285df5fd4 100644
--- a/src/js/directives/directives.js
+++ b/src/js/directives/directives.js
@@ -1,22 +1,6 @@
'use strict';
-
-function selectText(element) {
- var doc = document;
- if (doc.body.createTextRange) { // ms
- var range = doc.body.createTextRange();
- range.moveToElementText(element);
- range.select();
- } else if (window.getSelection) {
- var selection = window.getSelection();
- var range = doc.createRange();
- range.selectNodeContents(element);
- selection.removeAllRanges();
- selection.addRange(range);
-
- }
-}
angular.module('copayApp.directives')
- .directive('validAddress', ['$rootScope', 'bitcore',
+ .directive('validAddress', ['$rootScope', 'bitcore',
function($rootScope, bitcore) {
return {
require: 'ngModel',
@@ -24,10 +8,6 @@ angular.module('copayApp.directives')
var URI = bitcore.URI;
var Address = bitcore.Address
var validator = function(value) {
- var networkName = attrs.networkName;
-
- if (!networkName)
- throw 'validAddress should provide network name';
// Regular url
if (/^https?:\/\//.test(value)) {
@@ -37,13 +17,14 @@ angular.module('copayApp.directives')
// Bip21 uri
if (/^bitcoin:/.test(value)) {
- var uri, isAddressValid;
+ var uri, isAddressValidLivenet, isAddressValidTestnet;
var isUriValid = URI.isValid(value);
if (isUriValid) {
uri = new URI(value);
- isAddressValid = Address.isValid(uri.address.toString(), networkName)
+ isAddressValidLivenet = Address.isValid(uri.address.toString(), 'livenet')
+ isAddressValidTestnet = Address.isValid(uri.address.toString(), 'testnet')
}
- ctrl.$setValidity('validAddress', isUriValid && isAddressValid);
+ ctrl.$setValidity('validAddress', isUriValid && (isAddressValidLivenet || isAddressValidTestnet));
return value;
}
@@ -53,34 +34,13 @@ angular.module('copayApp.directives')
}
// Regular Address
- ctrl.$setValidity('validAddress', Address.isValid(value, networkName));
+ var regularAddressLivenet = Address.isValid(value, 'livenet');
+ var regularAddressTestnet = Address.isValid(value, 'testnet');
+ ctrl.$setValidity('validAddress', (regularAddressLivenet || regularAddressTestnet));
return value;
};
- ctrl.$parsers.unshift(validator);
- ctrl.$formatters.unshift(validator);
- }
- };
- }
- ])
- .directive('validUrl', [
-
- function() {
- return {
- require: 'ngModel',
- link: function(scope, elem, attrs, ctrl) {
- var validator = function(value) {
- // Regular url
- if (/^https?:\/\//.test(value)) {
- ctrl.$setValidity('validUrl', true);
- return value;
- } else {
- ctrl.$setValidity('validUrl', false);
- return value;
- }
- };
-
ctrl.$parsers.unshift(validator);
ctrl.$formatters.unshift(validator);
}
@@ -143,23 +103,6 @@ angular.module('copayApp.directives')
}
};
})
- .directive('loading', function() {
- return {
- restrict: 'A',
- link: function($scope, element, attr) {
- var a = element.html();
- var text = attr.loading;
- element.on('click', function() {
- element.html(' ' + text + '...');
- });
- $scope.$watch('loading', function(val) {
- if (!val) {
- element.html(a);
- }
- });
- }
- }
- })
.directive('ngFileSelect', function() {
return {
link: function($scope, el) {
@@ -187,147 +130,6 @@ angular.module('copayApp.directives')
};
}
])
- .directive('highlightOnChange', function() {
- return {
- restrict: 'A',
- link: function(scope, element, attrs) {
- scope.$watch(attrs.highlightOnChange, function(newValue, oldValue) {
- element.addClass('highlight');
- setTimeout(function() {
- element.removeClass('highlight');
- }, 500);
- });
- }
- }
- })
- .directive('checkStrength', function() {
- return {
- replace: false,
- restrict: 'EACM',
- require: 'ngModel',
- link: function(scope, element, attrs) {
-
- var MIN_LENGTH = 8;
- var MESSAGES = ['Very Weak', 'Very Weak', 'Weak', 'Medium', 'Strong', 'Very Strong'];
- var COLOR = ['#dd514c', '#dd514c', '#faa732', '#faa732', '#16A085', '#16A085'];
-
- function evaluateMeter(password) {
- var passwordStrength = 0;
- var text;
- if (password.length > 0) passwordStrength = 1;
- if (password.length >= MIN_LENGTH) {
- if ((password.match(/[a-z]/)) && (password.match(/[A-Z]/))) {
- passwordStrength++;
- } else {
- text = ', add mixed case';
- }
- if (password.match(/\d+/)) {
- passwordStrength++;
- } else {
- if (!text) text = ', add numerals';
- }
- if (password.match(/.[!,@,#,$,%,^,&,*,?,_,~,-,(,)]/)) {
- passwordStrength++;
- } else {
- if (!text) text = ', add punctuation';
- }
- if (password.length > 12) {
- passwordStrength++;
- } else {
- if (!text) text = ', add characters';
- }
- } else {
- text = ', that\'s short';
- }
- if (!text) text = '';
-
- return {
- strength: passwordStrength,
- message: MESSAGES[passwordStrength] + text,
- color: COLOR[passwordStrength]
- }
- }
-
- scope.$watch(attrs.ngModel, function(newValue, oldValue) {
- if (newValue && newValue !== '') {
- var info = evaluateMeter(newValue);
- scope[attrs.checkStrength] = info;
- }
- });
- }
- };
- })
- .directive('showFocus', function($timeout) {
- return function(scope, element, attrs) {
- scope.$watch(attrs.showFocus,
- function(newValue) {
- $timeout(function() {
- newValue && element[0].focus();
- });
- }, true);
- };
- })
- .directive('match', function() {
- return {
- require: 'ngModel',
- restrict: 'A',
- scope: {
- match: '='
- },
- link: function(scope, elem, attrs, ctrl) {
- scope.$watch(function() {
- return (ctrl.$pristine && angular.isUndefined(ctrl.$modelValue)) || scope.match === ctrl.$modelValue;
- }, function(currentValue) {
- ctrl.$setValidity('match', currentValue);
- });
- }
- };
- })
- .directive('clipCopy', function() {
- return {
- restrict: 'A',
- scope: {
- clipCopy: '=clipCopy'
- },
- link: function(scope, elm) {
- // TODO this does not work (FIXME)
- elm.attr('tooltip', 'Press Ctrl+C to Copy');
- elm.attr('tooltip-placement', 'top');
-
- elm.bind('click', function() {
- selectText(elm[0]);
- });
- }
- };
- })
- .directive('menuToggle', function() {
- return {
- restrict: 'E',
- replace: true,
- templateUrl: 'views/includes/menu-toggle.html'
- }
- })
- .directive('logo', function() {
- return {
- restrict: 'E',
- scope: {
- width: "@",
- negative: "="
- },
- controller: function($scope) {
- $scope.logo_url = $scope.negative ? 'img/logo-negative.svg' : 'img/logo.svg';
- },
- replace: true,
- template: '
'
- }
- })
- .directive('availableBalance', function() {
- return {
- restrict: 'E',
- replace: true,
- templateUrl: 'views/includes/available-balance.html'
- }
- })
.directive('ignoreMouseWheel', function($rootScope, $timeout) {
return {
restrict: 'A',
diff --git a/src/js/routes.js b/src/js/routes.js
index eea2d4994..5c1e95d18 100644
--- a/src/js/routes.js
+++ b/src/js/routes.js
@@ -85,7 +85,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
*
*/
- .state('disclaimer', {
+ .state('disclaimer', {
url: '/disclaimer',
templateUrl: 'views/disclaimer.html',
})
@@ -557,13 +557,26 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
*
*/
- .state('bitpayCard', {
- url: '/bitpay-card',
- templateUrl: 'views/bitpayCard.html'
+ .state('bitpayCard', {
+ url: '/bitpayCard',
+ abstract: true,
+ template: ''
})
- .state('preferencesBitpayCard', {
- url: '/preferences-bitpay-card',
- templateUrl: 'views/preferencesBitpayCard.html'
+ .state('bitpayCard.main', {
+ url: '/main',
+ views: {
+ 'bitpayCard': {
+ templateUrl: 'views/bitpayCard.html'
+ }
+ }
+ })
+ .state('bitpayCard.preferences', {
+ url: '/preferences',
+ views: {
+ 'bitpayCard': {
+ templateUrl: 'views/preferencesBitpayCard.html'
+ }
+ }
})
/*
diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js
index 6abbb1fcc..7a0368cb5 100644
--- a/src/js/services/bitpayCardService.js
+++ b/src/js/services/bitpayCardService.js
@@ -5,9 +5,13 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http,
var credentials = {};
var bpSession = {};
- root.setCredentials = function(network) {
- credentials.NETWORK = network;
- if (network == 'testnet') {
+ var _setCredentials = function() {
+ /*
+ * Development: 'testnet'
+ * Production: 'livenet'
+ */
+ credentials.NETWORK = 'livenet';
+ if (credentials.NETWORK == 'testnet') {
credentials.BITPAY_API_URL = 'https://test.bitpay.com';
}
else {
@@ -16,6 +20,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http,
};
var _getUser = function(cb) {
+ _setCredentials();
storageService.getBitpayCard(credentials.NETWORK, function(err, user) {
if (err) return cb(err);
if (lodash.isString(user)) {
@@ -26,6 +31,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http,
};
var _setUser = function(user, cb) {
+ _setCredentials();
user = JSON.stringify(user);
storageService.setBitpayCard(credentials.NETWORK, user, function(err) {
return cb(err);
@@ -33,6 +39,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http,
};
var _getSession = function(cb) {
+ _setCredentials();
$http({
method: 'GET',
url: credentials.BITPAY_API_URL + '/visa-api/session',
@@ -50,6 +57,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http,
};
var _getBitPay = function(endpoint) {
+ _setCredentials();
return {
method: 'GET',
url: credentials.BITPAY_API_URL + endpoint,
@@ -61,6 +69,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http,
};
var _postBitPay = function(endpoint, data) {
+ _setCredentials();
return {
method: 'POST',
url: credentials.BITPAY_API_URL + endpoint,
@@ -72,6 +81,11 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http,
};
};
+ root.getEnvironment = function() {
+ _setCredentials();
+ return credentials.NETWORK;
+ };
+
root.topUp = function(data, cb) {
var dataSrc = {
amount: data.amount,
@@ -173,6 +187,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http,
};
root.logout = function(cb) {
+ _setCredentials();
storageService.removeBitpayCard(credentials.NETWORK, function(err) {
$http(_getBitPay('/visa-api/logout')).then(function(data) {
$log.info('BitPay Logout: SUCCESS');
diff --git a/src/sass/main.scss b/src/sass/main.scss
index f6a9acaaa..411e2a4e9 100644
--- a/src/sass/main.scss
+++ b/src/sass/main.scss
@@ -955,3 +955,13 @@ input[type="number"] {
.calculator .button-calc .columns { padding: 20px; }
.calculator .header-calc { top: 18%; }
}
+
+/* Turn Off Number Input Spinners */
+
+input[type=number] {
+ &::-webkit-inner-spin-button, &::-webkit-outer-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+ }
+}
+