diff --git a/www/js/controllers/app-controllers.js b/www/js/controllers/app-controllers.js index 95e70aa197ee788a29f3e5d0bec074ecf1be2074..6ff04549a805bf1f89ca147cfd97c4961022faae 100644 --- a/www/js/controllers/app-controllers.js +++ b/www/js/controllers/app-controllers.js @@ -86,18 +86,22 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ // Device Methods //////////////////////////////////////// - function parseWIF(data, options) { + function parseWIF_or_EWIF(data, options) { options = options || {}; options.withSecret = angular.isDefined(options.withSecret) && options.withSecret || true; options.password = function() { return Modals.showPassword({ title: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.TITLE', subTitle: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.HELP', - error: options.error + error: options.error, + scope: $scope }) .then(function(password) { if (password) UIUtils.loading.show(); - return password; + // Timeout is need to force popup to be hide + return $timeout(function() { + return password; + }, 150); }); }; @@ -106,7 +110,7 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ if (err && err == 'CANCELLED') return; if (err && err.ucode == CryptoUtils.errorCodes.BAD_PASSWORD) { // recursive call - return parseWIF(data, {withSecret: options.withSecret, error: 'ACCOUNT.SECURITY.KEYFILE.ERROR.BAD_PASSWORD'}); + return parseWIF_or_EWIF(data, {withSecret: options.withSecret, error: 'ACCOUNT.SECURITY.KEYFILE.ERROR.BAD_PASSWORD'}); } console.error("[app] Unable to parse as WIF or EWIF format: " + (err && err.message || err)); throw err; // rethrow @@ -135,12 +139,17 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ // Not an URI: try WIF or EWIF format .catch(function(err) { - console.debug(err && err.message || err); + console.debug("[app] Scan data is not an URI (get error: " + (err && err.message || err) + "). Trying to decode as a WIF or EWIF format..."); // Try to read as WIF format - return parseWIF(data) + return parseWIF_or_EWIF(data) .then(function(keypair) { - if (!keypair || !keypair.signPk || !keypair.signSk) throw err; // rethrow the first error + if (!keypair || !keypair.signPk || !keypair.signSk) throw err; // rethrow the first error (e.g. Bad URI) + + // TODO: Use a temporary wallet ? + // var wallet = csWallet.instance('WIF'); + // return wallet.login(...) + return csWallet.login({ forceAuth: true, minData: false, @@ -150,12 +159,10 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ } }) .then(function () { - return $state.go('app.view_wallet'); + // Transfer all wallet + return $state.go('app.new_transfer', {all: true}); }); - // TODO: if WIF, force redirection to a transfer modal, using a temporary wallet: - // var wallet = csWallet.instance('WIF'); - // return wallet.login(...) }) // Unknown format (nor URI, nor WIF/EWIF) .catch(UIUtils.onError('ERROR.SCAN_UNKNOWN_FORMAT')); diff --git a/www/js/controllers/blockchain-controllers.js b/www/js/controllers/blockchain-controllers.js index d821f1acf6f83089a5c7248e9ec6090ff0d8a6a3..1c4cb7c09eb86521314734f706eed1ca91d5e2cb 100644 --- a/www/js/controllers/blockchain-controllers.js +++ b/www/js/controllers/blockchain-controllers.js @@ -107,6 +107,7 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho $scope.ionItemClass = 'item-border-large'; $scope.defaultSizeLimit = UIUtils.screen.isSmall() ? 50 : 100; $scope.helptipPrefix = 'helptip-network'; + $scope.listeners = []; /** * Enter into the view @@ -185,14 +186,14 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho } // endRemoveIf(device) - $scope.startListenBlock(); + $scope.addListeners(); $scope.entered = true; $scope.showHelpTip(); } else { - $scope.startListenBlock(); + $scope.addListeners(); } }; //$scope.$on('$ionicView.enter', $scope.enter); @@ -205,11 +206,7 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho * @param state */ $scope.leave = function() { - if ($scope.wsBlock) { - console.debug('[block] Stopping websocket [/ws/block]'); - $scope.wsBlock.close(); - delete $scope.wsBlock; - } + $scope.removeListeners(); }; //$scope.$on('$ionicView.leave', $scope.leave); $scope.$on('$ionicParentView.leave', $scope.leave); @@ -360,22 +357,36 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho }); }; - $scope.startListenBlock = function() { - if (!$scope.wsBlock) { - if ($scope.node == BMA) { - csCurrency.api.data.on.newBlock($scope, $scope.onBlock); - } - else { - console.debug('[block] Listening on websocket [/ws/block]'); - $scope.wsBlock = $scope.node.websocket.block(); - $scope.wsBlock.on(function(json) { - // Skip if WS closed (after leave view - should never happen) or invalid json - if (!$scope.wsBlock || !json) return; - var block = new Block(json); - block.cleanData(); // Remove unused content (arrays...) - $scope.onBlock(block); - }); - } + $scope.removeListeners = function() { + if ($scope.listeners.length) { + console.debug("[block] Closing listeners"); + _.forEach($scope.listeners, function(remove){ + remove(); + }); + $scope.listeners = []; + } + }; + + $scope.addListeners = function() { + if ($scope.listeners.length) return; // already started + + + console.debug("[block] Starting listeners"); + if ($scope.node === BMA) { + $scope.listeners.push( + csCurrency.api.data.on.newBlock($scope, $scope.onBlock) + ); + } + else { + var wsBlock = $scope.node.websocket.block(); + wsBlock.on(function(json) { + // Skip if WS closed (after leave view - should never happen) or invalid json + if (!json) return; + var block = new Block(json); + block.cleanData(); // Remove unused content (arrays...) + $scope.onBlock(block); + }); + $scope.listeners.push(wsBlock.close); } }; diff --git a/www/js/controllers/login-controllers.js b/www/js/controllers/login-controllers.js index 00ba7f1851a7a177cce4e153277124024f10ed12..21d383648ee4da7387170dc2739b943a264e5aa5 100644 --- a/www/js/controllers/login-controllers.js +++ b/www/js/controllers/login-controllers.js @@ -54,6 +54,7 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, CryptoUtils, // modal enter $scope.enter = function() { + console.log("Will enter !", arguments); UIUtils.loading.hide(); // Ink effect UIUtils.ink({selector: '.modal-login .ink'}); @@ -62,6 +63,7 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, CryptoUtils, // modal leave $scope.leave = function() { + console.log("Will hide !", arguments); $scope.formData = {}; $scope.computing = false; $scope.pubkey = null; @@ -134,10 +136,6 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, CryptoUtils, return UIUtils.loading.hide(10); } - // TODO: if WIF, force redirection to a transfer modal, using a temporary wallet: - // var wallet = csWallet.instance('WIF'); - // return wallet.login(...) - $scope.pubkeyError = false; return { @@ -206,6 +204,7 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, CryptoUtils, } // Return result then close + console.log("Will close login modal !!", res); return $scope.closeModal(res); }); }; @@ -329,12 +328,16 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, CryptoUtils, return Modals.showPassword({ title: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.TITLE', subTitle: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.HELP', - error: options.error + error: options.error, + scope: $scope }) .then(function (password) { // Remember password (for validation) $scope.formData.file.password = password; - return password; + // Timeout is need to force popup to be hide + return $timeout(function() { + return password; + }, 150); }); }; diff --git a/www/js/controllers/network-controllers.js b/www/js/controllers/network-controllers.js index a585ea4f08e87cd1e58875d3f2a22d620351fc32..914509be96eede3f64a44b2f4e920312657a6d4e 100644 --- a/www/js/controllers/network-controllers.js +++ b/www/js/controllers/network-controllers.js @@ -8,7 +8,7 @@ angular.module('cesium.network.controllers', ['cesium.services']) .state('app.network', { url: "/network?type&expert", - cache: false, + cache: true, views: { 'menuContent': { templateUrl: "templates/network/view_network.html", @@ -64,9 +64,20 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win sort : undefined, asc: true }; + $scope.listeners = []; $scope.helptipPrefix = 'helptip-network'; $scope.eanbleLocationHref = true; // can be overrided by sub-controler (e.g. popup) + $scope.removeListeners = function() { + if ($scope.listeners.length) { + console.debug("[network] Closing listeners"); + _.forEach($scope.listeners, function(remove){ + remove(); + }); + $scope.listeners = []; + } + }; + /** * Enter in view */ @@ -102,6 +113,7 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win */ $scope.leave = function() { if (!$scope.networkStarted) return; + $scope.removeListeners(); csNetwork.close(); $scope.networkStarted = false; $scope.search.loading = true; @@ -110,6 +122,7 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win $scope.$on('$ionicParentView.beforeLeave', $scope.leave); $scope.$on('$destroy', $scope.leave); + $scope.computeOptions = function() { var options = { filter: { @@ -136,7 +149,8 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win // Catch event on new peers $scope.refreshing = false; - csNetwork.api.data.on.changed($scope, function(data){ + $scope.listeners.push( + csNetwork.api.data.on.changed($scope, function(data){ if (!$scope.refreshing) { $scope.refreshing = true; csWot.extendAll(data.peers) @@ -148,7 +162,7 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win $scope.refreshing = false; }); } - }); + })); } // Show help tip @@ -409,6 +423,7 @@ function NetworkLookupPopoverController($scope, $controller) { $scope.showHelpTip = function() {}; // Enter the popover + console.log("Will enter the popover !"); $scope.enter(); } diff --git a/www/js/controllers/transfer-controllers.js b/www/js/controllers/transfer-controllers.js index 55da07c1281e94dc60423af1806e345c0211a7ff..71bc10baa5bde32c3d4e37e2fb7e7d5da8f5c08d 100644 --- a/www/js/controllers/transfer-controllers.js +++ b/www/js/controllers/transfer-controllers.js @@ -312,8 +312,8 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc if (comment && !comment.length) { comment = null; } - - if ($scope.formData.all) { + var hasRest = $scope.formData.all && $scope.formData.restAmount > 0; + if (hasRest) { return csWallet.transferAll($scope.formData.destPub, amount, comment, $scope.formData.useRelative, $scope.formData.restPub); } else { @@ -338,17 +338,18 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc }); }; - $scope.askTransferConfirm = function() { + $scope.askTransferConfirm = function(confirmationMessage) { return $translate(['COMMON.UD', 'COMMON.EMPTY_PARENTHESIS']) .then(function(translations) { - return $translate($scope.formData.all ? 'CONFIRM.TRANSFER_ALL' : 'CONFIRM.TRANSFER', { + var hasRest = $scope.formData.all && $scope.formData.restAmount > 0; + return $translate(hasRest ? 'CONFIRM.TRANSFER_ALL' : 'CONFIRM.TRANSFER', { from: csWallet.data.isMember ? csWallet.data.uid : $filter('formatPubkey')(csWallet.data.pubkey), to: $scope.destUid || $scope.destPub, amount: $scope.formData.amount, unit: $scope.formData.useRelative ? translations['COMMON.UD'] : $filter('abbreviate')($scope.currency), comment: (!$scope.formData.comment || $scope.formData.comment.trim().length === 0) ? translations['COMMON.EMPTY_PARENTHESIS'] : $scope.formData.comment, - restAmount: $scope.formData.all && $filter('formatAmount')($scope.formData.restAmount, {useRelative: $scope.formData.useRelative}), - restTo: ($scope.restUid || $scope.restPub) + restAmount: hasRest && $filter('formatAmount')($scope.formData.restAmount, {useRelative: $scope.formData.useRelative}), + restTo: hasRest && ($scope.restUid || $scope.restPub) }); }) .then(UIUtils.alert.confirm); diff --git a/www/js/controllers/wallet-controllers.js b/www/js/controllers/wallet-controllers.js index e5a00b4d0395f7fe7279175ddae0097464801291..205e3bd5fc11c31d49cbe3c7106eba9a346ad908 100644 --- a/www/js/controllers/wallet-controllers.js +++ b/www/js/controllers/wallet-controllers.js @@ -770,15 +770,18 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, }; } -function WalletTxErrorController($scope, UIUtils, csWallet) { +function WalletTxErrorController($scope, UIUtils, csSettings, csWallet) { 'ngInject'; + $scope.settings = csSettings.data; + $scope.loading = true; $scope.formData = {}; $scope.$on('$ionicView.enter', function(e) { $scope.loadWallet() .then(function(walletData) { $scope.formData = walletData; + $scope.loading = false; $scope.doMotion(); $scope.showFab('fab-redo-transfer'); UIUtils.loading.hide(); @@ -788,14 +791,21 @@ function WalletTxErrorController($scope, UIUtils, csWallet) { // Updating wallet data $scope.doUpdate = function(silent) { + $scope.loading = true; return (silent ? csWallet.refreshData() : UIUtils.loading.show() .then(csWallet.refreshData) .then(UIUtils.loading.hide) ) - .then($scope.doMotion) - .catch(UIUtils.onError('ERROR.REFRESH_WALLET_DATA')); + .then(function() { + $scope.doMotion(); + $scope.loading = false; + }) + .catch(function(err) { + UIUtils.onError('ERROR.REFRESH_WALLET_DATA')(err); + $scope.loading = false; + }); }; $scope.filterReceivedTx = function(tx){ @@ -806,6 +816,14 @@ function WalletTxErrorController($scope, UIUtils, csWallet) { return tx.amount && tx.amount < 0; }; + $scope.hasReceivedTx = function(){ + return $scope.formData.tx && !!_($scope.formData.tx.errors || []).find($scope.filterReceivedTx); + }; + + $scope.hasSentTx = function(){ + return $scope.formData.tx && !!_($scope.formData.tx.errors || []).find($scope.filterSentTx); + }; + } function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ diff --git a/www/js/services/bma-services.js b/www/js/services/bma-services.js index 724ccdcfaff23264baf964b4a053b5e0ce291613..ca3a8f754452d4c39f80f09618fd757e3fcf09ea 100644 --- a/www/js/services/bma-services.js +++ b/www/js/services/bma-services.js @@ -195,26 +195,16 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. ws = function(path) { return function() { var sock = that.cache.wsByPath[path]; - if (!sock) { + if (!sock || sock.isClosed()) { sock = csHttp.ws(that.host, that.port, path, that.useSsl); - // Override close methods (add a usage counter) - sock._counter = 1; - var inheritedClose = sock.close; - sock.close = function() { - sock._counter--; - if (sock._counter <= 0) { - console.debug('[BMA] Closing websocket ['+path+']'); - inheritedClose(); - delete that.cache.wsByPath[path]; - } + // When close, remove from cache + sock.onclose = function() { + delete that.cache.wsByPath[path]; }; that.cache.wsByPath[path] = sock; } - else { - sock._counter++; - } return sock; }; }; diff --git a/www/js/services/crypto-services.js b/www/js/services/crypto-services.js index ac15f9a3a1a890f5d6483c7e5fb1722423b87112..c683f2cd4c4a906c87cc1d89d9c1502728fa5b46 100644 --- a/www/js/services/crypto-services.js +++ b/www/js/services/crypto-services.js @@ -296,7 +296,7 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) } // If password is a promise, get the result then read data - if (typeof options.password == "object" && options.password.then) { + if (typeof options.password === "object" && options.password.then) { return options.password.then(function(password) { if (!password) throw 'CANCELLED'; return that.parseEWIF_v1(data_base58, password); diff --git a/www/js/services/currency-services.js b/www/js/services/currency-services.js index 0098ef22267def809e3c30754ffa740437ff1fa6..23d08583c288e64b93a2ecc6b8ae0d9c0ce7d2db 100644 --- a/www/js/services/currency-services.js +++ b/www/js/services/currency-services.js @@ -158,7 +158,7 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) console.debug('[currency] Received new block [' + block.number + '-' + block.hash + ']'); data.currentBlock = block; - data.currentBlock.receivedAt = new Date().getTime() / 1000; + data.currentBlock.receivedAt = Math.trunc(new Date().getTime() / 1000); data.medianTime = block.medianTime; data.membersCount = block.membersCount; @@ -242,15 +242,19 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) return currentBlockField() .then(function(currentBlock) { + + var now = Math.trunc(new Date().getTime() / 1000); + if (cache) { - var now = new Date().getTime() / 1000; - if (currentBlock && (currentBlock.receivedAt - now) < 60/*1min*/) { - console.debug('[currency] find current block in cache: use it'); + if (currentBlock && (now - currentBlock.receivedAt) < 60/*1min*/) { + console.debug('[currency] Use current block #'+ currentBlock.number +' from cache (age='+ (now - currentBlock.receivedAt) + 's)'); return currentBlock; } - // TODO : Should never occured if block event listener works ! - console.warn('[currency] No current block in cache: get it from network'); + if (!currentBlock) { + // Should never occur, if websocket /ws/block works ! + console.warn('[currency] No current block in cache: get it from network. Websocket [/ws/block] may not be started ?'); + } } return BMA.blockchain.current() diff --git a/www/js/services/http-services.js b/www/js/services/http-services.js index 892cf86a4bcffaef557043b843b0a6ba0e168c36..71832c9985d77cd21ba248099307a2bf88d01a51 100644 --- a/www/js/services/http-services.js +++ b/www/js/services/http-services.js @@ -225,10 +225,30 @@ angular.module('cesium.http.services', ['cesium.cache.services']) }; }); } + if (callback) self.callbacks.push(callback); return _waitOpen(self); } + function _close(self) { + if (self.delegate) { + self.delegate.closing = true; + console.debug('[http] Closing websocket ['+self.path+']...'); + self.delegate.close(); + self.callbacks = []; + if (self.onclose) self.onclose(); + } + } + + function _remove(self, callback) { + self.callbacks = _.reject(self.callbacks, function(item) { + return item === callback; + }); + if (!self.callbacks.length) { + _close(self); + } + } + return { open: function(params) { return _open(this, null, params); @@ -236,21 +256,27 @@ angular.module('cesium.http.services', ['cesium.cache.services']) on: function(callback, params) { return _open(this, callback, params); }, + onListener: function(callback, params) { + var self = this; + _open(self, callback, params); + return function() { + _remove(self, callback); + }; + }, send: function(data) { var self = this; return _waitOpen(self) .then(function(){ - self.delegate.send(data); + self.delegate && self.delegate.send(data); }); }, close: function() { var self = this; - if (self.delegate) { - self.delegate.closing = true; - console.debug('[http] Closing websocket ['+self.path+']...'); - self.delegate.close(); - self.callbacks = []; - } + _close(self); + }, + isClosed: function() { + var self = this; + return !self.delegate || self.delegate.closing; } }; } diff --git a/www/js/services/modal-services.js b/www/js/services/modal-services.js index 61614948306a550cb556795af1d03c9704322e1e..35b7ef593e62fa2d9b7159b1bf9b6d0ddd108dbf 100644 --- a/www/js/services/modal-services.js +++ b/www/js/services/modal-services.js @@ -159,15 +159,9 @@ angular.module('cesium.modal.services', []) function showLogin(parameters) { return ModalUtils.show('templates/login/modal_login.html','LoginModalCtrl', - parameters, {focusFirstInput: true}); + parameters, {focusFirstInput: true, backdropClickToClose: false}); } - function showAdvancedLogin(parameters) { - return ModalUtils.show('templates/login/modal_advanced_login.html','LoginModalCtrl', - parameters, {focusFirstInput: true}); - } - - function showWotLookup(parameters) { return ModalUtils.show('templates/wot/modal_lookup.html','WotLookupModalCtrl', parameters || {}, {focusFirstInput: true}); @@ -268,7 +262,6 @@ angular.module('cesium.modal.services', []) return { showTransfer: showTransfer, showLogin: showLogin, - showAdvancedLogin: showAdvancedLogin, showWotLookup: showWotLookup, showNetworkLookup: showNetworkLookup, showAbout: showAbout, diff --git a/www/js/services/network-services.js b/www/js/services/network-services.js index 726cb2337399bf32b0008a6d564c0a11f7df749d..9f2dfab3be3852724404305dedc4aa6d95bea7ac 100644 --- a/www/js/services/network-services.js +++ b/www/js/services/network-services.js @@ -16,7 +16,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi data = { bma: null, - websockets: [], + listeners: [], loading: true, peers: [], filter: { @@ -48,7 +48,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi resetData = function() { data.bma = null; - data.websockets = []; + data.listeners = []; data.peers.splice(0); data.filter = { member: true, @@ -654,46 +654,53 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi api.data.raise.changed(data); // raise event }, - startListeningOnSocket = function() { + removeListeners = function() { + _.forEach(data.listeners, function(remove){ + remove(); + }); + data.listeners = []; + }, + + addListeners = function() { // Listen for new block - var wsBlock = data.bma.websocket.block(); - data.websockets.push(wsBlock); - wsBlock.on(function(block) { - if (!block || data.loading) return; - var buid = [block.number, block.hash].join('-'); - if (data.knownBlocks.indexOf(buid) === -1) { - console.debug('[network] Receiving block: ' + buid.substring(0, 20)); - data.knownBlocks.push(buid); - // If first block: do NOT refresh peers (will be done in start() method) - var skipRefreshPeers = data.knownBlocks.length === 1; - if (!skipRefreshPeers) { - data.loading = true; - // We wait 2s when a new block is received, just to wait for network propagation - $timeout(function() { - console.debug('[network] new block received by WS: will refresh peers'); - loadPeers(); - }, 2000, false /*invokeApply*/); + data.listeners.push( + data.bma.websocket.block().onListener(function(block) { + if (!block || data.loading) return; + var buid = [block.number, block.hash].join('-'); + if (data.knownBlocks.indexOf(buid) === -1) { + console.debug('[network] Receiving block: ' + buid.substring(0, 20)); + data.knownBlocks.push(buid); + // If first block: do NOT refresh peers (will be done in start() method) + var skipRefreshPeers = data.knownBlocks.length === 1; + if (!skipRefreshPeers) { + data.loading = true; + // We wait 2s when a new block is received, just to wait for network propagation + $timeout(function() { + console.debug('[network] new block received by WS: will refresh peers'); + loadPeers(); + }, 2000, false /*invokeApply*/); + } } - } - }); + }) + ); // Listen for new peer - var wsPeer = data.bma.websocket.peer(); - data.websockets.push(wsPeer); - wsPeer.on(function(json) { - if (!json || data.loading) return; - var newPeers = []; - addOrRefreshPeerFromJson(json, newPeers) - .then(function(hasUpdates) { - if (!hasUpdates) return; - if (newPeers.length>0) { - flushNewPeersAndSort(newPeers, true); - } - else { - console.debug('[network] [ws] Peers updated received'); - sortPeers(true); - } - }); - }); + data.listeners.push( + data.bma.websocket.peer().onListener(function(json) { + if (!json || data.loading) return; + var newPeers = []; + addOrRefreshPeerFromJson(json, newPeers) + .then(function(hasUpdates) { + if (!hasUpdates) return; + if (newPeers.length>0) { + flushNewPeersAndSort(newPeers, true); + } + else { + console.debug('[network] [ws] Peers updated received'); + sortPeers(true); + } + }); + }) + ); }, sort = function(options) { @@ -714,13 +721,13 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi data.expertMode = angular.isDefined(options.expertMode) ? options.expertMode : data.expertMode; data.timeout = angular.isDefined(options.timeout) ? options.timeout : csConfig.timeout; console.info('[network] Starting network from [{0}]'.format(bma.server)); - var now = new Date(); + var now = new Date().getTime(); - startListeningOnSocket(); + addListeners(); return loadPeers() .then(function(peers){ - console.debug('[network] Started in '+(new Date().getTime() - now.getTime())+'ms'); + console.debug('[network] Started in '+(new Date().getTime() - now)+'ms'); return peers; }); }); @@ -728,11 +735,8 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi close = function() { if (data.bma) { - console.info('[network] Stopping'); - - _.forEach(data.websockets, function(ws){ - ws.close(); - }); + console.info('[network-service] Stopping...'); + removeListeners(); resetData(); } }, diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js index 807b9a38c10a4744af0bffe1778fc310645d2e7b..d69916a2cedec6d55bf1e059f9224a81f4d3f9e8 100644 --- a/www/js/services/wallet-services.js +++ b/www/js/services/wallet-services.js @@ -793,7 +793,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return $q.all([ getKeypair(), csCurrency.get(), - block && $q.when(block) || csCurrency.blockchain.lastValid() + block && $q.when(block) || csCurrency.blockchain.current() ]) .then(function(res) { var keypair = res[0]; @@ -887,14 +887,14 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se // Send tx return createAndSendTx(currency, block, keypair, destPub, amount, inputs, comments, restPub||data.pubkey, logs) .then(function(res) { - data.balance -= amount; + data.balance -= res.amount; _.forEach(inputs.sources, function(source) { source.consumed=true; }); // Add new sources if (res && res.sources.length) { - //console.log("TODO: detected new source after the TX: ", res.sources); + console.log("[wallet-service] New sources to be add after the TX: ", res.sources); addSources(res.sources); } @@ -930,7 +930,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se console.debug('[wallet] TX rejected by node with error [{0}]. Reloading sources then retry...'.format(err.message||'Source already consumed')); return $timeout(loadTxAndSources, 500) .then(function() { - return transfer(destPub, amount, comments, useRelative); + return transfer(destPub, amount, comments, useRelative, restPub, block); }); } @@ -986,10 +986,18 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return transfer(destPub, amount, comments, useRelative, restPub, block) .then(function() { + + // If more money: transfer all to restPub if (data.balance > 0 && restPub) { + + console.debug("Sending the rest amount to {" + restPub + '}...'); + data.sources.forEach(function(src) { + console.debug(src); + }); + console.debug("[wallet] Wallet has some more money: transfering fund to [{0}]".format(restPub.substring(0,6))); - return transfer(restPub, data.balance, undefined/*comments*/, false/*useRelative*/, block); + return transfer(restPub, data.balance, undefined/*comments*/, false/*useRelative*/, restPub, block); } }); @@ -1102,7 +1110,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se if (outputAmount > 0) { outputAmount = outputBase === 0 ? outputAmount : outputAmount / Math.pow(10, outputBase); tx += outputAmount +':'+outputBase+':SIG('+restPub+')\n'; - // If source to himself: add new sources + // If rest to himself: add new sources if (data.pubkey === restPub) { newSources.push({ type: 'T', @@ -1153,6 +1161,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se output.pending = true; }); return { + amount: (data.pubkey === destPub) ? 0 : ((data.pubkey === restPub) ? amount : inputs.amount), tx: signedTx, hash: txHash, sources: newSources diff --git a/www/templates/wallet/item_tx.html b/www/templates/wallet/item_tx.html index cd56e4d5dd043fd2b9e7d76054ac35897133ede8..a1cfe652146cd7dbaa9a843724e96c59cd3a6bb7 100644 --- a/www/templates/wallet/item_tx.html +++ b/www/templates/wallet/item_tx.html @@ -5,8 +5,7 @@ <div class="row no-padding"> <div class="col no-padding"> - <b class="ion-clock" ng-if="::pending"> </b> - <b class="ion-clock" ng-if="::validating"> </b> + <b class="ion-clock" ng-if="::(pending||validating)"> </b> <a class="" ui-sref="app.wot_identity({pubkey:tx.pubkey, uid:tx.uid})" ng-if="tx.uid"> {{::tx.name||tx.uid}} </a> diff --git a/www/templates/wallet/view_wallet_tx_error.html b/www/templates/wallet/view_wallet_tx_error.html index b23a813b51a573577fbc543010f9010e16a42bd7..5284be9b21aa208e4a60b931c5c3f9c1662a0ed2 100644 --- a/www/templates/wallet/view_wallet_tx_error.html +++ b/www/templates/wallet/view_wallet_tx_error.html @@ -1,16 +1,20 @@ <ion-view left-buttons="leftButtons" - id="wallet"> + class="view-wallet-tx-error"> <ion-nav-title> <!-- no title--> </ion-nav-title> <ion-nav-buttons side="secondary"> - - <button class="button button-icon button-clear icon ion-loop visible-xs visible-sm " ng-click="doUpdate()"> - </button> + <cs-extension-point name="nav-buttons"></cs-extension-point> </ion-nav-buttons> - <ion-content scroll="true"> + <ion-content scroll="true" + class="refresher-top-bg" + bind-notifier="{ rebind:settings.useRelative, locale:settings.locale.id}"> + + <ion-refresher pulling-text="{{'COMMON.BTN_REFRESH' | translate}}" + on-refresh="doUpdate(true)"> + </ion-refresher> <!-- Buttons bar --> <div class="hidden-xs hidden-sm padding text-center"> @@ -36,10 +40,11 @@ </div> </span> - <span class="item" ng-if="!formData.tx.errors.length"> - <h3 translate>ACCOUNT.NO_TX</h3> + <span class="item padding" ng-if="!loading && !hasReceivedTx()"> + <span class="gray">{{:locale:'ACCOUNT.NO_TX'|translate}}</span> </span> + <div class="item item-pending item-tx item-icon-left" ng-repeat="tx in formData.tx.errors | filter: filterReceivedTx" ng-init="pending=true;" @@ -55,8 +60,8 @@ </div> </span> - <span class="item" ng-if="!formData.tx.errors.length"> - <h3 translate>ACCOUNT.NO_TX</h3> + <span class="item padding" ng-if="!loading && !hasSentTx()"> + <span class="gray">{{:locale:'ACCOUNT.NO_TX'|translate}}</span> </span> <div class="item item-pending item-tx item-icon-left"