Merge pull request #214 from cmgustavo/ref/design-59

Ref/design 59
This commit is contained in:
Gustavo Maximiliano Cortez 2016-09-29 10:24:34 -03:00 committed by GitHub
commit ec31e5ddec
21 changed files with 328 additions and 315 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 bitcoin-address" ng-class="{'item-big-icon-left':isCard}">
<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

@ -1,21 +1,18 @@
<ion-view>
<ion-view id="bitpayCard">
<ion-nav-bar class="bar-royal">
<ion-nav-buttons side="primary">
<button class="button button-clear" ui-sref="tabs.home">
Close
</button>
</ion-nav-buttons>
<ion-nav-back-button>
</ion-nav-back-button>
<ion-nav-title>BitPay Card</ion-nav-title>
<ion-nav-buttons side="secondary">
<button class="button button-clear" ui-sref="bitpayCard.preferences">
<i class="icon ion-gear-b"></i>
<ion-nav-buttons side="secondary" ng-show="bitpayCard.bitpayCardAuthenticated">
<button class="button back-button" ui-sref="tabs.bitpayCard.preferences">
<i class="icon ion-ios-gear-outline"></i>
</button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-content ng-controller="bitpayCardController as bitpayCard" ng-init="bitpayCard.init()">
<ion-content>
<div class="box-notification warning" ng-show="network == 'testnet'">
<div class="box-notification warning m0" ng-show="network == 'testnet'">
Sandbox version. Only for testing purpose
</div>
@ -35,7 +32,7 @@
<form
ng-show="!bitpayCard.bitpayCardTwoFactorPending"
name="authenticateForm"
ng-submit="bitpayCard.authenticate()"
ng-submit="bitpayCard.authenticate(email, password)"
novalidate>
<div class="card list">
@ -71,7 +68,7 @@
<form
ng-show="bitpayCard.bitpayCardTwoFactorPending"
name="authenticate2FAForm"
ng-submit="bitpayCard.authenticate2FA()"
ng-submit="bitpayCard.authenticate2FA(twoFactorCode)"
novalidate>
<div class="list">
@ -92,47 +89,43 @@
</form>
</div>
<div ng-show="bitpayCard.bitpayCardAuthenticated && !bitpayCard.visaCardActivated && !addFunds">
<div id="bitpayCard" class="oh pr">
<div ng-show="bitpayCard.bitpayCardAuthenticated">
<div class="oh pr">
<div class="amount">
<div ng-show="!loadingHistory && bitpayCard.bitpayCardCurrentBalance" ng-click="bitpayCard.update()">
<strong class="size-36">${{bitpayCard.bitpayCardCurrentBalance}}</strong>
<div class="size-12">Available balance</div>
<div ng-if="!loadingHistory && bitpayCard.bitpayCardCurrentBalance" ng-click="bitpayCard.update()">
<div class="size-36 m20b">${{bitpayCard.bitpayCardCurrentBalance}}</div>
<a class="button button-positive button-small" ui-sref="tabs.bitpayCard.amount({'isCard': true, 'toName': 'BitPay Card'})">
<i class="icon ion-ios-plus-empty"></i> {{'Add Funds'|translate}}
</a>
</div>
<div ng-show="loadingHistory">
<div ng-if="loadingHistory" class="m10t">
<strong class="size-36">...</strong>
</div>
</div>
<div class="camera-icon" ng-show="bitpayCard.bitpayCardCurrentBalance">
<a ng-click="addFunds = true">
<i class="icon ion-plus size-21"></i>
</a>
</div>
</div>
<select class="m10" ng-model="dateRange" ng-change="bitpayCard.update(dateRange)">
<option value="last30Days">Recent Activity</option>
<option value="lastMonth">Last Month</option>
<option value="all">All Activity</option>
</select>
<div
class="oh pr m20t text-gray size-12 text-center"
class="m10t text-center padding"
ng-show="!bitpayCard.bitpayCardTransactionHistory[0] &&
!bitpayCard.bitpayCardInvoiceHistory[0] && !loadingHistory">
No transactions yet
!bitpayCard.bitpayCardInvoiceHistory[0] && (!loadingHistory || !bitpayCardCached)">
<i class="icon ion-ios-arrow-thin-up size-24"></i>
<h1>Get started</h1>
<h4>Your BitPay Card is ready. Add funds to your card to start using your card at stores and ATMs worldwide.</h4>
</div>
<div ng-show="loadingHistory" class="oh pr m20t text-gray text-center">
<i class="icon ion-android-sync"></i>
</div>
<div class="card list" ng-show="!loadingHistory">
<div class="list" ng-if="bitpayCardCached">
<div class="item item-divider">
<select class="select-style" ng-model="dateRange" ng-change="bitpayCard.update(dateRange)">
<option value="last30Days">Recent Activity</option>
<option value="lastMonth">Last Month</option>
<option value="all">All Activity</option>
</select>
</div>
<div
ng-repeat="tx in bitpayCard.bitpayCardTransactionHistory | orderBy: ['pending','-timestamp']"
class="item row"
ng-init="bitpayCard.getMerchantInfo(tx)">
<div class="col" ng-init="icon = bitpayCard.getIconName(tx)">
<div class="col col-10" ng-init="icon = bitpayCard.getIconName(tx)">
<img class="m5t" ng-src="img/mcc-icons/{{icon}}.svg" width="22">
</div>
@ -146,7 +139,7 @@
</div>
<div
ng-init="desc = bitpayCard.processDescription(tx)"
class="col">
class="col size-12">
{{desc}}
</div>
<div class="col">
@ -165,55 +158,5 @@
</div>
</div>
</div>
<div ng-show="bitpayCard.bitpayCardAuthenticated && !bitpayCard.visaCardActivated && addFunds">
<form
name="createInvoiceForm"
ng-submit="bitpayCard.sendFunds()"
novalidate>
<div class="card list">
<label class="item item-input item-stacked-label">
<span class="input-label">Amount</span>
<input
type="number"
id="fiat"
name="fiat"
ng-attr-placeholder="{{'Amount in USD'}}"
min="0.01"
max="2000"
ng-model="fiat"
autocomplete="off"
required>
<a class="postfix">USD</a>
</label>
<wallets ng-if="wallets[0]" wallets="wallets"></wallets>
</div>
<p class="size-12 text-warning" ng-show="bitpayCard.isMultisigWallet">
You selected a multisignature wallet. Please note that the transaction will only appear on your card's
Activity when the payment is fully signed.
</p>
<div class="row">
<div class="col">
<button class="button button-block button-light"
type="button"
ng-click="addFunds = false; fiat = null">
Cancel
</button>
</div>
<div class="col">
<button class="button button-block button-positive"
ng-disabled="!fiat"
type="submit">
Send
</button>
</div>
</div>
</form>
</div>
</ion-content>
</ion-view>

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

