diff --git a/public/views/modals/customized-amount.html b/public/views/modals/customAmount.html similarity index 100% rename from public/views/modals/customized-amount.html rename to public/views/modals/customAmount.html diff --git a/public/views/modals/inputAmount.html b/public/views/modals/inputAmount.html new file mode 100644 index 000000000..9e1ca7b41 --- /dev/null +++ b/public/views/modals/inputAmount.html @@ -0,0 +1,114 @@ + + + +

Enter amount

+
+ + +
+ +
+ + + +
+
{{amount || '-'}}
+
+ {{globalResult}} {{amountResult || '0.00'}} {{alternativeIsoCode}} +
+
+ {{globalResult}} {{alternativeResult || '0.00'}} {{unitName}} +
+
+ +
+
+
+ +
+
+ +
+
+
+
7
+
8
+
9
+
/
+
+ +
+
4
+
5
+
6
+
x
+
+ +
+
1
+
2
+
3
+
+
+
+ +
+
.
+
0
+
+
-
+
+
+
+ + + + +
+
diff --git a/public/views/walletHome.html b/public/views/walletHome.html index 0ee21524f..27be41161 100644 --- a/public/views/walletHome.html +++ b/public/views/walletHome.html @@ -302,9 +302,9 @@
-
@@ -403,34 +403,32 @@ -
+
- + Not valid - +
-
+
-
-
- -
diff --git a/src/css/ionic-migration.css b/src/css/ionic-migration.css index 58c49a4b3..ab7e5f347 100644 --- a/src/css/ionic-migration.css +++ b/src/css/ionic-migration.css @@ -88,6 +88,30 @@ font-size: 14px; } +.button.button-light:hover { + background-color: #fff; + border: 1px solid #E9E9EC; +} + +.button.button-light:active { + background-color: #ababab; + border: 1px solid #E9E9EC; +} + +.button.button-stable:hover { + background-color: transparent; + border: 1px solid #E9E9EC; +} + +.button.button-stable:active { + background-color: #ababab; + border: 1px solid #E9E9EC; +} + +.button-amount { + text-transform: none; +} + button, .button { min-width: inherit; min-height: inherit; diff --git a/src/js/controllers/modals/inputAmount.js b/src/js/controllers/modals/inputAmount.js new file mode 100644 index 000000000..ceafa36b0 --- /dev/null +++ b/src/js/controllers/modals/inputAmount.js @@ -0,0 +1,170 @@ +'use strict'; + +angular.module('copayApp.controllers').controller('inputAmountController', function($rootScope, $scope, $filter, $timeout, $ionicScrollDelegate, profileService, platformInfo, lodash, configService, go, rateService) { + var unitToSatoshi; + var satToUnit; + var unitDecimals; + var satToBtc; + var self = $scope.self; + var SMALL_FONT_SIZE_LIMIT = 13; + var LENGTH_EXPRESSION_LIMIT = 19; + + $scope.init = function() { + var config = configService.getSync().wallet.settings; + $scope.unitName = config.unitName; + $scope.alternativeIsoCode = config.alternativeIsoCode; + $scope.specificAmount = $scope.specificAlternativeAmount = ''; + $scope.isCordova = platformInfo.isCordova; + unitToSatoshi = config.unitToSatoshi; + satToUnit = 1 / unitToSatoshi; + satToBtc = 1 / 100000000; + unitDecimals = config.unitDecimals; + $scope.resetAmount(); + $timeout(function() { + $ionicScrollDelegate.resize(); + }, 100); + }; + + $scope.shareAddress = function(uri) { + if ($scope.isCordova) { + window.plugins.socialsharing.share(uri, null, null, null); + } + }; + + $scope.toggleAlternative = function() { + $scope.showAlternativeAmount = !$scope.showAlternativeAmount; + + if ($scope.amount && isExpression($scope.amount)) { + var amount = evaluate(format($scope.amount)); + $scope.globalResult = '= ' + processResult(amount); + } + }; + + function checkFontSize() { + if ($scope.amount && $scope.amount.length >= SMALL_FONT_SIZE_LIMIT) $scope.smallFont = true; + else $scope.smallFont = false; + }; + + $scope.pushDigit = function(digit) { + if ($scope.amount && $scope.amount.length >= LENGTH_EXPRESSION_LIMIT) return; + + $scope.amount = ($scope.amount + digit).replace('..', '.'); + checkFontSize(); + processAmount($scope.amount); + }; + + $scope.pushOperator = function(operator) { + if (!$scope.amount || $scope.amount.length == 0) return; + $scope.amount = _pushOperator($scope.amount); + + function _pushOperator(val) { + if (!isOperator(lodash.last(val))) { + return val + operator; + } else { + return val.slice(0, -1) + operator; + } + }; + }; + + function isOperator(val) { + var regex = /[\/\-\+\x\*]/; + return regex.test(val); + }; + + function isExpression(val) { + var regex = /^\.?\d+(\.?\d+)?([\/\-\+\*x]\d?\.?\d+)+$/; + + return regex.test(val); + }; + + $scope.removeDigit = function() { + $scope.amount = $scope.amount.slice(0, -1); + processAmount($scope.amount); + checkFontSize(); + }; + + $scope.resetAmount = function() { + $scope.amount = $scope.alternativeResult = $scope.amountResult = $scope.globalResult = ''; + checkFontSize(); + }; + + function processAmount(val) { + if (!val) { + $scope.resetAmount(); + return; + } + + var formatedValue = format(val); + var result = evaluate(formatedValue); + + if (lodash.isNumber(result)) { + $scope.globalResult = isExpression(val) ? '= ' + processResult(result) : ''; + $scope.amountResult = $filter('formatFiatAmount')(toFiat(result)); + $scope.alternativeResult = profileService.formatAmount(fromFiat(result) * unitToSatoshi, true); + } + }; + + function processResult(val) { + if ($scope.showAlternativeAmount) + return $filter('formatFiatAmount')(val); + else + return profileService.formatAmount(val.toFixed(unitDecimals) * unitToSatoshi, true); + }; + + function fromFiat(val) { + return parseFloat((rateService.fromFiat(val, $scope.alternativeIsoCode) * satToUnit).toFixed(unitDecimals), 10); + }; + + function toFiat(val) { + return parseFloat((rateService.toFiat(val * unitToSatoshi, $scope.alternativeIsoCode)).toFixed(2), 10); + }; + + function evaluate(val) { + var result; + try { + result = $scope.$eval(val); + } catch (e) { + return 0; + } + if (!lodash.isFinite(result)) return 0; + return result; + }; + + function format(val) { + var result = val.toString(); + + if (isOperator(lodash.last(val))) + result = result.slice(0, -1); + + return result.replace('x', '*'); + }; + + $scope.finish = function() { + var amount = $scope.showAlternativeAmount ? fromFiat(evaluate(format($scope.amount))).toFixed(unitDecimals) : evaluate(format($scope.amount)); + var alternativeAmount = $scope.showAlternativeAmount ? evaluate(format($scope.amount)) : toFiat(evaluate(format($scope.amount))); + + if (amount % 1 == 0) amount = parseInt(amount); + + if ($scope.addr) { + $scope.specificAmount = profileService.formatAmount(amount * unitToSatoshi, true); + $scope.specificAlternativeAmount = $filter('formatFiatAmount')(alternativeAmount); + + if ($scope.unitName == 'bits') { + var amountSat = parseInt((amount * unitToSatoshi).toFixed(0)); + amount = (amountSat * satToBtc).toFixed(8); + } + $scope.customizedAmountBtc = amount; + + $timeout(function() { + $ionicScrollDelegate.resize(); + }, 100); + } else { + self.setAmount(amount, $scope.showAlternativeAmount); + $scope.cancel(); + } + }; + + $scope.cancel = function() { + $scope.inputAmountModal.hide(); + }; +}); diff --git a/src/js/controllers/walletHome.js b/src/js/controllers/walletHome.js index 4a720fc6b..93174daeb 100644 --- a/src/js/controllers/walletHome.js +++ b/src/js/controllers/walletHome.js @@ -29,6 +29,8 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi ret.isWindowsPhoneApp = platformInfo.isWP; ret.countDown = null; ret.sendMaxInfo = {}; + ret.showAlternative = false; + ret.fromInputAmount = null; var vanillaScope = ret; var disableScannerListener = $rootScope.$on('dataScanned', function(event, data) { @@ -239,35 +241,8 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi } }; - this.openCustomizedAmountModal = function(addr) { - var fc = profileService.focusedClient; - - $scope.color = fc.backgroundColor; - $scope.self = self; - $scope.addr = addr; - - $ionicModal.fromTemplateUrl('views/modals/customized-amount.html', { - scope: $scope - }).then(function(modal) { - $scope.customAmountModal = modal; - $scope.customAmountModal.show(); - }); - }; - // Send - this.canShowAlternative = function() { - return $scope.showAlternative; - }; - - this.showAlternative = function() { - $scope.showAlternative = true; - }; - - this.hideAlternative = function() { - $scope.showAlternative = false; - }; - this.resetError = function() { this.error = this.success = null; }; @@ -336,7 +311,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi }, set: function(newValue) { $scope.__alternative = newValue; - if (typeof(newValue) === 'number' && self.isRateAvailable) { + if (self.isRateAvailable) { $scope._amount = parseFloat((rateService.fromFiat(newValue, self.alternativeIsoCode) * satToUnit).toFixed(self.unitDecimals), 10); } else { $scope.__amount = null; @@ -352,7 +327,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi }, set: function(newValue) { $scope.__amount = newValue; - if (typeof(newValue) === 'number' && self.isRateAvailable) { + if (self.isRateAvailable) { $scope.__alternative = parseFloat((rateService.toFiat(newValue * self.unitToSatoshi, self.alternativeIsoCode)).toFixed(2), 10); } else { $scope.__alternative = null; @@ -396,6 +371,13 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi }, 1); }; + this.setAmount = function(amount, useAlternativeAmount) { + $scope.showAlternative = useAlternativeAmount; + + self.fromInputAmount = true; + self.setForm(null, amount, null); + }; + this.submitForm = function() { if (!$scope._amount || !$scope._address) return; var client = profileService.focusedClient; @@ -579,6 +561,42 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi }); }; + $scope.openCustomInputAmountModal = function(addr) { + var fc = profileService.focusedClient; + $scope.color = fc.backgroundColor; + $scope.self = self; + $scope.addr = addr; + + $ionicModal.fromTemplateUrl('views/modals/customAmount.html', { + scope: $scope + }).then(function(modal) { + $scope.customAmountModal = modal; + $scope.customAmountModal.show(); + }); + }; + + $scope.openAmountModal = function(addr) { + if (isCordova) + $scope.openInputAmountModal(addr); + else + $scope.openCustomInputAmountModal(addr); + }; + + $scope.openInputAmountModal = function(addr) { + var fc = profileService.focusedClient; + $scope.color = fc.backgroundColor; + $scope.showAlternativeAmount = $scope.showAlternative || null; + $scope.self = self; + $scope.addr = addr; + + $ionicModal.fromTemplateUrl('views/modals/inputAmount.html', { + scope: $scope + }).then(function(modal) { + $scope.inputAmountModal = modal; + $scope.inputAmountModal.show(); + }); + }; + this.setForm = function(to, amount, comment) { var form = $scope.sendForm; if (to) { @@ -592,7 +610,9 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi form.amount.$setViewValue("" + amount); form.amount.$isValid = true; form.amount.$render(); - this.lockAmount = true; + if (!this.fromInputAmount) + this.lockAmount = true; + this.fromInputAmount = false; } if (comment) { diff --git a/src/sass/forms.scss b/src/sass/forms.scss index e5bbebbbe..e58f64586 100644 --- a/src/sass/forms.scss +++ b/src/sass/forms.scss @@ -44,6 +44,28 @@ textarea:focus { background: transparent; } +input[type="amount"] { + &[readonly] { + width: 100%; + opacity: 1; + color: #B7C2CD; + margin-bottom: 1.5rem; + height: 35px; + background: transparent; + border: none; + padding-left: 0.1rem; + font-size: 13px; + border-bottom: 1px solid #E9EDF0; + cursor: text; + }, + &[disabled] { + background-color: #E4E8EC; + color: #2C3E50; + padding-left: 0.5rem; + opacity: 1; + } +} + input[type="text"] { &[disabled], &[readonly] { background-color: #E4E8EC; diff --git a/src/sass/main.scss b/src/sass/main.scss index 08d749250..4549c7a04 100644 --- a/src/sass/main.scss +++ b/src/sass/main.scss @@ -588,6 +588,10 @@ ul.manage li { margin-bottom: 10px; } +.m3t { + margin-top: 3px; +} + .m10t { margin-top: 10px; } @@ -2123,3 +2127,53 @@ body.modal-open { color: #2C3E50; } } + +.calculator .header-calc { + position: absolute; + width: 100%; + text-align: center; +} + +.calculator .button-calc { + position: absolute; + width: 100%; + bottom: 0; +} + +.calculator .button-calc .row { + padding: 0 !important; +} + +.calculator .button-calc .columns { + cursor: pointer; + text-align: center; +} + +.calculator .button-calc .operator { + color: #2C3E50; + background-color: #eee; +} + +.calculator .button-calc .columns:active { + background-color: #eee; +} + +.calculator .button-calc .operator:active { + background-color: #f8f8f8; +} + +@media all and (max-height: 480px) { + .calculator .button-calc .columns { padding: 10px; } + .calculator .header-calc { top: 11%; } +} + +@media (min-height: 481px) and (max-height: 670px) { + .calculator .button-calc .columns { padding: 15px; } + .calculator .header-calc { top: 15%; } +} + +@media all and (min-height: 671px) { + .calculator .button-calc .columns { padding: 20px; } + .calculator .header-calc { top: 18%; } +} +