New send flow for bitpay card. Fix paypro txStatus. Minor bug fixes

This commit is contained in:
Gustavo Maximiliano Cortez 2016-09-28 17:51:45 -03:00
parent 11a7e96c08
commit 1ac78c21a5
No known key found for this signature in database
GPG Key ID: 15EDAD8D9F2EB1AF
13 changed files with 182 additions and 90 deletions

View File

@ -12,10 +12,15 @@
<div>
<div class="item item-no-bottom-border" translate>Recipient</div>
<div class="item item-text-wrap item-icon-left bitcoin-address">
<div class="item item-text-wrap item-icon-left item-big-icon-left bitcoin-address">
<i ng-if="isWallet" class="icon ion-briefcase size-21"></i>
<gravatar ng-if="!isWallet" class="send-gravatar" name="{{toName}}" width="30" email="{{toEmail}}"></gravatar>
<span>{{toName || toAddress}}</span>
<span ng-if="!isWallet">
<gravatar ng-if="!isCard" class="send-gravatar" name="{{toName}}" width="30" email="{{toEmail}}"></gravatar>
<i ng-if="isCard" class="icon big-icon-svg">
<div class="bg icon-bitpay-card"></div>
</i>
</span>
<span ng-class="{'m10l':isCard}">{{toName || toAddress}}</span>
</div>
</div>

View File

@ -101,7 +101,7 @@
</div>
</div>
<div class="camera-icon" ng-show="bitpayCard.bitpayCardCurrentBalance">
<a ng-click="addFunds = true">
<a ui-sref="tabs.bitpayCard.amount({'isCard': true, 'toName': 'BitPay Card'})">
<i class="icon ion-plus size-21"></i>
</a>
</div>

View File

@ -26,14 +26,21 @@
<div class="item item-icon-left">
<i ng-if="isWallet" class="icon ion-briefcase size-21"></i>
<gravatar ng-if="!isWallet" class="send-gravatar" name="{{toName}}" width="30" email="{{toEmail}}"></gravatar>
<span translate>To</span>: {{toAddress}}
<p ng-show="toName">{{toName}}</p>
<div ng-if="!isWallet">
<gravatar ng-if="!isCard" class="send-gravatar" name="{{toName}}" width="30" email="{{toEmail}}"></gravatar>
<i ng-if="isCard" class="icon big-icon-svg">
<div class="bg icon-bitpay-card"></div>
</i>
</div>
<div ng-class="{'m10l':isCard}">
<span translate>To</span>: {{toAddress}}
<p ng-show="toName">{{toName}}</p>
<div ng-show="_paypro" ng-click="openPPModal(_paypro)">
<i ng-show="_paypro.verified && _paypro.caTrusted" class="ion-locked" style="color:green"></i>
<i ng-show="!_paypro.caTrusted" class="ion-unlocked" style="color:red"></i>
{{_paypro.domain}}
<div ng-show="_paypro" ng-click="openPPModal(_paypro)">
<i ng-show="_paypro.verified && _paypro.caTrusted" class="ion-locked" style="color:green"></i>
<i ng-show="!_paypro.caTrusted" class="ion-unlocked" style="color:red"></i>
{{_paypro.domain}}
</div>
</div>
</div>
</div>

View File

