Merge remote-tracking branch 'origin/wallet/task/440' into wallet/task/514
# Conflicts: # i18n/po/template.pot # src/js/controllers/amount.js # www/css/main.css
This commit is contained in:
commit
391201471d
22 changed files with 702 additions and 47 deletions
|
|
@ -3714,4 +3714,33 @@ msgstr ""
|
||||||
|
|
||||||
#: src/js/controllers/amount.js:49
|
#: src/js/controllers/amount.js:49
|
||||||
msgid "Address doesn\'t contain currency information, please make sure you are sending the correct currency."
|
msgid "Address doesn\'t contain currency information, please make sure you are sending the correct currency."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: www/views/review.html:4
|
||||||
|
msgid "Review Transaction"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: www/views/review.html:14
|
||||||
|
msgid "You are sending"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: www/views/review.html:22
|
||||||
|
msgid "From:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: www/views/review.html:36
|
||||||
|
msgid "To:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: www/views/review.html:53
|
||||||
|
msgid "Add personal note"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
|
||||||
|
#: www/views/review.html:57
|
||||||
|
msgid "Personal note:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: www/views/review.html:69
|
||||||
|
msgid "Less than 1 cent"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -35,9 +35,9 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
|
||||||
vm.save = save;
|
vm.save = save;
|
||||||
vm.sendMax = sendMax;
|
vm.sendMax = sendMax;
|
||||||
vm.errorMessage = '';
|
vm.errorMessage = '';
|
||||||
|
|
||||||
$scope.$on('$ionicView.beforeEnter', onBeforeEnter);
|
$scope.$on('$ionicView.beforeEnter', onBeforeEnter);
|
||||||
$scope.$on('$ionicView.leave', onLeave);
|
$scope.$on('$ionicView.leave', onLeave);
|
||||||
|
|
||||||
var LENGTH_EXPRESSION_LIMIT = 19;
|
var LENGTH_EXPRESSION_LIMIT = 19;
|
||||||
var LENGTH_BEFORE_COMMA_EXPRESSION_LIMIT = 8;
|
var LENGTH_BEFORE_COMMA_EXPRESSION_LIMIT = 8;
|
||||||
|
|
@ -66,7 +66,7 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
|
||||||
}
|
}
|
||||||
|
|
||||||
function onBeforeEnter(event, data) {
|
function onBeforeEnter(event, data) {
|
||||||
|
|
||||||
initCurrencies();
|
initCurrencies();
|
||||||
|
|
||||||
passthroughParams = data.stateParams;
|
passthroughParams = data.stateParams;
|
||||||
|
|
@ -81,7 +81,7 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
|
||||||
|
|
||||||
setAvailableUnits();
|
setAvailableUnits();
|
||||||
updateUnitUI();
|
updateUnitUI();
|
||||||
|
|
||||||
var reNr = /^[1234567890\.]$/;
|
var reNr = /^[1234567890\.]$/;
|
||||||
var reOp = /^[\*\+\-\/]$/;
|
var reOp = /^[\*\+\-\/]$/;
|
||||||
|
|
||||||
|
|
@ -153,7 +153,7 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
|
||||||
|
|
||||||
unitIndex = 0;
|
unitIndex = 0;
|
||||||
|
|
||||||
|
|
||||||
// currency have preference
|
// currency have preference
|
||||||
var fiatName;
|
var fiatName;
|
||||||
if (data.stateParams.currency) {
|
if (data.stateParams.currency) {
|
||||||
|
|
@ -260,11 +260,11 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
|
||||||
if (vm.amount == '0' && digit == '0') return;
|
if (vm.amount == '0' && digit == '0') return;
|
||||||
if (availableUnits[unitIndex].isFiat && vm.amount.indexOf('.') > -1 && vm.amount[vm.amount.indexOf('.') + 2]) return;
|
if (availableUnits[unitIndex].isFiat && vm.amount.indexOf('.') > -1 && vm.amount[vm.amount.indexOf('.') + 2]) return;
|
||||||
|
|
||||||
if (vm.amount == '0' && digit != '.') {
|
if (vm.amount == '0' && digit != '.') {
|
||||||
vm.amount = '';
|
vm.amount = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm.amount == '' && digit == '.') {
|
if (vm.amount == '' && digit == '.') {
|
||||||
vm.amount = '0';
|
vm.amount = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -335,16 +335,16 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
|
||||||
if (a) {
|
if (a) {
|
||||||
amountInCrypto = a;
|
amountInCrypto = a;
|
||||||
var amountInSatoshis = a * unitToSatoshi;
|
var amountInSatoshis = a * unitToSatoshi;
|
||||||
vm.fundsAreInsufficient = !!passthroughParams.fromWalletId
|
vm.fundsAreInsufficient = !!passthroughParams.fromWalletId
|
||||||
&& availableSatoshis !== null
|
&& availableSatoshis !== null
|
||||||
&& availableSatoshis < amountInSatoshis;
|
&& availableSatoshis < amountInSatoshis;
|
||||||
|
|
||||||
vm.alternativeAmount = txFormatService.formatAmount(amountInSatoshis, true);
|
vm.alternativeAmount = txFormatService.formatAmount(amountInSatoshis, true);
|
||||||
vm.allowSend = lodash.isNumber(a)
|
vm.allowSend = lodash.isNumber(a)
|
||||||
&& a > 0
|
&& a > 0
|
||||||
&& (!vm.shapeshiftOrderId
|
&& (!vm.shapeshiftOrderId
|
||||||
|| (a >= vm.minAmount && a <= vm.maxAmount))
|
|| (a >= vm.minAmount && a <= vm.maxAmount))
|
||||||
&& !vm.fundsAreInsufficient;
|
&& !vm.fundsAreInsufficient;
|
||||||
} else {
|
} else {
|
||||||
if (result) {
|
if (result) {
|
||||||
vm.alternativeAmount = 'N/A';
|
vm.alternativeAmount = 'N/A';
|
||||||
|
|
@ -356,16 +356,16 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
amountInCrypto = result;
|
amountInCrypto = result;
|
||||||
vm.fundsAreInsufficient = passthroughParams.fromWalletId
|
vm.fundsAreInsufficient = passthroughParams.fromWalletId
|
||||||
&& availableSatoshis !== null
|
&& availableSatoshis !== null
|
||||||
&& availableSatoshis < result * unitToSatoshi;
|
&& availableSatoshis < result * unitToSatoshi;
|
||||||
|
|
||||||
vm.alternativeAmount = $filter('formatFiatAmount')(toFiat(result));
|
vm.alternativeAmount = $filter('formatFiatAmount')(toFiat(result));
|
||||||
vm.allowSend = lodash.isNumber(result)
|
vm.allowSend = lodash.isNumber(result)
|
||||||
&& result > 0
|
&& result > 0
|
||||||
&& (!vm.shapeshiftOrderId
|
&& (!vm.shapeshiftOrderId
|
||||||
|| (result >= vm.minAmount && result <= vm.maxAmount))
|
|| (result >= vm.minAmount && result <= vm.maxAmount))
|
||||||
&& !vm.fundsAreInsufficient;
|
&& !vm.fundsAreInsufficient;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -381,7 +381,7 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
|
||||||
|
|
||||||
} else if (amountInCrypto > vm.maxAmount) {
|
} else if (amountInCrypto > vm.maxAmount) {
|
||||||
vm.errorMessage = gettextCatalog.getString('Amount is above maximum');
|
vm.errorMessage = gettextCatalog.getString('Amount is above maximum');
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
vm.errorMessage = '';
|
vm.errorMessage = '';
|
||||||
}
|
}
|
||||||
|
|
@ -474,7 +474,9 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$state.transitionTo('tabs.send.confirm', confirmData);
|
$state.transitionTo('tabs.send.review', confirmData);
|
||||||
|
}
|
||||||
|
$scope.useSendMax = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -585,7 +587,7 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
|
||||||
close();
|
close();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function updateAvailableFundsStringIfNeeded() {
|
function updateAvailableFundsStringIfNeeded() {
|
||||||
if (passthroughParams.fromWalletId && availableSatoshis !== null) {
|
if (passthroughParams.fromWalletId && availableSatoshis !== null) {
|
||||||
availableFundsInFiat = '';
|
availableFundsInFiat = '';
|
||||||
|
|
|
||||||
214
src/js/controllers/review.controller.js
Normal file
214
src/js/controllers/review.controller.js
Normal file
|
|
@ -0,0 +1,214 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('copayApp.controllers')
|
||||||
|
.controller('reviewController', reviewController);
|
||||||
|
|
||||||
|
function reviewController(addressbookService, configService, profileService, $log, $scope, txFormatService) {
|
||||||
|
var vm = this;
|
||||||
|
|
||||||
|
vm.destination = {
|
||||||
|
address: '',
|
||||||
|
balanceAmount: '',
|
||||||
|
balanceCurrency: '',
|
||||||
|
coin: '',
|
||||||
|
color: '',
|
||||||
|
currency: '',
|
||||||
|
currencyColor: '',
|
||||||
|
kind: '', // 'address', 'contact', 'wallet'
|
||||||
|
name: ''
|
||||||
|
};
|
||||||
|
vm.feeCrypto = '';
|
||||||
|
vm.feeFiat = '';
|
||||||
|
vm.origin = {
|
||||||
|
balanceAmount: '',
|
||||||
|
balanceCurrency: '',
|
||||||
|
color: '',
|
||||||
|
currency: '',
|
||||||
|
currencyColor: '',
|
||||||
|
name: '',
|
||||||
|
};
|
||||||
|
vm.primaryAmount = '';
|
||||||
|
vm.primaryCurrency = '';
|
||||||
|
vm.secondaryAmount = '';
|
||||||
|
vm.secondaryCurrency = '';
|
||||||
|
|
||||||
|
var config = null;
|
||||||
|
var coin = '';
|
||||||
|
var originWalletId = '';
|
||||||
|
var priceDisplayIsFiat = true;
|
||||||
|
var satoshis = null;
|
||||||
|
var toAddress = '';
|
||||||
|
var destinationWalletId = '';
|
||||||
|
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.beforeEnter", onBeforeEnter);
|
||||||
|
|
||||||
|
|
||||||
|
function onBeforeEnter(event, data) {
|
||||||
|
|
||||||
|
originWalletId = data.stateParams.fromWalletId;
|
||||||
|
satoshis = parseInt(data.stateParams.amount, 10);
|
||||||
|
toAddress = data.stateParams.toAddr;
|
||||||
|
|
||||||
|
var originWallet = profileService.getWallet(originWalletId);
|
||||||
|
vm.origin.currency = originWallet.coin.toUpperCase();
|
||||||
|
vm.origin.color = originWallet.color;
|
||||||
|
vm.origin.name = originWallet.name;
|
||||||
|
coin = originWallet.coin;
|
||||||
|
|
||||||
|
configService.get(function onConfig(err, configCache) {
|
||||||
|
if (err) {
|
||||||
|
$log.err('Error getting config.', err);
|
||||||
|
} else {
|
||||||
|
config = configCache;
|
||||||
|
priceDisplayIsFiat = config.wallet.settings.priceDisplay === 'fiat';
|
||||||
|
vm.origin.currencyColor = originWallet.coin === 'btc' ? config.bitcoinWalletColor : config.bitcoinCashWalletColor;
|
||||||
|
}
|
||||||
|
updateSendAmounts();
|
||||||
|
getOriginWalletBalance(originWallet);
|
||||||
|
handleDestinationAsAddress(toAddress, coin);
|
||||||
|
handleDestinationAsWallet(data.stateParams.toWalletId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOriginWalletBalance(originWallet) {
|
||||||
|
var balanceText = getWalletBalanceDisplayText(originWallet);
|
||||||
|
vm.origin.balanceAmount = balanceText.amount;
|
||||||
|
vm.origin.balanceCurrency = balanceText.currency;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getWalletBalanceDisplayText(wallet) {
|
||||||
|
var balanceCryptoAmount = '';
|
||||||
|
var balanceCryptoCurrencyCode = '';
|
||||||
|
var balanceFiatAmount = '';
|
||||||
|
var balanceFiatCurrency = ''
|
||||||
|
var displayAmount = '';
|
||||||
|
var displayCurrency = '';
|
||||||
|
|
||||||
|
var walletStatus = null;
|
||||||
|
if (wallet.status.isValid) {
|
||||||
|
walletStatus = wallet.status;
|
||||||
|
} else if (wallet.cachedStatus.isValid) {
|
||||||
|
walletStatus = wallet.cachedStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (walletStatus) {
|
||||||
|
var cryptoBalanceParts = walletStatus.spendableBalanceStr.split(' ');
|
||||||
|
balanceCryptoAmount = cryptoBalanceParts[0];
|
||||||
|
balanceCryptoCurrencyCode = cryptoBalanceParts.length > 1 ? cryptoBalanceParts[1] : '';
|
||||||
|
|
||||||
|
if (walletStatus.alternativeBalanceAvailable) {
|
||||||
|
balanceFiatAmount = walletStatus.spendableBalanceAlternative;
|
||||||
|
balanceFiatCurrency = walletStatus.alternativeIsoCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priceDisplayIsFiat) {
|
||||||
|
displayAmount = balanceFiatAmount ? balanceFiatAmount : balanceCryptoAmount;
|
||||||
|
displayCurrency = balanceFiatAmount ? balanceFiatCurrency : balanceCryptoCurrencyCode;
|
||||||
|
} else {
|
||||||
|
displayAmount = balanceCryptoAmount;
|
||||||
|
displayCurrency = balanceCryptoCurrencyCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
amount: displayAmount,
|
||||||
|
currency: displayCurrency
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDestinationAsAddress(address, originCoin) {
|
||||||
|
if (!address) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the recipient is a contact
|
||||||
|
addressbookService.get(originCoin + address, function(err, contact) {
|
||||||
|
if (!err && contact) {
|
||||||
|
console.log('destination is contact');
|
||||||
|
handleDestinationAsContact(contact);
|
||||||
|
} else {
|
||||||
|
console.log('destination is address');
|
||||||
|
vm.destination.address = address;
|
||||||
|
vm.destination.kind = 'address';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDestinationAsContact(contact) {
|
||||||
|
vm.destination.kind = 'contact';
|
||||||
|
vm.destination.name = contact.name;
|
||||||
|
vm.destination.color = contact.coin === 'btc' ? config.bitcoinWalletColor : config.bitcoinCashWalletColor;
|
||||||
|
vm.destination.currency = contact.coin.toUpperCase();
|
||||||
|
vm.destination.currencyColor = vm.destination.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDestinationAsWallet(walletId) {
|
||||||
|
destinationWalletId = walletId;
|
||||||
|
if (!destinationWalletId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('destination is wallet');
|
||||||
|
var destinationWallet = profileService.getWallet(destinationWalletId);
|
||||||
|
vm.destination.coin = destinationWallet.coin;
|
||||||
|
vm.destination.color = destinationWallet.color;
|
||||||
|
vm.destination.currency = destinationWallet.coin.toUpperCase();
|
||||||
|
vm.destination.kind = 'wallet';
|
||||||
|
vm.destination.name = destinationWallet.name;
|
||||||
|
|
||||||
|
if (config) {
|
||||||
|
vm.destination.currencyColor = vm.destination.coin === 'btc' ? config.bitcoinWalletColor : config.bitcoinCashWalletColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
var balanceText = getWalletBalanceDisplayText(destinationWallet);
|
||||||
|
vm.destination.balanceAmount = balanceText.amount;
|
||||||
|
vm.destination.balanceCurrency = balanceText.currency;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSendAmounts() {
|
||||||
|
if (typeof satoshis !== 'number') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cryptoAmount = '';
|
||||||
|
var cryptoCurrencyCode = '';
|
||||||
|
var amountStr = txFormatService.formatAmountStr(coin, satoshis);
|
||||||
|
if (amountStr) {
|
||||||
|
var amountParts = amountStr.split(' ');
|
||||||
|
cryptoAmount = amountParts[0];
|
||||||
|
cryptoCurrencyCode = amountParts.length > 1 ? amountParts[1] : '';
|
||||||
|
}
|
||||||
|
// Want to avoid flashing of amount strings so do all formatting after this has returned.
|
||||||
|
txFormatService.formatAlternativeStr(coin, satoshis, function(v) {
|
||||||
|
if (!v) {
|
||||||
|
vm.primaryAmount = cryptoAmount;
|
||||||
|
vm.primaryCurrency = cryptoCurrencyCode;
|
||||||
|
vm.secondaryAmount = '';
|
||||||
|
vm.secondaryCurrency = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vm.secondaryAmount = vm.primaryAmount;
|
||||||
|
vm.secondaryCurrency = vm.primaryCurrency;
|
||||||
|
|
||||||
|
var fiatParts = v.split(' ');
|
||||||
|
var fiatAmount = fiatParts[0];
|
||||||
|
var fiatCurrency = fiatParts.length > 1 ? fiatParts[1] : '';
|
||||||
|
|
||||||
|
if (priceDisplayIsFiat) {
|
||||||
|
vm.primaryAmount = fiatAmount;
|
||||||
|
vm.primaryCurrency = fiatCurrency;
|
||||||
|
vm.secondaryAmount = cryptoAmount;
|
||||||
|
vm.secondaryCurrency = cryptoCurrencyCode;
|
||||||
|
} else {
|
||||||
|
vm.primaryAmount = cryptoAmount;
|
||||||
|
vm.primaryCurrency = cryptoCurrencyCode;
|
||||||
|
vm.secondaryAmount = fiatAmount;
|
||||||
|
vm.secondaryCurrency = fiatCurrency;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -48,37 +48,44 @@ angular.module('bitcoincom.directives')
|
||||||
return '2';
|
return '2';
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (getDecimalPlaces($scope.currency)) {
|
var formatNumbers = function(currency, value) {
|
||||||
case '0':
|
switch (getDecimalPlaces(currency)) {
|
||||||
var valueFormatted = numberWithCommas(Math.round(parseFloat($scope.value)));
|
case '0':
|
||||||
buildAmount(valueFormatted, '', '');
|
var valueFormatted = numberWithCommas(Math.round(parseFloat(value)));
|
||||||
break;
|
|
||||||
|
|
||||||
case '2':
|
|
||||||
var valueProcessing = parseFloat(parseFloat($scope.value).toFixed(2));
|
|
||||||
var valueFormatted = numberWithCommas(valueProcessing);
|
|
||||||
buildAmount(valueFormatted, '', '');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '3':
|
|
||||||
var valueProcessing = parseFloat(parseFloat($scope.value).toFixed(3));
|
|
||||||
var valueFormatted = numberWithCommas(valueProcessing);
|
|
||||||
buildAmount(valueFormatted, '', '');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '8':
|
|
||||||
var valueFormatted = parseFloat($scope.value).toFixed(8);
|
|
||||||
if (parseFloat($scope.value) == 0) {
|
|
||||||
buildAmount('0', '', '');
|
|
||||||
} else {
|
|
||||||
buildAmount(valueFormatted, '', '');
|
buildAmount(valueFormatted, '', '');
|
||||||
var start = numberWithCommas(valueFormatted.slice(0, -5));
|
break;
|
||||||
var middle = valueFormatted.slice(-5, -2);
|
|
||||||
var end = valueFormatted.substr(valueFormatted.length - 2);
|
case '2':
|
||||||
buildAmount(start, middle, end);
|
var valueProcessing = parseFloat(parseFloat(value).toFixed(2));
|
||||||
}
|
var valueFormatted = numberWithCommas(valueProcessing);
|
||||||
break;
|
buildAmount(valueFormatted, '', '');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '3':
|
||||||
|
var valueProcessing = parseFloat(parseFloat(value).toFixed(3));
|
||||||
|
var valueFormatted = numberWithCommas(valueProcessing);
|
||||||
|
buildAmount(valueFormatted, '', '');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '8':
|
||||||
|
var valueFormatted = parseFloat(value).toFixed(8);
|
||||||
|
if (parseFloat(value) == 0) {
|
||||||
|
buildAmount('0', '', '');
|
||||||
|
} else {
|
||||||
|
buildAmount(valueFormatted, '', '');
|
||||||
|
var start = numberWithCommas(valueFormatted.slice(0, -5));
|
||||||
|
var middle = valueFormatted.slice(-5, -2);
|
||||||
|
var end = valueFormatted.substr(valueFormatted.length - 2);
|
||||||
|
buildAmount(start, middle, end);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
formatNumbers($scope.currency, $scope.value);
|
||||||
|
$scope.$watchGroup(['currency', 'value'], function() {
|
||||||
|
formatNumbers($scope.currency, $scope.value);
|
||||||
|
});
|
||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -344,6 +344,19 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.state('tabs.send.review', {
|
||||||
|
url: '/review/:amount/:fromWalletId/:sendMax/:toAddr/:toWalletId',
|
||||||
|
views: {
|
||||||
|
'tab-send@tabs': {
|
||||||
|
controller: 'reviewController',
|
||||||
|
controllerAs: 'vm',
|
||||||
|
templateUrl: 'views/review.html'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
paypro: null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
|
|
|
||||||
24
src/sass/components/action-minor.scss
Normal file
24
src/sass/components/action-minor.scss
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
.action-minor {
|
||||||
|
margin: 20px 14px;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
&.mt-negative {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.text-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .action-icon {
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-right: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .action-text {
|
||||||
|
vertical-align: middle;
|
||||||
|
color: #444444;
|
||||||
|
}
|
||||||
|
}
|
||||||
27
src/sass/components/address.scss
Normal file
27
src/sass/components/address.scss
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
.address {
|
||||||
|
background-color: #F8F8F8;
|
||||||
|
border: 0.5px solid #EDEBEB;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 9px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
&.expanded {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prefix {
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mid {
|
||||||
|
color: #919191;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suffix {
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
5
src/sass/components/card.scss
Normal file
5
src/sass/components/card.scss
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
.card {
|
||||||
|
&.card-gutter-compact {
|
||||||
|
margin: 10px 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1 +1,11 @@
|
||||||
|
@import "item";
|
||||||
|
@import "ion-content";
|
||||||
|
@import "card";
|
||||||
|
|
||||||
|
@import "header";
|
||||||
|
@import "content-frame";
|
||||||
|
@import "address";
|
||||||
|
@import "action-minor";
|
||||||
|
@import "expand-content";
|
||||||
|
@import "fee-summary";
|
||||||
@import "amount.scss";
|
@import "amount.scss";
|
||||||
|
|
|
||||||
11
src/sass/components/content-frame.scss
Normal file
11
src/sass/components/content-frame.scss
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
.content-frame {
|
||||||
|
&.negative-top {
|
||||||
|
margin-top: -40px;
|
||||||
|
|
||||||
|
.card {
|
||||||
|
&:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/sass/components/expand-content.scss
Normal file
26
src/sass/components/expand-content.scss
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
.expand-content-frame {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.expand-content-trigger {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
&.expand-content-revealed {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-content {
|
||||||
|
opacity: 0;
|
||||||
|
transform-origin: 100% 0%;
|
||||||
|
transform: scale(0,0);
|
||||||
|
transition: opacity 0.3s ease, transform 0.3s ease;
|
||||||
|
|
||||||
|
&.expand-content-revealed {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1,1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/sass/components/fee-summary.scss
Normal file
33
src/sass/components/fee-summary.scss
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
.fee-summary {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
padding: 5px 12px 15px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: #F2F2F2;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: -15px;
|
||||||
|
width: 100%;
|
||||||
|
height: 15px;
|
||||||
|
background: linear-gradient(to bottom, rgba(242,242,242,0) 0%,rgba(242,242,242,1) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fee-fiat {
|
||||||
|
&.positive {
|
||||||
|
color: #70955F;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.negative {
|
||||||
|
color: #C24633;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fee-crypto {
|
||||||
|
color: #A7A7A7;
|
||||||
|
}
|
||||||
|
}
|
||||||
36
src/sass/components/header.scss
Normal file
36
src/sass/components/header.scss
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
.header {
|
||||||
|
padding: 29px 12px 61px;
|
||||||
|
background-color: #FAB915;
|
||||||
|
color: #FFFFFF;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1em;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
+ .content {
|
||||||
|
margin-top: 23px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1em;
|
||||||
|
font-size: 18px;
|
||||||
|
|
||||||
|
&.large {
|
||||||
|
font-size: 29px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ p {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/sass/components/ion-content.scss
Normal file
17
src/sass/components/ion-content.scss
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Extends Ionic v1 ion-content
|
||||||
|
*/
|
||||||
|
|
||||||
|
ion-content {
|
||||||
|
&.bg-neutral {
|
||||||
|
background-color: #F2F2F2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.padded-bottom-cta {
|
||||||
|
bottom: 92px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.padded-bottom-cta-with-summary {
|
||||||
|
bottom: 134px;
|
||||||
|
}
|
||||||
|
}
|
||||||
48
src/sass/components/item.scss
Normal file
48
src/sass/components/item.scss
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Extends Ionic v1 item
|
||||||
|
*/
|
||||||
|
|
||||||
|
.item {
|
||||||
|
&.item-compact {
|
||||||
|
padding: 11px 13px;
|
||||||
|
}
|
||||||
|
&.item-gutterless {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-content {
|
||||||
|
&.item-content-avatar {
|
||||||
|
min-height: 69px;
|
||||||
|
padding: 13px 11px 13px 68px;
|
||||||
|
|
||||||
|
> img,
|
||||||
|
> i {
|
||||||
|
&:first-child {
|
||||||
|
position: absolute;
|
||||||
|
max-width: 40px;
|
||||||
|
max-height: 40px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
left: 13px;
|
||||||
|
top: 50%;
|
||||||
|
padding: 0;
|
||||||
|
transform: translate(0,-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.item-content-compact {
|
||||||
|
min-height: 0;
|
||||||
|
padding: 13px 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
color: #FAB915
|
||||||
|
}
|
||||||
|
|
||||||
|
+ .item-content {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
@import "gravatar";
|
@import "gravatar";
|
||||||
|
@import "elastic";
|
||||||
4
src/sass/directives/elastic.scss
Normal file
4
src/sass/directives/elastic.scss
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
.elastic {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
@ -88,6 +88,13 @@
|
||||||
background-image: url('../img/icon-faucet.svg');
|
background-image: url('../img/icon-faucet.svg');
|
||||||
background-size: 70%;
|
background-size: 70%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.icon-wallet {
|
||||||
|
background-color: #FAB915;
|
||||||
|
background-image: url('../img/icon-wallet.svg');
|
||||||
|
border: none;
|
||||||
|
box-shadow: 0 0 0 1px rgba(0,0,0,0.3) inset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
13
src/sass/views/review.scss
Normal file
13
src/sass/views/review.scss
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#view-review {
|
||||||
|
background-color: #494949;
|
||||||
|
|
||||||
|
slide-to-accept, slide-to-accept-success {
|
||||||
|
margin-bottom: constant(safe-area-inset-bottom); /* iOS 11.0 */
|
||||||
|
margin-bottom: env(safe-area-inset-bottom); /* iOS 11.2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.fee-summary {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 92px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -50,3 +50,4 @@
|
||||||
@import "includes/logOptions";
|
@import "includes/logOptions";
|
||||||
@import "includes/checkBar";
|
@import "includes/checkBar";
|
||||||
@import "cashScan";
|
@import "cashScan";
|
||||||
|
@import "review";
|
||||||
|
|
|
||||||
11
www/img/icon-bookmark.svg
Normal file
11
www/img/icon-bookmark.svg
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 11.25 15">
|
||||||
|
<defs>
|
||||||
|
<style>
|
||||||
|
.cls-1 {
|
||||||
|
fill: #444;
|
||||||
|
opacity: 0.564;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</defs>
|
||||||
|
<path id="_ionicons_svg_md-bookmark" class="cls-1" d="M121.688,64h-8.125A1.567,1.567,0,0,0,112,65.563V79l5.625-2.5L123.25,79V65.563A1.567,1.567,0,0,0,121.688,64Z" transform="translate(-112 -64)"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 381 B |
116
www/views/review.html
Normal file
116
www/views/review.html
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
<ion-view id="view-review" hide-tabs>
|
||||||
|
<ion-nav-bar class="bar-royal">
|
||||||
|
<ion-nav-title>
|
||||||
|
{{'Review Transaction' | translate}}
|
||||||
|
</ion-nav-title>
|
||||||
|
<ion-nav-back-button>
|
||||||
|
</ion-nav-back-button>
|
||||||
|
</ion-nav-bar>
|
||||||
|
|
||||||
|
<ion-content class="padded-bottom-cta-with-summary bg-neutral"
|
||||||
|
ng-init="memoExpanded = false">
|
||||||
|
<div class="header">
|
||||||
|
<div class="content">
|
||||||
|
<p translate>You are sending</p>
|
||||||
|
<p class="large">{{vm.primaryAmount}} {{vm.primaryCurrency}}</amount></p>
|
||||||
|
<p ng-show="vm.secondaryAmount">{{vm.secondaryAmount}} {{vm.secondaryCurrency}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content-frame negative-top">
|
||||||
|
<div class="card card-gutter-compact">
|
||||||
|
<div class="item item-compact" translate>From:</div>
|
||||||
|
<div class="item item-gutterless item-complex item-avatar">
|
||||||
|
<div class="item-content item-content-avatar">
|
||||||
|
<i class="icon big-icon-svg theme-circle theme-circle-services">
|
||||||
|
<div class="bg icon-wallet"
|
||||||
|
style="background-color: {{vm.origin.color}}"
|
||||||
|
></div>
|
||||||
|
</i>
|
||||||
|
<h2>{{vm.origin.name}} <span class="highlight" style="color: {{vm.origin.currencyColor}}">({{vm.origin.currency}})</span></h2>
|
||||||
|
<p ng-show="vm.origin.balanceAmount">{{vm.origin.balanceAmount}} {{vm.origin.balanceCurrency}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card card-gutter-compact">
|
||||||
|
<div class="item item-compact" translate>To:</div>
|
||||||
|
<div class="item item-gutterless item-complex item-avatar">
|
||||||
|
<div class="item-content item-content-avatar"
|
||||||
|
ng-if="vm.destination.kind === 'contact' || vm.destination.kind === 'wallet'">
|
||||||
|
<img src="img/contact-placeholder.svg" class="bg" ng-if="vm.destination.kind === 'contact'">
|
||||||
|
<i class="icon big-icon-svg theme-circle theme-circle-services" ng-if="vm.destination.kind === 'wallet'">
|
||||||
|
<div class="bg icon-wallet"
|
||||||
|
style="background-color: {{vm.destination.color}}"
|
||||||
|
></div>
|
||||||
|
</i>
|
||||||
|
<h2>{{vm.destination.name}}<span class="highlight" style="color: {{vm.destination.currencyColor}}" ng-if="vm.destination.currency"> ({{vm.destination.currency}})</span></h2></h2>
|
||||||
|
<p ng-if="vm.destination.balanceAmount">{{vm.destination.balanceAmount}} {{vm.destination.balanceCurrency}}</p>
|
||||||
|
</div>
|
||||||
|
<div class="item-content item-content-compact" ng-init="addressExpanded = false" ng-if="vm.destination.kind === 'address'">
|
||||||
|
<div class="address" ng-class="{ 'expanded': addressExpanded }" ng-click="addressExpanded = !addressExpanded"><span class="prefix">qz9cq</span><span class="mid">q5pryv9hnqwa8q8mccmynk9uf4vlu5nxer</span><span class="suffix">pzmc</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="expand-content-frame">
|
||||||
|
<div class="action-minor mt-negative text-right expand-content-trigger"
|
||||||
|
ng-class="{ 'expand-content-revealed': memoExpanded }"
|
||||||
|
ng-click="memoExpanded = !memoExpanded">
|
||||||
|
<img src="img/icon-bookmark.svg" class="action-icon">
|
||||||
|
<span class="action-text">Add personal note</span>
|
||||||
|
</div>
|
||||||
|
<div class="card card-gutter-compact expand-content"
|
||||||
|
ng-class="{ 'expand-content-revealed': memoExpanded }">
|
||||||
|
<div class="item item-compact" translate>Personal Note:</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="item-content">
|
||||||
|
<textarea elastic placeholder="{{btx.note.body || btx.message || 'Enter text here'}}" class="elastic"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ion-content>
|
||||||
|
|
||||||
|
<div class="fee-summary">
|
||||||
|
<div class="fee-fiat positive">Fee: Less than 1 cent</div>
|
||||||
|
<div class="fee-crypto"
|
||||||
|
ng-init="fee = {value: '0.00195823', currency: 'BCH'};">
|
||||||
|
<amount
|
||||||
|
value="fee.value"
|
||||||
|
currency="fee.currency"></amount>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<click-to-accept
|
||||||
|
ng-click="approve(tx, wallet, statusChangeHandler)"
|
||||||
|
ng-if="(!isCordova || isWindowsPhoneApp) && wallet"
|
||||||
|
click-send-status="sendStatus"
|
||||||
|
is-disabled="!wallet">
|
||||||
|
{{buttonText}}
|
||||||
|
</click-to-accept>
|
||||||
|
<slide-to-accept
|
||||||
|
ng-if="isCordova && !isWindowsPhoneApp && wallet"
|
||||||
|
slide-on-confirm="approve(tx, wallet, statusChangeHandler)"
|
||||||
|
slide-send-status="sendStatus"
|
||||||
|
is-disabled="!wallet">
|
||||||
|
{{buttonText}}
|
||||||
|
</slide-to-accept>
|
||||||
|
<slide-to-accept-success
|
||||||
|
slide-success-show="sendStatus === 'success'"
|
||||||
|
slide-success-on-confirm="onSuccessConfirm()"
|
||||||
|
slide-success-hide-on-confirm="true">
|
||||||
|
<span ng-show="wallet.m == 1 && (wallet.canSign() || wallet.isPrivKeyExternal())" translate>Payment Sent</span>
|
||||||
|
<span ng-show="wallet.m > 1 && (wallet.canSign() || wallet.isPrivKeyExternal())" translate>Proposal Created</span>
|
||||||
|
<span ng-show="!wallet.canSign() && !wallet.isPrivKeyExternal()" translate>Transaction Created</span>
|
||||||
|
</slide-to-accept-success>
|
||||||
|
|
||||||
|
<wallet-selector
|
||||||
|
wallet-selector-title="walletSelectorTitle"
|
||||||
|
wallet-selector-wallets="wallets"
|
||||||
|
wallet-selector-selected-wallet="wallet"
|
||||||
|
wallet-selector-show="walletSelector"
|
||||||
|
wallet-selector-on-select="onWalletSelect"
|
||||||
|
wallet-selector-display-balance-as-fiat="displayBalanceAsFiat">
|
||||||
|
</wallet-selector>
|
||||||
|
|
||||||
|
</ion-view>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue