diff --git a/public/views/includes/sidebar.html b/public/views/includes/sidebar.html index 69c3e296d..771224690 100644 --- a/public/views/includes/sidebar.html +++ b/public/views/includes/sidebar.html @@ -1,53 +1,53 @@ diff --git a/public/views/walletHome.html b/public/views/walletHome.html index bdfa8949e..7188530b3 100644 --- a/public/views/walletHome.html +++ b/public/views/walletHome.html @@ -54,7 +54,7 @@ --> - + @@ -62,12 +62,12 @@
-
+
{{index.updateError|translate}}
-
+
Scan status finished with error
Tap to retry
@@ -83,7 +83,7 @@
-
+
[Balance Hidden]
Tap and hold to show @@ -106,8 +106,7 @@
- - +
@@ -157,7 +156,7 @@
- +

Activity diff --git a/src/js/controllers/walletHome.js b/src/js/controllers/walletHome.js index 82e52c8c1..7a99a2724 100644 --- a/src/js/controllers/walletHome.js +++ b/src/js/controllers/walletHome.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('walletHomeController', function($scope, $ionicScrollDelegate, $rootScope, $interval, $timeout, $filter, $modal, $log, $ionicModal, notification, txStatus, profileService, lodash, configService, rateService, storageService, bitcore, gettext, gettextCatalog, platformInfo, addressService, ledger, bwsError, confirmDialog, txFormatService, animationService, addressbookService, go, feeService, walletService, fingerprintService, nodeWebkit) { +angular.module('copayApp.controllers').controller('walletHomeController', function($scope, $ionicScrollDelegate, $ionicSideMenuDelegate, $rootScope, $interval, $timeout, $filter, $modal, $log, $ionicModal, notification, txStatus, profileService, lodash, configService, rateService, storageService, bitcore, gettext, gettextCatalog, platformInfo, addressService, ledger, bwsError, confirmDialog, txFormatService, animationService, addressbookService, go, feeService, walletService, fingerprintService, nodeWebkit) { var isCordova = platformInfo.isCordova; var isWP = platformInfo.isWP; @@ -32,12 +32,29 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi ret.sendMaxInfo = {}; var vanillaScope = ret; - $scope.getScrollPosition = function() { - $scope.shouldCollapse = $ionicScrollDelegate.$getByHandle('transactions').getScrollPosition().top > 50; + $scope.collapseBalanceContent = function(val) { + if (val) return; + $scope.shouldCollapse = $ionicScrollDelegate.$getByHandle('transactions').getScrollPosition().top > 50 ? true : false; $timeout(function() { $scope.$apply(); }); - } + }; + + $scope.freezeScroll = function() { + + if ($ionicScrollDelegate.$getByHandle('balance').getScrollPosition().top < -75) { + $ionicScrollDelegate.$getByHandle('balance').freezeScroll(true); + return; + } + if ($ionicSideMenuDelegate.getOpenRatio() != 0) + $ionicScrollDelegate.$getByHandle('balance').freezeScroll(true); + else + $ionicScrollDelegate.$getByHandle('balance').freezeScroll(false); + + $timeout(function() { + $scope.$apply(); + }); + }; var disableScannerListener = $rootScope.$on('dataScanned', function(event, data) { self.setForm(data); @@ -1425,3 +1442,226 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi } }); +out(function() { + $rootScope.$digest(); +}, 1); +return cb(true); +} + +self._paypro = paypro; +self.setForm(paypro.toAddress, (paypro.amount * satToUnit).toFixed(self.unitDecimals), paypro.memo); +_paymentTimeControl(paypro.expires); +return cb(); +}); +}, 1); +}; + +function _paymentTimeControl(expirationTime) { + self.paymentExpired = false; + setExpirationTime(); + + self.countDown = $interval(function() { + setExpirationTime(); + }, 1000); + + function setExpirationTime() { + var now = Math.floor(Date.now() / 1000); + if (now > expirationTime) { + setExpiredValues(); + return; + } + + var totalSecs = expirationTime - now; + var m = Math.floor(totalSecs / 60); + var s = totalSecs % 60; + self.remainingTimeStr = ('0' + m).slice(-2) + ":" + ('0' + s).slice(-2); + }; + + function setExpiredValues() { + self.paymentExpired = true; + self.remainingTimeStr = null; + self._paypro = null; + self.error = gettext('Cannot sign: The payment request has expired'); + if (self.countDown) $interval.cancel(self.countDown); + }; +}; + +this.setFromUri = function(uri) { + var self = this; + + function sanitizeUri(uri) { + // Fixes when a region uses comma to separate decimals + var regex = /[\?\&]amount=(\d+([\,\.]\d+)?)/i; + var match = regex.exec(uri); + if (!match || match.length === 0) { + return uri; + } + var value = match[0].replace(',', '.'); + var newUri = uri.replace(regex, value); + return newUri; + }; + + var satToUnit = 1 / this.unitToSatoshi; + + // URI extensions for Payment Protocol with non-backwards-compatible request + if ((/^bitcoin:\?r=[\w+]/).exec(uri)) { + uri = decodeURIComponent(uri.replace('bitcoin:?r=', '')); + this.setFromPayPro(uri, function(err) { + if (err) { + return err; + } + }); + } else { + uri = sanitizeUri(uri); + + if (!bitcore.URI.isValid(uri)) { + return uri; + } + var parsed = new bitcore.URI(uri); + + var addr = parsed.address ? parsed.address.toString() : ''; + var message = parsed.message; + + var amount = parsed.amount ? + (parsed.amount.toFixed(0) * satToUnit).toFixed(this.unitDecimals) : 0; + + + if (parsed.r) { + this.setFromPayPro(parsed.r, function(err) { + if (err && addr && amount) { + self.setForm(addr, amount, message); + return addr; + } + }); + } else { + this.setForm(addr, amount, message); + return addr; + } + } + +}; + +this.onAddressChange = function(value) { + this.resetError(); + if (!value) return ''; + + if (this._paypro) + return value; + + if (value.indexOf('bitcoin:') === 0) { + return this.setFromUri(value); + } else if (/^https?:\/\//.test(value)) { + return this.setFromPayPro(value); + } else { + return value; + } +}; + +// History + +function strip(number) { + return (parseFloat(number.toPrecision(12))); +} + +this.getUnitName = function() { + return this.unitName; +}; + +this.getAlternativeIsoCode = function() { + return this.alternativeIsoCode; +}; + +this.openTxModal = function(tx) { + $rootScope.$emit('Local/TxModal', tx); +}; + +this.hasAction = function(actions, action) { + return actions.hasOwnProperty('create'); +}; + +this.sendMax = function(availableBalanceSat) { + if (availableBalanceSat == 0) { + this.error = gettext("Cannot create transaction. Insufficient funds"); + return; + } + + var self = this; + var fc = profileService.focusedClient; + this.error = null; + this.setOngoingProcess(gettextCatalog.getString('Calculating fee')); + + feeService.getCurrentFeeValue(function(err, feePerKb) { + if (err || !lodash.isNumber(feePerKb)) { + self.setOngoingProcess(); + self.error = gettext('Could not get fee value'); + return; + } + + var opts = {}; + opts.feePerKb = feePerKb; + opts.returnInputs = true; + var config = configService.getSync(); + opts.excludeUnconfirmedUtxos = !config.wallet.spendUnconfirmed; + self.setOngoingProcess(gettextCatalog.getString('Retrieving inputs information')); + + fc.getSendMaxInfo(opts, function(err, resp) { + self.setOngoingProcess(); + if (err) { + self.error = err; + $scope.$apply(); + return; + } + + if (resp.amount == 0) { + self.error = gettext("Not enough funds for fee"); + $scope.$apply(); + return; + } + + var msg = gettextCatalog.getString("{{fee}} will be deducted for bitcoin networking fees", { + fee: profileService.formatAmount(resp.fee) + ' ' + self.unitName + }); + + var warningMsg = verifyExcludedUtxos(); + + if (!lodash.isEmpty(warningMsg)) + msg += '. \n' + warningMsg; + + confirmDialog.show(msg, function(confirmed) { + if (confirmed) { + self.sendMaxInfo = resp; + var amount = parseFloat((resp.amount * self.satToUnit).toFixed(self.unitDecimals)); + self.setForm(null, amount, null); + } else { + self.resetForm(); + } + }); + + function verifyExcludedUtxos() { + var warningMsg = []; + if (resp.utxosBelowFee > 0) { + warningMsg.push(gettextCatalog.getString("Note: a total of {{amountBelowFeeStr}} were excluded. These funds come from UTXOs smaller than the network fee provided.", { + amountBelowFeeStr: profileService.formatAmount(resp.amountBelowFee) + ' ' + self.unitName + })); + } + if (resp.utxosAboveMaxSize > 0) { + warningMsg.push(gettextCatalog.getString("Note: a total of {{amountAboveMaxSizeStr}} were excluded. The maximum size allowed for a transaction was exceeded", { + amountAboveMaxSizeStr: profileService.formatAmount(resp.amountAboveMaxSize) + ' ' + self.unitName + })); + } + return warningMsg.join('\n'); + } + }); + }); +}; + +/* Start setup */ +lodash.assign(self, vanillaScope); + +this.bindTouchDown(); +if (profileService.focusedClient) { + this.setAddress(); + this.setSendFormInputs(); +} + +}); diff --git a/src/js/services/go.js b/src/js/services/go.js index 388149117..f30a2b6b7 100644 --- a/src/js/services/go.js +++ b/src/js/services/go.js @@ -26,7 +26,7 @@ angular.module('copayApp.services').factory('go', function($window, $ionicSideMe }; root.toggleLeftMenu = function() { - $ionicSideMenuDelegate.toggleLeft() + $ionicSideMenuDelegate.toggleLeft(); }; root.walletHome = function() {