@ -1,60 +1,57 @@
<ion-modal-view ng-controller="payproController">
<ion-header-bar align-title="center" class="tab-bar" ng-style="{'background-color':color}">
<div class="left-small">
<a ng-click="cancel()" class="p10">
<span class="text-close" translate>Close</span>
</a>
<ion-header-bar align-title="center" class="bar-royal" ng-style="{'background-color': color}">
<button class="button button-clear" ng-click="cancel()">
{{'Close' | translate}}
</button>
<div class="title" translate>
Payment request
</div>
<h1 class="title ellipsis" translate>Payment request</h1>
</ion-header-bar>
<ion-content ng-style="{'background-color': '#F6F7F9'}">
<div class="modal-content">
<div class="header-modal text-center p50t">
<div class="size-42">
{{amountStr}}
</div>
</div>
<ion-content>
<div class="header-modal text-center size-42">
{{amountStr}}
</div>
<h4 class="title m10l" translate>Details</h4>
<ul class="no-bullet size-14 m10t">
<li class="line-b p10 oh">
<span class="text-gray" translate>Pay To</span>
<span class="right enable_text_select">{{_paypro.domain}}</span>
</li>
<li class="line-b p10 oh" ng-if="_paypro.toAddress">
<span class="text-gray" translate>Address</span>
<span class="right enable_text_select">{{_paypro.toAddress}}</span>
</li>
<li class="line-b p10 oh">
<span class="text-gray" translate>Certified by</span>
<span class="right text-right">
<div class="list">
<div class="item item-divider" translate>
Details
</div>
<div class="item">
{{'Pay To'|translate}}
<span class="item-note">{{_paypro.domain}}</span>
</div>
<div class="item" ng-if="_paypro.toAddress">
{{'Address'|translate}}
<span class="item-note">{{_paypro.toAddress}}</span>
</div>
<div class="item">
{{'Certified by'|translate}}
<span class="item-note">
<span ng-show="_paypro.caTrusted">
<i class="fi-lock color-greeni"></i>
<i class="ion-locked" style="color:green"></i>
{{_paypro.caName}}<br>
<span translate>(Trusted)</span>
</span>
<span ng-show="!_paypro.caTrusted">
<span ng-show="_paypro.selfSigned">
<i class="fi-unlock color-yellowi"></i> <span translate>Self-signed Certificate</span>
<i class="ion-unlocked" style="color:red"></i> <span translate>Self-signed Certificate</span>
</span>
<span ng-show="!_paypro.selfSigned">
<i class="fi-unlock color-yellowi"></i>{{_paypro.caName}}<br>
<i class="ion-locked" style="color:yellow"></i>{{_paypro.caName}}<br>
<span translate>WARNING: UNTRUSTED CERTIFICATE</span>
</span>
</span>
</span>
</li>
<li class="line-b p10 oh" ng-if="_paypro.memo">
<span class="text-gray" translate>Memo</span>
<span class="right">{{_paypro.memo}}</span>
</li>
<li class="line-b p10 oh" ng-if="_paypro.expires">
<span class="text-gray" translate>Expires</span>
<span class="right">{{_paypro.expires * 1000 | amTimeAgo }}</span>
</li>
</ul>
</div>
<div class="item" ng-if="_paypro.memo">
{{'Memo'|translate}}
<span class="item-note wrapword">{{_paypro.memo}}</span>
</div>
<div class="item" ng-if="_paypro.expires">
{{'Expires'|translate}}
<span class="item-note">{{_paypro.expires * 1000 | amTimeAgo }}</span>
</div>
</div>
<div class="extra-margin-bottom"></div>
</ion-content>
</ion-modal-view>

View File

@ -4,13 +4,14 @@
<div ng-show="tx.amountStr" class="m20t size-36">
{{tx.amountStr}}
</div>
<div class="size-16 text-gray m10v">
<span translate>Sent</span>
<div class="size-24 text-gray m20v">
<span ng-if="!fromBitPayCard" translate>Sent</span>
<span ng-if="fromBitPayCard" translate>Funds sent</span>
</div>
<div class="text-center m20t" ng-if="entryExist || !fromSendTab">
<div class="text-center m20t" ng-if="entryExist || !fromSendTab || fromPayPro">
<a class="button button-positive" ng-click="cancel()" translate>OKAY</a>
</div>
<div class="collect-address" ng-if="!entryExist && fromSendTab">
<div class="collect-address" ng-if="!entryExist && fromSendTab && !fromPayPro">
<div class="row">
<p translate class="col">Would you like to add this address to your address book?</p>
</div>
@ -40,7 +41,7 @@
<div ng-if="type == 'created'" class="popup-txsigned text-center m30tp">
<i class="icon ion-checkmark-round"></i>
<div class="text-center size-18 tu text-bold m20t">
<div class="text-center size-24 tu text-bold m20v">
<span translate>Payment Proposal Created</span>
</div>
<div class="text-center">
@ -52,7 +53,7 @@
<div ng-if="type == 'accepted'" class="popup-txsigned text-center m30tp">
<i class="icon ion-checkmark-round"></i>
<div class="text-center size-18 tu text-bold m20t">
<div class="text-center size-24 tu text-bold m20v">
<span translate>Payment Accepted</span>
</div>
<div class="text-center">
@ -62,7 +63,7 @@
<div ng-if="type=='rejected'" class="popup-txrejected text-center m30tp">
<i class="icon ion-close-round"></i>
<div class="text-center size-18 tu text-bold m20t">
<div class="text-center size-24 tu text-bold m20v">
<span translate>Payment Rejected</span>
</div>
<div class="text-center">

