diff --git a/src/js/controllers/amount.js b/src/js/controllers/amount.js
index 73ebfd150..c2dcc6cd4 100644
--- a/src/js/controllers/amount.js
+++ b/src/js/controllers/amount.js
@@ -29,6 +29,7 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
vm.finish = finish;
vm.goBack = goBack;
vm.loadMore = loadMore;
+ vm.next = next;
vm.openPopup = openPopup;
vm.pushDigit = pushDigit;
vm.removeDigit = removeDigit;
@@ -66,15 +67,14 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
}
function onBeforeEnter(event, data) {
- console.log('amount onBeforeEnter sendflow ', sendFlowService.getState());
-
if (data.direction == "back") {
sendFlowService.popState();
}
+ console.log('amount onBeforeEnter after back sendflow ', sendFlowService.state);
initCurrencies();
- passthroughParams = sendFlowService;
+ passthroughParams = sendFlowService.getStateClone();
vm.fromWalletId = passthroughParams.fromWalletId;
vm.toWalletId = passthroughParams.toWalletId;
@@ -463,7 +463,7 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
};
if (vm.thirdParty) {
- confirmData['thirdParty'] = this.thirdParty;
+ confirmData.thirdParty = vm.thirdParty;
}
sendFlowService.pushState(confirmData);
@@ -478,7 +478,7 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
// Currency
- var next = 10;
+ var nextCurrencies = 10;
var completeAlternativeList = [];
var popularCurrencyList = [
@@ -537,12 +537,17 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
function loadMore() {
$timeout(function() {
- vm.altCurrencyList = completeAlternativeList.slice(0, next);
- next += 10;
+ vm.altCurrencyList = completeAlternativeList.slice(0, nextCurrencies);
+ nextCurrencies += 10;
vm.listComplete = vm.altCurrencyList.length >= completeAlternativeList.length;
$scope.$broadcast('scroll.infiniteScrollComplete');
}, 100);
- };
+ }
+
+ function next() {
+ useSendMax = false;
+ vm.finish();
+ }
function findCurrency(search) {
if (!search) initCurrencies();
diff --git a/src/js/controllers/review.controller.js b/src/js/controllers/review.controller.js
index a3b015348..3c528c1f9 100644
--- a/src/js/controllers/review.controller.js
+++ b/src/js/controllers/review.controller.js
@@ -75,9 +75,9 @@ function reviewController(addressbookService, bitcoinCashJsService, bitcore, bit
function onBeforeEnter(event, data) {
- console.log('walletSelector onBeforeEnter sendflow ', sendFlowService.getState());
+ console.log('walletSelector onBeforeEnter sendflow ', sendFlowService.state);
defaults = configService.getDefaults();
- sendFlowData = sendFlowService.getState();
+ sendFlowData = sendFlowService.getStateClone();
originWalletId = sendFlowData.fromWalletId;
satoshis = parseInt(sendFlowData.amount, 10);
toAddress = sendFlowData.toAddress;
@@ -116,7 +116,9 @@ function reviewController(addressbookService, bitcoinCashJsService, bitcore, bit
if (!tx || !vm.originWallet) return;
if (vm.paymentExpired) {
- popupService.showAlert(null, gettextCatalog.getString('This bitcoin payment request has expired.'));
+ popupService.showAlert(null, gettextCatalog.getString('This bitcoin payment request has expired.', function () {
+ $ionicHistory.goBack();
+ }));
vm.sendStatus = '';
$timeout(function() {
$scope.$apply();
@@ -223,7 +225,7 @@ function reviewController(addressbookService, bitcoinCashJsService, bitcore, bit
// Grab stateParams
tx = {
amount: parseInt(sendFlowData.amount),
- sendMax: sendFlowData.sendMax === 'true' ? true : false,
+ sendMax: sendFlowData.sendMax,
fromWalletId: sendFlowData.fromWalletId,
toAddress: sendFlowData.toAddress,
paypro: txPayproData,
@@ -486,20 +488,26 @@ function reviewController(addressbookService, bitcoinCashJsService, bitcore, bit
walletService.getAddress(vm.originWallet, false, function onReturnWalletAddress(err, returnAddr) {
if (err) {
ongoingProcess.set('connectingShapeshift', false);
- popupService.showAlert(gettextCatalog.getString('Shapeshift Error'), err.toString());
+ popupService.showAlert(gettextCatalog.getString('Shapeshift Error'), err.toString(), function () {
+ $ionicHistory.goBack();
+ });
return;
}
walletService.getAddress(toWallet, false, function onWithdrawalWalletAddress(err, withdrawalAddr) {
if (err) {
ongoingProcess.set('connectingShapeshift', false);
- popupService.showAlert(gettextCatalog.getString('Shapeshift Error'), err.toString());
+ popupService.showAlert(gettextCatalog.getString('Shapeshift Error'), err.toString(), function () {
+ $ionicHistory.goBack();
+ });
return;
}
shapeshiftService.shiftIt(vm.originWallet.coin, toWallet.coin, withdrawalAddr, returnAddr, function onShiftIt(err, shapeshiftData) {
if (err && err != null) {
ongoingProcess.set('connectingShapeshift', false);
- popupService.showAlert(gettextCatalog.getString('Shapeshift Error'), err.toString());
+ popupService.showAlert(gettextCatalog.getString('Shapeshift Error'), err.toString(), function () {
+ $ionicHistory.goBack();
+ });
} else {
vm.memo = 'ShapeShift Order:\nhttps://www.shapeshift.io/#/status/' + shapeshiftData.orderId;
vm.memoExpanded = !!vm.memo;
@@ -640,7 +648,9 @@ function reviewController(addressbookService, bitcoinCashJsService, bitcore, bit
$timeout(function() {
$scope.$apply();
});
- popupService.showAlert(gettextCatalog.getString('Error at confirm'), bwcError.msg(msg));
+ popupService.showAlert(gettextCatalog.getString('Error at confirm'), bwcError.msg(msg), function () {
+ $ionicHistory.goBack();
+ });
};
function setupTx(tx) {
@@ -825,7 +835,9 @@ function reviewController(addressbookService, bitcoinCashJsService, bitcore, bit
if (tx.sendMax && sendMaxInfo.amount == 0) {
ongoingProcess.set('calculatingFee', false);
setNotReady(gettextCatalog.getString('Insufficient confirmed funds'));
- popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not enough funds for fee'));
+ popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not enough funds for fee'), function () {
+ $ionicHistory.goBack();
+ });
return cb('no_funds');
}
diff --git a/src/js/controllers/tab-home.js b/src/js/controllers/tab-home.js
index 51d500de7..318fcece2 100644
--- a/src/js/controllers/tab-home.js
+++ b/src/js/controllers/tab-home.js
@@ -1,7 +1,7 @@
'use strict';
angular.module('copayApp.controllers').controller('tabHomeController',
- function($rootScope, sendFlowService, $timeout, $scope, $state, $stateParams, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, bannerService, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, appConfigService, startupService, addressbookService, bwcError, nextStepsService, buyAndSellService, homeIntegrationsService, bitpayCardService, pushNotificationsService, timeService, $ionicNavBarDelegate) {
+ function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, bannerService, communityService, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, sendFlowService, storageService, txpModalService, appConfigService, startupService, addressbookService, bwcError, nextStepsService, buyAndSellService, homeIntegrationsService, bitpayCardService, pushNotificationsService, timeService, bitcoincomService, pricechartService, firebaseEventsService, servicesService, shapeshiftService, $ionicNavBarDelegate, signVerifyMessageService) {
var wallet;
var listeners = [];
var notifications = [];
@@ -58,7 +58,7 @@ angular.module('copayApp.controllers').controller('tabHomeController',
});
}
};
-
+
function onEnter(event, data) {
$ionicNavBarDelegate.showBar(true);
updateAllWallets();
@@ -214,6 +214,7 @@ angular.module('copayApp.controllers').controller('tabHomeController',
var j = 0;
lodash.each(wallets, function(wallet) {
+ walletService.invalidateCache(wallet); // Temporary solution, to have the good balance, when we ask to reload the wallets.
walletService.getStatus(wallet, {}, function(err, status) {
if (err) {
diff --git a/src/js/controllers/tab-receive.js b/src/js/controllers/tab-receive.js
index 190f1b752..0e80f4382 100644
--- a/src/js/controllers/tab-receive.js
+++ b/src/js/controllers/tab-receive.js
@@ -1,6 +1,6 @@
'use strict';
-angular.module('copayApp.controllers').controller('tabReceiveController', function($rootScope, $scope, $timeout, $log, $ionicModal, $state, $ionicHistory, $ionicPopover, storageService, platformInfo, walletService, profileService, configService, lodash, gettextCatalog, popupService, bwcError, bitcoinCashJsService, $ionicNavBarDelegate, txFormatService, soundService, clipboardService) {
+angular.module('copayApp.controllers').controller('tabReceiveController', function($rootScope, $scope, $timeout, $log, $ionicModal, $state, $ionicHistory, $ionicPopover, storageService, platformInfo, walletService, profileService, configService, lodash, gettextCatalog, popupService, bwcError, bitcoinCashJsService, $ionicNavBarDelegate, sendFlowService, txFormatService, soundService, clipboardService) {
var listeners = [];
$scope.bchAddressType = { type: 'cashaddr' };
@@ -18,9 +18,10 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
$scope.displayBalanceAsFiat = true;
$scope.requestSpecificAmount = function() {
- $state.go('tabs.paymentRequest.amount', {
+ sendFlowService.pushState({
toWalletId: $scope.wallet.credentials.walletId
});
+ $state.go('tabs.paymentRequest.amount');
};
$scope.setAddress = function(newAddr, copyAddress) {
@@ -158,6 +159,10 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
soundService.play('misc/payment_received.mp3');
}
+ // Notify new tx
+ $scope.$emit('bwsEvent', $scope.wallet.id);
+
+
$scope.$apply(function () {
$scope.showingPaymentReceived = true;
});
diff --git a/src/js/controllers/tab-send.js b/src/js/controllers/tab-send.js
index 81b3e4ca5..9ac6c35cb 100644
--- a/src/js/controllers/tab-send.js
+++ b/src/js/controllers/tab-send.js
@@ -28,14 +28,15 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
};
$scope.$on("$ionicView.enter", function(event, data) {
+
+ var stateParams = sendFlowService.getStateClone();
+ $scope.fromWallet = profileService.getWallet(stateParams.fromWalletId);
+
clipboardService.readFromClipboard(function(text) {
if (text.length > 200) {
text = text.substring(0, 200);
}
- var stateParams = sendFlowService.getState();
- $scope.fromWallet = profileService.getWallet(stateParams.fromWalletId);
-
$scope.clipboardHasAddress = false;
$scope.clipboardHasContent = false;
if ((text.indexOf('bitcoincash:') === 0 || text[0] === 'C' || text[0] === 'H' || text[0] === 'p' || text[0] === 'q') && text.replace('bitcoincash:', '').length === 42) { // CashAddr
@@ -183,7 +184,7 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
$log.debug('Got toAddress:' + toAddress + ' | ' + item.name);
- var stateParams = sendFlowService.getState();
+ var stateParams = sendFlowService.getStateClone();
stateParams.toAddress = toAddress,
stateParams.coin = item.coin;
sendFlowService.pushState(stateParams);
@@ -199,7 +200,7 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
$scope.startWalletToWalletTransfer = function() {
console.log('startWalletToWalletTransfer()');
- var params = sendFlowService.getState();
+ var params = sendFlowService.getStateClone();
sendFlowService.pushState(params);
$state.transitionTo('tabs.send.wallet-to-wallet', {
fromWalletId: sendFlowService.fromWalletId
@@ -221,7 +222,7 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
$scope.$on("$ionicView.beforeEnter", function(event, data) {
console.log(data);
- console.log('tab-send onBeforeEnter sendflow ', sendFlowService.getState());
+ console.log('tab-send onBeforeEnter sendflow ', sendFlowService.state);
$scope.isIOS = platformInfo.isIOS && platformInfo.isCordova;
$scope.showWalletsBch = $scope.showWalletsBtc = $scope.showWallets = false;
diff --git a/src/js/controllers/walletDetails.js b/src/js/controllers/walletDetails.js
index e6a8e2351..1aaef7581 100644
--- a/src/js/controllers/walletDetails.js
+++ b/src/js/controllers/walletDetails.js
@@ -304,6 +304,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
};
function refreshAmountSection(scrollPos) {
+ var AMOUNT_HEIGHT_BASE = 270;
$scope.showBalanceButton = false;
if ($scope.status) {
$scope.showBalanceButton = ($scope.status.totalBalanceSat != $scope.status.spendableAmount);
@@ -315,16 +316,16 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
}
scrollPos = scrollPos || 0;
- var amountHeight = 210 - scrollPos;
+ var amountHeight = AMOUNT_HEIGHT_BASE - scrollPos;
if (amountHeight < 80) {
amountHeight = 80;
}
var contentMargin = amountHeight;
- if (contentMargin > 210) {
- contentMargin = 210;
+ if (contentMargin > AMOUNT_HEIGHT_BASE) {
+ contentMargin = AMOUNT_HEIGHT_BASE;
}
- var amountScale = (amountHeight / 210);
+ var amountScale = (amountHeight / AMOUNT_HEIGHT_BASE);
if (amountScale < 0.5) {
amountScale = 0.5;
}
diff --git a/src/js/controllers/walletSelectorController.js b/src/js/controllers/walletSelectorController.js
index 74ed874d4..7a7c5a463 100644
--- a/src/js/controllers/walletSelectorController.js
+++ b/src/js/controllers/walletSelectorController.js
@@ -11,13 +11,12 @@ angular.module('copayApp.controllers').controller('walletSelectorController', fu
$scope.$on("$ionicView.enter", onEnter);
function onBeforeEnter(event, data) {
- console.log('walletSelector onBeforeEnter sendflow', sendFlowService.getState());
-
if (data.direction == "back") {
sendFlowService.popState();
}
+ console.log('walletSelector onBeforeEnter after back sendflow', sendFlowService.state);
- var stateParams = sendFlowService.getState();
+ $scope.params = sendFlowService.getStateClone();
var config = configService.getSync().wallet.settings;
priceDisplayAsFiat = config.priceDisplay === 'fiat';
@@ -29,21 +28,23 @@ angular.module('copayApp.controllers').controller('walletSelectorController', fu
$scope.sendFlowTitle = gettextCatalog.getString('Wallet to Wallet Transfer');
break;
case 'tabs.send.destination':
- if (stateParams.fromWalletId) {
+ if ($scope.params.fromWalletId && !$scope.params.thirdParty) {
$scope.sendFlowTitle = gettextCatalog.getString('Wallet to Wallet Transfer');
}
break;
default:
+ if (!$scope.params.thirdParty) {
+ $scope.sendFlowTitle = gettextCatalog.getString('Send');
+ }
// nop
}
- $scope.params = sendFlowService;
$scope.coin = false; // Wallets to show (for destination screen or contacts)
$scope.type = $scope.params['fromWalletId'] ? 'destination' : 'origin'; // origin || destination
fromWalletId = $scope.params['fromWalletId'];
if ($scope.type === 'destination' && $scope.params.toAddress) {
- $state.transitionTo(getNextStep());
+ $state.transitionTo(getNextStep($scope.params));
}
if ($scope.params.coin) {
@@ -103,13 +104,10 @@ angular.module('copayApp.controllers').controller('walletSelectorController', fu
}
}
- function getNextStep() {
- if ($scope.thirdParty) {
- $scope.params.thirdParty = $scope.thirdParty
- }
- if (!$scope.params.toWalletId && !$scope.params.toAddress) { // If we have no toAddress or fromWallet
+ function getNextStep(params) {
+ if (!params.toWalletId && !params.toAddress) { // If we have no toAddress or fromWallet
return 'tabs.send.destination';
- } else if (!$scope.params.amount) { // If we have no amount
+ } else if (!params.amount) { // If we have no amount
return 'tabs.send.amount';
} else { // If we do have them
return 'tabs.send.review';
@@ -193,14 +191,16 @@ angular.module('copayApp.controllers').controller('walletSelectorController', fu
$scope.useWallet = function(wallet) {
- var params = sendFlowService.getState();
+ var params = sendFlowService.getStateClone();
if ($scope.type === 'origin') { // we're on the origin screen, set wallet to send from
params.fromWalletId = wallet.id;
} else { // we're on the destination screen, set wallet to send to
params.toWalletId = wallet.id;
}
sendFlowService.pushState(params);
- $state.transitionTo(getNextStep(), $scope.params);
+ var nextStep = getNextStep(params);
+ console.log('walletSelector nextStep', nextStep);
+ $state.transitionTo(nextStep, $scope.params);
};
$scope.goBack = function() {
diff --git a/src/js/directives/formattedAmount.js b/src/js/directives/formattedAmount.js
index c0c341631..f81615593 100644
--- a/src/js/directives/formattedAmount.js
+++ b/src/js/directives/formattedAmount.js
@@ -1,5 +1,6 @@
'use strict';
+(function(){
/**
* @desc amount directive that can be used to display formatted financial values
* size-equal attribute is optional, defaults to false.
@@ -10,168 +11,189 @@
* @example
* @example
*/
-angular.module('bitcoincom.directives')
- .directive('formattedAmount', function(uxLanguage) {
- return {
- restrict: 'E',
- scope: {
- value: '@',
- currency: '@',
- sizeEqual: '@'
- },
- templateUrl: 'views/includes/formatted-amount.html',
- controller: function($scope, $timeout) {
- $scope.canShow = false;
-
- $scope.displaySizeEqual = !!$scope.sizeEqual;
-
- $timeout(function onFormattedAmountTimeout() {
-
- var decimalPlaces = {
- '0': ['BIF', 'CLP', 'DJF', 'GNF', 'ILS', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'UGX', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'],
- '3': ['BHD', 'IQD', 'JOD', 'KWD', 'OMR', 'TND'],
- '8': ['BCH', 'BTC']
- };
- var localizeNumbers = function(x, minimumFractionDigits) {
- var parsed = parseFloat(x);
- var opts = {
- minimumFractionDigits: minimumFractionDigits,
- useGrouping: true
- };
- var lang = uxLanguage.getCurrentLanguage();
- var localized = parsed.toLocaleString(lang, opts);
- var corrected = ensureEnoughFractionalDigits(localized, x, minimumFractionDigits);
- return corrected;
- };
-
- var buildAmount = function(start, middle, end) {
- $scope.start = start;
- $scope.middle = middle;
- $scope.end = end;
- };
-
- var getDecimalPlaces = function(currency) {
- if (decimalPlaces['0'].indexOf(currency.toUpperCase()) > -1) return '0';
- if (decimalPlaces['3'].indexOf(currency.toUpperCase()) > -1) return '3';
- if (decimalPlaces['8'].indexOf(currency.toUpperCase()) > -1) return '8';
- return '2';
- };
-
- var getDecimalSeparator = function() {
- var testNum = 1.5;
- var testString = testNum.toLocaleString(uxLanguage.getCurrentLanguage());
- // Some environments let you set decimal separators that are more than one character
- var separator = /^1(.+)5$/.exec(testString)[1]
- return separator;
- };
-
- var formatNumbers = function() {
- // During watch, may be changed from having a separate currency value,
- // to both being in value. Don't want to use previous currency value.
- // Try to extract currency from value..
- var currencySplit = $scope.value.split(" ");
- if (currencySplit.length === 2) {
- $scope.currency = currencySplit[1];
- }
- $scope.currency = $scope.currency || '';
-
-
- var parsed = parseFloat($scope.value);
- var valueFormatted = '';
- var valueProcessing = '';
- switch (getDecimalPlaces($scope.currency)) {
- case '0':
- if (isNaN(parsed)) {
- buildAmount('-', '', '');
- } else {
- valueFormatted = localizeNumbers(Math.round(parsed), 0);
- buildAmount(valueFormatted, '', '');
- }
- break;
-
- case '3':
- if (isNaN(parsed)) {
- buildAmount('-' + getDecimalSeparator() + '---', '', '');
- } else {
- valueProcessing = parsed.toFixed(3);
- valueFormatted = localizeNumbers(valueProcessing, 3);
- buildAmount(valueFormatted, '', '');
- }
- break;
-
- case '8':
- if (isNaN(parsed)) {
- buildAmount('-' + getDecimalSeparator() + '---', '', '');
- } else if (parsed === 0) {
- buildAmount('0', '', '');
- } else {
- valueFormatted = parsed.toFixed(8);
- valueFormatted = localizeNumbers(valueFormatted, 8);
- var start = valueFormatted.slice(0, -5);
- var middle = valueFormatted.slice(-5, -2);
- var end = valueFormatted.substr(valueFormatted.length - 2);
- buildAmount(start, middle, end);
-
- }
- break;
-
- default: // 2
- if (isNaN(parsed)) {
- buildAmount('-' + getDecimalSeparator() + '--', '', '');
- } else {
- valueProcessing = parseFloat(parsed.toFixed(2));
- valueFormatted = localizeNumbers(valueProcessing, 2);
- buildAmount(valueFormatted, '', '');
- }
- break;
- }
- $scope.canShow = true;
- };
-
- formatNumbers();
- $scope.$watchGroup(['currency', 'value'], function onFormattedAmountWatch() {
- formatNumbers();
- });
-
- /**
- * On Android 4.4, toLocaleString() only returns 3 fractional digits when 8 is specified.
- */
- function ensureEnoughFractionalDigits(localizedString, number, desiredFractionDigits) {
- if (desiredFractionDigits === 0) {
- // Assume it is OK
- return localizedString;
- }
- var fractionalRe = /^(\d*\D)(\d+)$/;
- var match = fractionalRe.exec(localizedString);
- if (match.length !== 3) {
- // Don't know what's happening, just return what we have
- return localizedString;
- }
-
- var decimals = match[2];
- var decimalCount = decimals.length;
- if (decimalCount >= desiredFractionDigits) {
- // Everything is OK.
- return localizedString;
- }
-
- if (typeof number !== 'number') {
- number = parseFloat(number);
- }
-
- var fixed = number.toFixed(desiredFractionDigits);
- var fixedMatch = fractionalRe.exec(fixed);
- if (fixedMatch.length !== 3) {
- // Don't know what's happening, just return what we have
- return localizedString;
- }
-
- // Keeps locale decimal separator.
- var enough = match[1] + fixedMatch[2];
- return enough;
- }
- });
+ angular
+ .module('bitcoincom.directives')
+ .directive('formattedAmount', function() {
+ return {
+ restrict: 'E',
+ scope: {
+ value: '@',
+ currency: '@',
+ sizeEqual: '@'
+ },
+ templateUrl: 'views/includes/formatted-amount.html',
+ controller: formattedAmountController
}
+ });
+
+ function formattedAmountController($scope, uxLanguage) {
+ $scope.vm = {};
+ var vm = $scope.vm;
+
+ vm.currency = '';
+ vm.value = '';
+
+ $scope.canShow = false
+ $scope.displaySizeEqual = !!$scope.sizeEqual;
+
+ var decimalPlaces = {
+ '0': ['BIF', 'CLP', 'DJF', 'GNF', 'ILS', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'UGX', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'],
+ '3': ['BHD', 'IQD', 'JOD', 'KWD', 'OMR', 'TND'],
+ '8': ['BCH', 'BTC']
+ };
+
+ $scope.$watch('value', function onFormattedAmountWatch() {
+ formatNumbers();
+ });
+
+ function buildAmount(start, middle, end) {
+ $scope.start = start;
+ $scope.middle = middle;
+ $scope.end = end;
+ };
+
+ /**
+ * On Android 4.4, toLocaleString() only returns 3 fractional digits when 8 is specified.
+ */
+ function ensureEnoughFractionDigits(localizedString, number, desiredFractionDigits) {
+ if (desiredFractionDigits === 0) {
+ // Assume it is OK
+ return localizedString;
+ }
+ var fractionalRe = /^-*(\d*\D)(\d+)$/;
+ var match = fractionalRe.exec(localizedString);
+ if (!match || match.length !== 3) {
+ // Don't know what's happening, just return what we have
+ return localizedString;
+ }
+
+ var decimals = match[2];
+ var decimalCount = decimals.length;
+ if (decimalCount >= desiredFractionDigits) {
+ // Everything is OK.
+ return localizedString;
+ }
+
+ if (typeof number !== 'number') {
+ number = parseFloat(number);
+ }
+
+ var fixed = number.toFixed(desiredFractionDigits);
+ var fixedMatch = fractionalRe.exec(fixed);
+ if (!fixedMatch || fixedMatch.length !== 3) {
+ // Don't know what's happening, just return what we have
+ return localizedString;
+ }
+
+ // Keeps locale decimal separator.
+ var enough = match[1] + fixedMatch[2];
+ return enough;
+ }
+
+ function formatNumbers() {
+ // Might get "< 0.01 USD" being passed in.
+ // During watch, may be changed from having a separate currency value,
+ // to both being in value. Don't want to use previous currency value.
+ // Try to extract currency from value..
+ if (!$scope.currency || $scope.currency.length === 0) {
+ var currencySplit = $scope.value.split(" ");
+ if (currencySplit.length >= 2) {
+ vm.currency = currencySplit[currencySplit.length - 1];
+ }
+ } else {
+ vm.currency = $scope.currency;
+ }
+
+ // Redo this when we have proper formatting for low fees
+ if ($scope.value.indexOf("<") === 0) {
+ buildAmount($scope.value, '', '');
+ vm.currency = '';
+ $scope.canShow = true;
+ return;
+ }
+
+ // Remove thousands separators for parseFloat()
+ $scope.value = $scope.value.replace(',', '');
+
+ var parsed = parseFloat($scope.value);
+ var valueFormatted = '';
+ var valueProcessing = '';
+ switch (getDecimalPlaces(vm.currency)) {
+ case '0':
+ if (isNaN(parsed)) {
+ buildAmount('-', '', '');
+ } else {
+ valueFormatted = localizeNumbers(Math.round(parsed), 0);
+ buildAmount(valueFormatted, '', '');
+ }
+ break;
+
+ case '3':
+ if (isNaN(parsed)) {
+ buildAmount('-' + getDecimalSeparator() + '---', '', '');
+ } else {
+ valueProcessing = parsed.toFixed(3);
+ valueFormatted = localizeNumbers(valueProcessing, 3);
+ buildAmount(valueFormatted, '', '');
+ }
+ break;
+
+ case '8':
+ if (isNaN(parsed)) {
+ buildAmount('-' + getDecimalSeparator() + '---', '', '');
+ } else if (parsed === 0) {
+ buildAmount('0', '', '');
+ } else {
+ valueFormatted = parsed.toFixed(8);
+ valueFormatted = localizeNumbers(valueFormatted, 8);
+ var start = valueFormatted.slice(0, -5);
+ var middle = valueFormatted.slice(-5, -2);
+ var end = valueFormatted.substr(valueFormatted.length - 2);
+ buildAmount(start, middle, end);
+
+ }
+ break;
+
+ default: // 2
+ if (isNaN(parsed)) {
+ buildAmount('-' + getDecimalSeparator() + '--', '', '');
+ } else {
+ valueProcessing = parseFloat(parsed.toFixed(2));
+ valueFormatted = localizeNumbers(valueProcessing, 2);
+ buildAmount(valueFormatted, '', '');
+ }
+ break;
+ }
+ $scope.canShow = true;
+ $scope.$apply();
+ };
+
+ function getDecimalPlaces(currency) {
+ if (decimalPlaces['0'].indexOf(currency.toUpperCase()) > -1) return '0';
+ if (decimalPlaces['3'].indexOf(currency.toUpperCase()) > -1) return '3';
+ if (decimalPlaces['8'].indexOf(currency.toUpperCase()) > -1) return '8';
+ return '2';
+ };
+
+ function getDecimalSeparator() {
+ var testNum = 1.5;
+ var testString = testNum.toLocaleString(uxLanguage.getCurrentLanguage());
+ // Some environments let you set decimal separators that are more than one character
+ var separator = /^1(.+)5$/.exec(testString)[1]
+ return separator;
+ };
+
+ function localizeNumbers(x, minimumFractionDigits) {
+ var parsed = parseFloat(x);
+ var opts = {
+ minimumFractionDigits: minimumFractionDigits,
+ useGrouping: true
+ };
+ var lang = uxLanguage.getCurrentLanguage();
+ var localized = parsed.toLocaleString(lang, opts);
+ var corrected = ensureEnoughFractionDigits(localized, x, minimumFractionDigits);
+ return corrected;
};
}
-);
\ No newline at end of file
+
+})();
\ No newline at end of file
diff --git a/src/js/directives/walletBalanceDirective.js b/src/js/directives/walletBalanceDirective.js
new file mode 100644
index 000000000..1fea59203
--- /dev/null
+++ b/src/js/directives/walletBalanceDirective.js
@@ -0,0 +1,120 @@
+'use strict';
+
+(function(){
+
+ angular
+ .module('bitcoincom.directives')
+ .directive('walletBalance', function() {
+ return {
+ restrict: 'E',
+ scope: {
+ displayAsFiat: '@',
+ totalBalanceSat: '@',
+ // The Wallet object is sometimes not stringify()-able, so not interpolatable,
+ // so can't be passed to a directive.
+ walletStatus: '@',
+ walletCachedBalance: '@',
+ walletCachedBalanceUpdatedOn: '@',
+ walletCachedStatus: '@'
+ },
+ templateUrl: 'views/includes/wallet-balance.html',
+ controller: walletBalanceController
+ }
+ });
+
+ function walletBalanceController($log, $scope, txFormatService) {
+ var cryptoBalanceHasBeenDisplayed = false;
+
+ formatBalance();
+ $scope.$watchGroup(['displayAsFiat', 'totalBalanceSat'], function onWalletBalanceWatch() {
+ formatBalance();
+ });
+
+ function displayCryptoBalance(walletStatus, walletCachedBalance, walletCachedBalanceUpdatedOn, walletCachedStatus) {
+ console.log('displayCryptoBalance()');
+
+ if (walletStatus && walletStatus.isValid && walletStatus.totalBalanceStr) {
+ setDisplay(walletStatus.totalBalanceStr, '');
+ cryptoBalanceHasBeenDisplayed = true;
+ return;
+ }
+
+ if (walletCachedBalance) {
+ setDisplay(walletCachedBalance, walletCachedBalanceUpdatedOn);
+ return;
+ }
+
+ if (walletCachedStatus && walletCachedStatus.isValid && walletCachedStatus.totalBalanceStr) {
+ setDisplay(walletCachedStatus.totalBalanceStr, '');
+ return;
+ }
+
+ setDisplay('', '');
+ }
+
+ function displayFiatBalance(walletStatus, walletCachedStatus) {
+ var displayAmount = '';
+ if (walletStatus && walletStatus.isValid && walletStatus.alternativeBalanceAvailable) {
+ displayAmount = walletStatus.totalBalanceAlternative + ' ' + walletStatus.alternativeIsoCode;
+ setDisplay(displayAmount, '');
+ return;
+ }
+
+ if (walletCachedStatus && walletCachedStatus.isValid && walletCachedStatus.alternativeBalanceAvailable) {
+ displayAmount = walletCachedStatus.totalBalanceAlternative + ' ' + walletCachedStatus.alternativeIsoCode;
+ setDisplay(displayAmount, '');
+ return;
+ }
+
+ getFiatBalance(wallet);
+ }
+
+ function formatBalance() {
+ var displayAsFiat = $scope.displayAsFiat === 'true';
+
+ var walletStatusObj = null;
+ var walletCachedBalance = null;
+ var walletCachedBalanceUpdatedOn = null;
+ var walletCachedStatusObj = null;
+
+ try {
+ walletStatusObj = JSON.parse($scope.walletStatus);
+ } catch (e) {
+ $log.warn('Failed to parse walletStatus.', e);
+ }
+
+ try {
+ walletCachedStatusObj = JSON.parse($scope.walletCachedStatus);
+ } catch (e) {
+ $log.warn('Failed to parse walletCachedStatus.', e);
+ }
+
+ if (!displayAsFiat || displayAsFiat && !cryptoBalanceHasBeenDisplayed) {
+ displayCryptoBalance(walletStatusObj, walletCachedBalance, walletCachedBalanceUpdatedOn, walletCachedStatusObj);
+ }
+
+ if (displayAsFiat) {
+ displayFiatBalance(walletStatusObj, walletCachedStatusObj);
+ }
+ }
+
+ function getFiatBalance(wallet) {
+ if (!(wallet.status && wallet.status.isValid)) {
+ $log.warn('Abandoning call to get fiat balance, because no valid wallet status.');
+ return;
+ }
+
+ txFormatService.formatAlternativeStr(wallet.coin, wallet.status.totalBalanceSat, function onFormatAlernativeStr(formatted) {
+ if (formatted) {
+ setDisplay(formatted, '');
+ }
+ });
+ }
+
+ function setDisplay(amount, cachedBalanceUpdatedOn) {
+ $scope.displayAmount = amount;
+ $scope.cachedBalanceUpdatedOn = cachedBalanceUpdatedOn;
+ }
+ }
+})();
+
diff --git a/src/js/routes.js b/src/js/routes.js
index b5a9c91fe..d2b78aac3 100644
--- a/src/js/routes.js
+++ b/src/js/routes.js
@@ -1277,6 +1277,13 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
});
window.BitAnalytics.ActionHandlers.trackAction(actionTabOpen);
+ var actionShapeShiftStart = new window.BitAnalytics.ActionFactory.createAction('click', {
+ name: 'shapeshift_start_click',
+ class: 'track_shapeshift_start_click',
+ channels: [channel]
+ });
+ window.BitAnalytics.ActionHandlers.trackAction(actionShapeShiftStart);
+
// Init language
uxLanguage.init(function (lang) {
diff --git a/src/js/services/incomingData.js b/src/js/services/incomingData.js
index 86c928a5e..9fad8b0f5 100644
--- a/src/js/services/incomingData.js
+++ b/src/js/services/incomingData.js
@@ -82,7 +82,7 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
});
// Timeout is required to enable the "Back" button
$timeout(function() {
- var params = sendFlowService.getState();
+ var params = sendFlowService.getStateClone();
if (amount) {
params.amount = amount;
@@ -447,7 +447,7 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
amount: thirdPartyData.amount,
toAddress: thirdPartyData.toAddress,
coin: coin,
- thirdParty: JSON.stringify(thirdPartyData)
+ thirdParty: thirdPartyData
};
// fee
@@ -455,6 +455,9 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
stateParams.requiredFeeRate = thirdPartyData.requiredFeeRate * 1024;
}
+ // This does not make sense, thirdPartyData gets added by stateParams below
+ //sendFlowService.pushState(thirdPartyData);
+
scannerService.pausePreview();
$state.go('tabs.send', {}, {
'reload': true,
diff --git a/src/js/services/sendFlowService.js b/src/js/services/sendFlowService.js
index 29686b15b..fcb061c26 100644
--- a/src/js/services/sendFlowService.js
+++ b/src/js/services/sendFlowService.js
@@ -9,17 +9,21 @@ angular
function sendFlowService($log) {
var service = {
- amount: '',
- fromWalletId: '',
- sendMax: false,
- thirdParty: null,
- toAddress: '',
- toWalletId: '',
+ // A separate state variable so we can ensure it is cleared of everything,
+ // even other properties added that this service does not know about. (such as "coin")
+ state: {
+ amount: '',
+ fromWalletId: '',
+ sendMax: false,
+ thirdParty: null,
+ toAddress: '',
+ toWalletId: ''
+ },
previousStates: [],
// Functions
clear: clear,
- getState: getState,
+ getStateClone: getStateClone,
map: map,
popState: popState,
pushState: pushState,
@@ -36,22 +40,24 @@ angular
function clearCurrent() {
console.log("sendFlow clearCurrent()");
- service.amount = '';
- service.fromWalletId = '';
- service.sendMax = false;
- service.thirdParty = null;
- service.toAddress = '';
- service.toWalletId = '';
+ service.state = {
+ amount: '',
+ fromWalletId: '',
+ sendMax: false,
+ thirdParty: null,
+ toAddress: '',
+ toWalletId: ''
+ }
}
/**
* Handy for debugging
*/
- function getState() {
+ function getStateClone() {
var currentState = {};
- Object.keys(service).forEach(function forCurrentParam(key) {
- if (typeof service[key] !== 'function' && key !== 'previousStates') {
- currentState[key] = service[key];
+ Object.keys(service.state).forEach(function forCurrentParam(key) {
+ if (typeof service.state[key] !== 'function' && key !== 'previousStates') {
+ currentState[key] = service.state[key];
}
});
return currentState;
@@ -68,7 +74,7 @@ angular
function map(params) {
Object.keys(params).forEach(function forNewParam(key) {
- service[key] = params[key];
+ service.state[key] = params[key];
});
};
@@ -85,7 +91,7 @@ angular
function pushState(params) {
console.log('sendFlow push');
- var currentParams = getState();
+ var currentParams = getStateClone();
service.previousStates.push(currentParams);
clearCurrent();
map(params);
diff --git a/src/js/services/servicesService.js b/src/js/services/servicesService.js
index f2344dd01..316009957 100644
--- a/src/js/services/servicesService.js
+++ b/src/js/services/servicesService.js
@@ -1,7 +1,12 @@
'use strict'
angular.module('copayApp.services').factory('servicesService', function(configService, $log, lodash) {
var root = {};
- var services = [];
+ var services = [{
+ name: 'shapeshift',
+ title: 'Shapeshift',
+ icon: 'icon-shapeshift',
+ sref: 'tabs.shapeshift',
+ }];
root.register = function(serviceInfo) {
$log.info('Adding Services entry:' + serviceInfo.name);
diff --git a/src/js/services/shapeshiftService.js b/src/js/services/shapeshiftService.js
index 7cf6b4e03..1ce9672ce 100644
--- a/src/js/services/shapeshiftService.js
+++ b/src/js/services/shapeshiftService.js
@@ -137,17 +137,5 @@ angular.module('copayApp.services').factory('shapeshiftService', function ($http
});
};
- var servicesItem = {
- name: 'shapeshift',
- title: 'Shapeshift',
- icon: 'icon-shapeshift',
- sref: 'tabs.shapeshift',
- };
-
- var register = function() {
- servicesService.register(servicesItem);
- };
-
- register();
return root;
});
diff --git a/src/sass/buttons.scss b/src/sass/buttons.scss
index 41ec3f674..df0ce8945 100644
--- a/src/sass/buttons.scss
+++ b/src/sass/buttons.scss
@@ -74,7 +74,7 @@
color: #FFF;
}
&-outline {
- @include button-style(transparent, #FFFFFF, #FAFAFA, #FFF, #FFFFFF);
+ @include button-style(transparent, #FFFFFF, #FFFFFF, #FFFFFF, #FFFFFF);
@include button-outline(#FFFFFF);
background: none;
box-shadow: none;
diff --git a/src/sass/components/components.scss b/src/sass/components/components.scss
index fb53508b0..4d2bd695e 100644
--- a/src/sass/components/components.scss
+++ b/src/sass/components/components.scss
@@ -9,3 +9,4 @@
@import "expand-content";
@import "fee-summary";
@import "formatted-amount";
+@import "wallet-balance";
diff --git a/src/sass/components/wallet-balance.scss b/src/sass/components/wallet-balance.scss
new file mode 100644
index 000000000..faf4e8611
--- /dev/null
+++ b/src/sass/components/wallet-balance.scss
@@ -0,0 +1,3 @@
+.wallet-balance-directive {
+ display: inline-block;
+}
\ No newline at end of file
diff --git a/src/sass/views/amount.scss b/src/sass/views/amount.scss
index ca32c6ac4..bf4d3506a 100644
--- a/src/sass/views/amount.scss
+++ b/src/sass/views/amount.scss
@@ -305,7 +305,8 @@
&.very-long {
input, .unit, .primary-amount-display {
- font-size: 0.9em;
+ font-size: 1.2em; // OK for iPhone 5 / SE with BCH to 8dp
+
@media (min-width: 375px) {
font-size: 1.3em;
@@ -382,41 +383,46 @@
.available-funds {
color: #6F6F70;
+ text-align: left;
+ }
+
+ .change-currency {
+ text-align: right;
}
.warning {
color: $v-warning-color-2;
}
- .extra,
- button.extra {
- /*display: flex;*/
- flex: 0 1 auto;
- }
-
- button.extra {
- background: none;
- border: none;
- color: #000;
- font-family: 'ProximaNova';
- font-size: 14px;
+ .extra {
+ flex: 1;
line-height: normal;
- min-height: auto;
- min-width: auto;
- padding: 0;
- }
- .button .icon:before {
- font-size: 14px;
- line-height: normal;
- }
-
+ .button {
+ background: none;
+ border: none;
+ border-radius: 0;
+ color: #000;
+ font-family: 'ProximaNova';
+ font-size: 14px;
+ line-height: normal;
+ min-height: auto;
+ min-width: auto;
+ padding: 0;
+ }
- .button {
- span {
- display: flex;
- align-items: center;
- justify-content: center;
+ .button .icon:before {
+ font-size: 14px;
+ line-height: normal;
+ }
+
+
+ .button {
+ span {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
}
}
}
diff --git a/src/sass/views/review.scss b/src/sass/views/review.scss
index 79bca1896..c530a1cef 100644
--- a/src/sass/views/review.scss
+++ b/src/sass/views/review.scss
@@ -1,5 +1,4 @@
#view-review {
- background-color: #494949;
slide-to-accept, slide-to-accept-success {
margin-bottom: constant(safe-area-inset-bottom); /* iOS 11.0 */
diff --git a/src/sass/views/walletDetails.scss b/src/sass/views/walletDetails.scss
index 0843a1c07..858229d85 100644
--- a/src/sass/views/walletDetails.scss
+++ b/src/sass/views/walletDetails.scss
@@ -261,6 +261,7 @@
.no-alternative {
padding-top: 45px;
}
+
.item.item-footer {
font-weight: lighter;
}
diff --git a/www/css/main.css b/www/css/main.css
index 0dfaaf5fb..8602ba35d 100644
--- a/www/css/main.css
+++ b/www/css/main.css
@@ -15359,8 +15359,6 @@ log-options #check-bar .checkbox-icon {
#view-review .fee-summary {
position: absolute;
bottom: 92px; }
- #view-review .fee-summary-spacer {
- height: 15px; }
#view-review .shapeshift-banner, #view-review .bitpay-banner, #view-review .egifter-banner {
box-shadow: none; }
#view-review .warning {
diff --git a/www/views/amount.html b/www/views/amount.html
index 57a8e46ce..b69431b6b 100644
--- a/www/views/amount.html
+++ b/www/views/amount.html
@@ -14,14 +14,14 @@
@@ -90,7 +93,7 @@
+
@@ -41,7 +46,7 @@
class="size-14 amount-alternative"
ng-if="status.totalBalanceStr && wallet.network == 'livenet'"
ng-style="{opacity: altAmountOpacity}">
-
+