From ce833c6ef9baf9becc521b2ea114042b9796b99e Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Tue, 23 Aug 2016 09:37:21 -0300 Subject: [PATCH 1/4] Clean directives. Fix mouse-wheel on input number --- public/views/buyAmazon.html | 2 +- public/views/buyAndSell.html | 6 +- public/views/includes/menu-toggle.html | 5 - public/views/modals/addressbook.html | 3 +- public/views/tab-home.html | 11 +- src/js/controllers/tab-send.js | 2 +- src/js/directives/directives.js | 201 +------------------------ src/sass/main.scss | 10 ++ 8 files changed, 22 insertions(+), 218 deletions(-) delete mode 100644 public/views/includes/menu-toggle.html diff --git a/public/views/buyAmazon.html b/public/views/buyAmazon.html index efdcba473..1eb985b1a 100644 --- a/public/views/buyAmazon.html +++ b/public/views/buyAmazon.html @@ -49,7 +49,7 @@ min="0.01" max="500" ng-model="fiat" - autocomplete="off" required> + autocomplete="off" ignore-mouse-wheel required> USD 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/addressbook.html b/public/views/modals/addressbook.html index 0b2662b80..b1aca8a2e 100644 --- a/public/views/modals/addressbook.html +++ b/public/views/modals/addressbook.html @@ -67,8 +67,7 @@ + ng-model="addressbookEntry.address" required> diff --git a/public/views/tab-home.html b/public/views/tab-home.html index 7034b91b2..399db200a 100644 --- a/public/views/tab-home.html +++ b/public/views/tab-home.html @@ -61,7 +61,7 @@
  • + ui-sref="wallet.details({'walletId': item.id})"> {{item.name || item.id}} @@ -81,20 +81,17 @@

    Next steps

      -
    • +
    • BitPay Card
    • -
    • +
    • Buy and Sell
    • -
    • +
    • Gift Cards - - bla bla -
    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..19b2e667e 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', @@ -26,7 +10,7 @@ angular.module('copayApp.directives') var validator = function(value) { var networkName = attrs.networkName; - if (!networkName) + if (!networkName) throw 'validAddress should provide network name'; // Regular url @@ -58,29 +42,6 @@ angular.module('copayApp.directives') }; - 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 +104,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 +131,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: 'Copay' - } - }) - .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/sass/main.scss b/src/sass/main.scss index b18dc6db2..98f4b1235 100644 --- a/src/sass/main.scss +++ b/src/sass/main.scss @@ -1045,3 +1045,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; + } +} + From e2413ff62080388925376972a430feda98f326da Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Tue, 23 Aug 2016 10:30:29 -0300 Subject: [PATCH 2/4] Support valid-address testnet/livenet --- public/views/modals/addressbook.html | 3 ++- src/js/directives/directives.js | 15 +++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/public/views/modals/addressbook.html b/public/views/modals/addressbook.html index b1aca8a2e..0b2662b80 100644 --- a/public/views/modals/addressbook.html +++ b/public/views/modals/addressbook.html @@ -67,7 +67,8 @@ + ng-model="addressbookEntry.address" + valid-address required> diff --git a/src/js/directives/directives.js b/src/js/directives/directives.js index 19b2e667e..285df5fd4 100644 --- a/src/js/directives/directives.js +++ b/src/js/directives/directives.js @@ -8,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)) { @@ -21,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; } @@ -37,7 +34,9 @@ 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; }; From 894223a47f444c8cc0b7d0ae58d06d6d79f41b80 Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Mon, 22 Aug 2016 17:43:31 -0300 Subject: [PATCH 3/4] BitPay card. Fix initial wallet home --- public/views/bitpayCard.html | 246 ++++++++---------- .../modals/bitpay-card-confirmation.html | 34 +-- public/views/preferencesBitpayCard.html | 34 +-- public/views/tab-home.html | 17 +- src/js/controllers/bitpayCard.js | 16 +- .../modals/bitpayCardConfirmation.js | 4 +- src/js/controllers/tab-home.js | 15 +- src/js/routes.js | 27 +- src/js/services/bitpayCardService.js | 21 +- 9 files changed, 208 insertions(+), 206 deletions(-) diff --git a/public/views/bitpayCard.html b/public/views/bitpayCard.html index d760655e7..b52acfb2d 100644 --- a/public/views/bitpayCard.html +++ b/public/views/bitpayCard.html @@ -1,32 +1,21 @@ -
    -
    - -
    - -
    - -
    - +
    Sandbox version. Only for testing purpose
    @@ -34,16 +23,15 @@ Loading...
    -
    -
    -
    +
    +
    -

    +

    Login to your account 2-Step Verification -

    -
    +
    {{bitpayCard.error}} @@ -55,37 +43,30 @@ ng-submit="bitpayCard.authenticate()" novalidate> - +
    + - - -
    - +
    + +

    @@ -98,27 +79,22 @@ ng-submit="bitpayCard.authenticate2FA()" novalidate> -

    - -
    - - -
    - +
    +
    + + -
    @@ -134,7 +110,7 @@
    @@ -158,19 +134,19 @@
    - +
    -
    +
    -
    +
    {{tx.merchant.name}}
    @@ -180,14 +156,14 @@
    + class="col"> {{desc}}
    -
    +
    -
    +
    -
    +
    @@ -211,41 +186,38 @@ ng-submit="bitpayCard.sendFunds()" novalidate> -

    Next steps

      -
    • +
    • BitPay Card
    • 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..6dafd872d 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, $location, bitpayCardService) { $scope.ok = function() { bitpayCardService.logout(function() { - go.path('bitpayCard'); + $location.path('/bitpayCard/main'); }); $scope.cancel(); }; diff --git a/src/js/controllers/tab-home.js b/src/js/controllers/tab-home.js index eefe6259f..fe3687958 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) { @@ -108,7 +110,7 @@ angular.module('copayApp.controllers').controller('tabHomeController', if (err) { console.log('[tab-home.js.35:err:]', $log.error(err)); //TODO return; - } + } if (status.pendingTxps && status.pendingTxps[0]) { var txps = lodash.filter($scope.txps, function(x) { return x.walletId != wallet.id; @@ -136,14 +138,13 @@ angular.module('copayApp.controllers').controller('tabHomeController', c1(); }); - 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; @@ -159,12 +160,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/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'); From 894c206204f5507d9adcc3431a7d935ccc6675ee Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Tue, 23 Aug 2016 08:31:48 -0300 Subject: [PATCH 4/4] Using state.go --- src/js/controllers/modals/bitpayCardConfirmation.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/controllers/modals/bitpayCardConfirmation.js b/src/js/controllers/modals/bitpayCardConfirmation.js index 6dafd872d..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, $location, bitpayCardService) { +angular.module('copayApp.controllers').controller('bitpayCardConfirmationController', function($scope, $timeout, $state, bitpayCardService) { $scope.ok = function() { bitpayCardService.logout(function() { - $location.path('/bitpayCard/main'); + $state.go('bitpayCard.main'); }); $scope.cancel(); };