@ -76,14 +76,15 @@
</p>
<i class="icon nav-item-arrow-right"></i>
</a>
<a ui-sref="bitpayCard.main"
<a ui-sref="tabs.bitpayCard"
ng-if="externalServices.BitpayCard"
class="item item-icon-left item-big-icon-left item-icon-right">
<i class="icon big-icon-svg">
<div class="bg icon-bitpay-card"></div>
</i>
<h2>BitPay Card</h2>
<p translate>Add funds to get started</p>
<p ng-if="!bitpayCard" translate>Add funds to get started</p>
<span ng-if="bitpayCard">${{bitpayCard.balance}}</span>
<i class="icon nav-item-arrow-right"></i>
</a>
</div>

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) {
$scope.$on("$ionicView.beforeEnter", 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

@ -3,15 +3,14 @@
angular.module('copayApp.controllers').controller('bitpayCardController', function($scope, $timeout, $log, lodash, bitpayCardService, configService, profileService, walletService, ongoingProcess, pbkdf2Service, moment, popupService, gettextCatalog, bwcError) {
var self = this;
var wallet;
$scope.dateRange = 'last30Days';
$scope.network = bitpayCardService.getEnvironment();
$scope.$on('Wallet/Changed', function(event, w) {
if (lodash.isEmpty(w)) {
$log.debug('No wallet provided');
return;
}
wallet = w;
$log.debug('Wallet changed: ' + w.name);
bitpayCardService.getCacheData(function(err, data) {
if (err || lodash.isEmpty(data)) return;
$scope.bitpayCardCached = true;
self.bitpayCardTransactionHistory = data.transactions;
self.bitpayCardCurrentBalance = data.balance;
});
var processTransactions = function(invoices, history) {
@ -89,6 +88,14 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi
self.bitpayCardTransactionHistory = processTransactions(invoices, history.transactionList);
self.bitpayCardCurrentBalance = history.currentCardBalance;
var cacheData = {
balance: self.bitpayCardCurrentBalance,
transactions: self.bitpayCardTransactionHistory
};
bitpayCardService.setCacheData(cacheData, function(err) {
if (err) $log.error(err);
});
});
});
}
@ -98,103 +105,11 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi
});
};
this.init = function() {
$scope.dateRange = 'last30Days';
$scope.network = bitpayCardService.getEnvironment();
$scope.wallets = profileService.getWallets({
network: $scope.network,
onlyComplete: true
});
self.update();
wallet = $scope.wallets[0];
if (wallet && wallet.credentials.n > 1)
self.isMultisigWallet = true;
};
this.sendFunds = function() {
if (lodash.isEmpty(wallet)) return;
if (!wallet.canSign() && !wallet.isPrivKeyExternal()) {
$log.info('No signing proposal: No private key');
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg('MISSING_PRIVATE_KEY'));
return;
}
var dataSrc = {
amount: $scope.fiat,
currency: 'USD'
};
var outputs = [];
var config = configService.getSync();
var configWallet = config.wallet;
var walletSettings = configWallet.settings;
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) {
var address, comment, amount;
address = data.bitcoinAddress;
amount = parseInt((data.btcPrice * 100000000).toFixed(0));
comment = data.itemDesc;
outputs.push({
'toAddress': address,
'amount': amount,
'message': comment
});
var txp = {
toAddress: address,
amount: amount,
outputs: outputs,
message: comment,
payProUrl: null,
excludeUnconfirmedUtxos: configWallet.spendUnconfirmed ? false : true,
feeLevel: walletSettings.feeLevel || 'normal'
};
walletService.createTx(wallet, txp, function(err, createdTxp) {
ongoingProcess.set('Processing Transaction...', false);
if (err) {
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err));
return;
}
walletService.publishAndSign(wallet, createdTxp, function(err, tx) {
if (err) {
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err));
return;
}
self.update();
$scope.addFunds = false;
$timeout(function() {
$scope.$digest();
});
});
});
});
});
}, 100);
};
this.authenticate = function() {
this.authenticate = function(email, password) {
var data = {
emailAddress : $scope.email,
hashedPassword : pbkdf2Service.pbkdf2Sync($scope.password, '..............', 200, 64).toString('hex')
emailAddress : email,
hashedPassword : pbkdf2Service.pbkdf2Sync(password, '..............', 200, 64).toString('hex')
};
// POST /authenticate
@ -215,10 +130,10 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi
});
};
this.authenticate2FA = function() {
this.authenticate2FA = function(twoFactorCode) {
var data = {
twoFactorCode : $scope.twoFactorCode
twoFactorCode : twoFactorCode
};
self.authenticating = true;
@ -258,5 +173,9 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi
return tx.description;
};
$scope.$on("$ionicView.beforeEnter", function(event, data){
self.update();
});
});

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.$on("$ionicView.beforeEnter", 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

@ -1,7 +1,7 @@
'use strict';
angular.module('copayApp.controllers').controller('preferencesBitpayCardController',
function($scope, $state, $timeout, bitpayCardService, popupService) {
function($scope, $state, $timeout, $ionicHistory, bitpayCardService, popupService) {
$scope.logout = function() {
var title = 'Are you sure you would like to log out of your Bitpay Card account?';
@ -12,8 +12,9 @@ angular.module('copayApp.controllers').controller('preferencesBitpayCardControll
var logout = function() {
bitpayCardService.logout(function() {
$ionicHistory.removeBackView();
$timeout(function() {
$state.go('bitpayCard.main');
$state.go('tabs.home');
}, 100);
});
};

View File

@ -1,7 +1,7 @@
'use strict';
angular.module('copayApp.controllers').controller('tabHomeController',
function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, gettextCatalog, lodash, popupService, ongoingProcess, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, $window) {
function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, gettextCatalog, lodash, popupService, ongoingProcess, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, $window, bitpayCardService) {
var wallet;
$scope.externalServices = {};
$scope.bitpayCardEnabled = true; // TODO
@ -76,7 +76,7 @@ angular.module('copayApp.controllers').controller('tabHomeController',
});
}
$state.go('tabs.details', {
$state.go('tabs.wallet', {
walletId: wallet.credentials.walletId
});
};
@ -206,7 +206,15 @@ angular.module('copayApp.controllers').controller('tabHomeController',
});
});
var bitpayCardCache = function() {
bitpayCardService.getCacheData(function(err, data) {
if (err || lodash.isEmpty(data)) return;
$scope.bitpayCard = data;
});
};
$scope.$on("$ionicView.enter", function(event, data) {
$scope.bitpayCard = null;
configService.whenAvailable(function() {
var config = configService.getSync();
var isWindowsPhoneApp = platformInfo.isWP && platformInfo.isCordova;
@ -217,6 +225,8 @@ angular.module('copayApp.controllers').controller('tabHomeController',
$scope.bitpayCardEnabled = config.bitpayCard.enabled;
$scope.nextStepEnabled = $scope.glideraEnabled || $scope.coinbaseEnabled || $scope.amazonEnabled || $scope.bitpayCardEnabled;
$scope.recentTransactionsEnabled = config.recentTransactions.enabled;
if ($scope.bitpayCardEnabled) bitpayCardCache();
});
$scope.nextStep();
$scope.updateAllWallets();

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

@ -150,10 +150,10 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
*
*/
.state('tabs.details', {
url: '/details/{walletId}/{fromOnboarding}',
.state('tabs.wallet', {
url: '/wallet/{walletId}/{fromOnboarding}',
views: {
'tab-home': {
'tab-home@tabs': {
controller: 'walletDetailsController',
templateUrl: 'views/walletDetails.html'
}
@ -166,7 +166,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
.state('tabs.activity', {
url: '/activity',
views: {
'tab-home': {
'tab-home@tabs': {
controller: 'activityController',
templateUrl: 'views/activity.html',
}
@ -175,7 +175,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
.state('tabs.proposals', {
url: '/proposals',
views: {
'tab-home': {
'tab-home@tabs': {
controller: 'proposalsController',
templateUrl: 'views/proposals.html',
}
@ -836,29 +836,44 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
}
})
/*
*
* BitPay Card
*
*/
/*
*
* BitPay Card
*
*/
.state('bitpayCard', {
url: '/bitpayCard',
abstract: true,
template: '<ion-nav-view name="bitpayCard"></ion-nav-view>'
})
.state('bitpayCard.main', {
url: '/main',
.state('tabs.bitpayCard', {
url: '/bitpay-card',
views: {
'bitpayCard': {
'tab-home@tabs': {
controller: 'bitpayCardController',
controllerAs: 'bitpayCard',
templateUrl: 'views/bitpayCard.html'
}
}
})
.state('bitpayCard.preferences', {
.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: {
'bitpayCard': {
'tab-home@tabs': {
templateUrl: 'views/preferencesBitpayCard.html'
}
}

View File

@ -187,8 +187,38 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http,
});
};
root.getCacheData = function(cb) {
_setCredentials();
storageService.getBitpayCardCache(credentials.NETWORK, function(err, data) {
if (err) return cb(err);
if (lodash.isString(data)) {
data = JSON.parse(data);
}
data = data || {};
return cb(null, data);
});
};
root.setCacheData = function(data, cb) {
_setCredentials();
data = JSON.stringify(data);
storageService.setBitpayCardCache(credentials.NETWORK, data, function(err) {
if (err) return cb(err);
return cb();
});
};
root.removeCacheData = function(cb) {
_setCredentials();
storageService.removeBitpayCardCache(credentials.NETWORK, function(err) {
if (err) return cb(err);
return cb();
});
};
root.logout = function(cb) {
_setCredentials();
root.removeCacheData(function() {});
storageService.removeBitpayCard(credentials.NETWORK, function(err) {
$http(_getBitPay('/visa-api/logout')).then(function(data) {
$log.info('BitPay Logout: SUCCESS');

View File

@ -833,7 +833,7 @@ angular.module('copayApp.services')
x.action = function() {
// TODO?
// $state.go('tabs.details', {
// $state.go('tabs.wallet', {
// walletId: x.walletId,
// txpId: x.txpId,
// txid: x.txid,

View File

@ -337,6 +337,18 @@ angular.module('copayApp.services')
storage.remove('bitpayCard-' + network, cb);
};
root.setBitpayCardCache = function(network, data, cb) {
storage.set('bitpayCardCache-' + network, data, cb);
};
root.getBitpayCardCache = function(network, cb) {
storage.get('bitpayCardCache-' + network, cb);
};
root.removeBitpayCardCache = function(network, cb) {
storage.remove('bitpayCardCache-' + network, cb);
};
root.removeAllWalletData = function(walletId, cb) {
root.clearLastAddress(walletId, function(err) {
if (err) return cb(err);

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

@ -3,8 +3,7 @@
width: 100%;
text-align: center;
padding: 2rem 1rem 1.5rem 1rem;
min-height: 115px;
margin-bottom: 25px;
min-height: 140px;
border-color: #172565;
background-color: #1e3186;
background-image: linear-gradient(0deg, #172565, #172565 0%, transparent 0%);
@ -13,4 +12,13 @@
strong {
line-height: 100%;
}
.select-style {
border: none;
box-shadow: none;
background-color: transparent;
background-image: none;
margin: 0;
padding: 0;
width: 100%;
}
}

View File

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