View File

@ -1,6 +1,6 @@
'use strict';
angular.module('copayApp.controllers').controller('amountController', function($rootScope, $scope, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, txFormatService) {
angular.module('copayApp.controllers').controller('amountController', function($rootScope, $scope, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, txFormatService, ongoingProcess, bitpayCardService, popupService) {
var unitToSatoshi;
var satToUnit;
@ -10,18 +10,20 @@ angular.module('copayApp.controllers').controller('amountController', function($
var SMALL_FONT_SIZE_LIMIT = 13;
var LENGTH_EXPRESSION_LIMIT = 19;
$scope.isWallet = $stateParams.isWallet;
$scope.toAddress = $stateParams.toAddress;
$scope.toName = $stateParams.toName;
$scope.toEmail = $stateParams.toEmail;
$scope.$on('$ionicView.leave', function() {
angular.element($window).off('keydown');
});
$scope.$on("$ionicView.enter", function(event, data) {
if (!$stateParams.toAddress) {
$scope.isWallet = data.stateParams.isWallet;
$scope.isCard = data.stateParams.isCard;
$scope.toAddress = data.stateParams.toAddress;
$scope.toName = data.stateParams.toName;
$scope.toEmail = data.stateParams.toEmail;
$scope.showAlternativeAmount = !!$scope.isCard;
if (!$scope.isCard && !$stateParams.toAddress) {
$log.error('Bad params at amount')
throw ('bad params');
}
@ -97,7 +99,6 @@ angular.module('copayApp.controllers').controller('amountController', function($
};
$scope.pushOperator = function(operator) {
console.log('[amount.js.90:operator:]', operator); //TODO
if (!$scope.amount || $scope.amount.length == 0) return;
$scope.amount = _pushOperator($scope.amount);
@ -185,14 +186,50 @@ angular.module('copayApp.controllers').controller('amountController', function($
$scope.finish = function() {
var _amount = evaluate(format($scope.amount));
var amount = $scope.showAlternativeAmount ? fromFiat(_amount).toFixed(unitDecimals) : _amount.toFixed(unitDecimals);
$state.transitionTo('tabs.send.confirm', {
isWallet: $scope.isWallet,
toAmount: amount * unitToSatoshi,
toAddress: $scope.toAddress,
toName: $scope.toName,
toEmail: $scope.toEmail
});
if ($scope.isCard) {
var amountUSD = $scope.showAlternativeAmount ? _amount : $filter('formatFiatAmount')(toFiat(_amount));
var dataSrc = {
amount: amountUSD,
currency: 'USD'
};
ongoingProcess.set('Processing Transaction...', true);
$timeout(function() {
bitpayCardService.topUp(dataSrc, function(err, invoiceId) {
if (err) {
ongoingProcess.set('Processing Transaction...', false);
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err));
return;
}
bitpayCardService.getInvoice(invoiceId, function(err, data) {
ongoingProcess.set('Processing Transaction...', false);
if (err) {
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err));
return;
}
var payProUrl = data.paymentUrls.BIP73;
$state.transitionTo('tabs.bitpayCard.confirm', {
isCard: $scope.isCard,
toName: $scope.toName,
paypro: payProUrl
});
});
});
});
} else {
var amount = $scope.showAlternativeAmount ? fromFiat(_amount).toFixed(unitDecimals) : _amount.toFixed(unitDecimals);
$state.transitionTo('tabs.send.confirm', {
isWallet: $scope.isWallet,
toAmount: amount * unitToSatoshi,
toAddress: $scope.toAddress,
toName: $scope.toName,
toEmail: $scope.toEmail
});
}
};
});

View File

@ -4,15 +4,15 @@ angular.module('copayApp.controllers').controller('confirmController', function(
var cachedTxp = {};
var isChromeApp = platformInfo.isChromeApp;
$scope.isWallet = $stateParams.isWallet;
$scope.toAmount = $stateParams.toAmount;
$scope.toAddress = $stateParams.toAddress;
$scope.toName = $stateParams.toName;
$scope.toEmail = $stateParams.toEmail;
$scope.description = $stateParams.description;
$scope.paypro = $stateParams.paypro;
$scope.$on("$ionicView.enter", function(event, data) {
$scope.isWallet = data.stateParams.isWallet;
$scope.isCard = data.stateParams.isCard;
$scope.toAmount = data.stateParams.toAmount;
$scope.toAddress = data.stateParams.toAddress;
$scope.toName = data.stateParams.toName;
$scope.toEmail = data.stateParams.toEmail;
$scope.description = data.stateParams.description;
$scope.paypro = data.stateParams.paypro;
initConfirm();
});
@ -243,7 +243,8 @@ angular.module('copayApp.controllers').controller('confirmController', function(
walletService.createTx(wallet, txp, function(err, ctxp) {
if (err) {
return setSendError(err);
setSendError(err);
return cb(err);
}
return cb(null, ctxp);
});
@ -312,8 +313,4 @@ angular.module('copayApp.controllers').controller('confirmController', function(
if (err) return setSendError(err);
});
};
$scope.cancel = function() {
$state.go('tabs.send');
};
});

View File

@ -1,9 +1,13 @@
'use strict';
angular.module('copayApp.controllers').controller('txStatusController', function($scope, $timeout, $state, $ionicHistory, $log, addressbookService) {
angular.module('copayApp.controllers').controller('txStatusController', function($scope, $timeout, $state, $stateParams, $ionicHistory, $log, addressbookService) {
if ($scope.cb) $timeout($scope.cb, 100);
$scope.fromSendTab = $ionicHistory.viewHistory().backView && $ionicHistory.viewHistory().backView.stateName === "tabs.send.amount" ||  "tabs.send";
var previousView = $ionicHistory.viewHistory().backView && $ionicHistory.viewHistory().backView.stateName;
$scope.fromSendTab = previousView.match(/tabs.send/) ? true : false;
$scope.fromBitPayCard = previousView.match(/tabs.bitpayCard/) ? true : false;
$scope.fromPayPro = $stateParams.paypro ? true : false;
$scope.cancel = function() {
$scope.txStatusModal.hide();
@ -13,6 +17,11 @@ angular.module('copayApp.controllers').controller('txStatusController', function
$timeout(function() {
$state.transitionTo('tabs.home');
}, 100);
} else if ($scope.fromBitPayCard) {
$ionicHistory.removeBackView();
$timeout(function() {
$state.transitionTo('tabs.bitpayCard');
}, 100);
}
};
@ -24,7 +33,7 @@ angular.module('copayApp.controllers').controller('txStatusController', function
});
$ionicHistory.removeBackView();
$state.go('tabs.send.addressbook', {
fromSendTab: true,
fromSendTab: $scope.fromSendTab,
addressbookEntry: addressbookEntry
});
}

View File

@ -33,6 +33,8 @@ angular.module('copayApp.controllers').controller('tabsController', function($ro
'tabs.preferences.backup',
'tabs.receive.backupWarning',
'tabs.receive.backup',
'tabs.bitpayCard.amount',
'tabs.bitpayCard.confirm',
];
$rootScope.$on('$ionicView.beforeEnter', function() {

View File

@ -852,6 +852,24 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
}
}
})
.state('tabs.bitpayCard.amount', {
url: '/amount/:isCard/:toName',
views: {
'tab-home@tabs': {
controller: 'amountController',
templateUrl: 'views/amount.html'
}
}
})
.state('tabs.bitpayCard.confirm', {
url: '/confirm/:isCard/:toAddress/:toName/:toAmount/:toEmail/:description/:paypro',
views: {
'tab-home@tabs': {
controller: 'confirmController',
templateUrl: 'views/confirm.html'
}
}
})
.state('tabs.bitpayCard.preferences', {
url: '/preferences',
views: {

View File

@ -116,3 +116,16 @@ ion-header-bar{
.card{
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.3);
}
/* Wrap text from item-note */
.item-note{
white-space: -moz-pre-wrap !important;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
white-space: pre-wrap;
word-wrap: break-word;
white-space: -webkit-pre-wrap;
word-break: break-all;
white-space: normal;
}

View File

@ -1,4 +1,7 @@
#view-amount {
.icon-bitpay-card {
background-image: url("../img/icon-bitpay.svg");
}
@media(max-width: 480px) {
.bitcoin-address {
.icon {

View File

@ -1,4 +1,7 @@
#view-confirm {
.icon-bitpay-card {
background-image: url("../img/icon-bitpay.svg");
}
.slide-to-pay{
bottom: 149px;
}