diff --git a/www/js/controllers/blockchain-controllers.js b/www/js/controllers/blockchain-controllers.js index 64e80245c59f0b952ee1766b825cdee05cdd6ba1..ca77f5d3df00177ba38fd422cd77e7c542449af1 100644 --- a/www/js/controllers/blockchain-controllers.js +++ b/www/js/controllers/blockchain-controllers.js @@ -205,7 +205,7 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho */ $scope.leave = function() { if ($scope.wsBlock) { - console.info('[block] Stopping websocket on block'); + console.debug('[block] Stopping websocket [/ws/block]'); $scope.wsBlock.close(); delete $scope.wsBlock; } @@ -361,70 +361,79 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho $scope.startListenBlock = function() { if (!$scope.wsBlock) { - console.info('[block] Starting websocket on block'); - $scope.wsBlock = $scope.node.websocket.block(); + 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); + }); + } } + }; - var showBlock = function(block){ - // Force rebind - $scope.$broadcast('$$rebind::rebind'); - $scope.motion.show({selector: '#block-'+block.number}); - }; - - $scope.wsBlock.on(function(json) { - // Skip if still loading or if filter/sort is not the default (not last blocks) - if ($scope.search.loading || !json || $scope.search.type != 'last' || - ($scope.search.sort && $scope.search.sort != 'desc')) return; // skip + $scope.onBlock = function(block) { + // Skip if still loading or if filter/sort is not the default (not last blocks) + if ($scope.search.loading || $scope.search.type != 'last' || + ($scope.search.sort && $scope.search.sort != 'desc')) return; // skip - var block = new Block(json); - block.cleanData(); // release arrays content + // Make sure results is init + $scope.search.results = $scope.search.results || []; - // Make sure results is init - $scope.search.results = $scope.search.results || []; + if (!$scope.search.results.length) { + console.debug('[ES] [blockchain] new block #{0} received (by websocket)'.format(block.number)); + // add it to result + $scope.search.total++; + $scope.search.results.push(block); - if (!$scope.search.results.length) { + // Prepare the new block, then show it + $scope.doPrepareResult([block]) + .then(function() { + return $scope.showBlock(block); + }); + } + else { + // Find existing block, by number + var existingBlock = _.findWhere($scope.search.results, {number: block.number}); + + // replace existing block (fork could have replaced previous block) + if (existingBlock) { + if (existingBlock.hash != block.hash) { + console.debug('[ES] [blockchain] block #{0} updated (by websocket)'.format(block.number)); + // Replace existing content + angular.copy(block, existingBlock); + // Prepare the new block, then show it + $scope.doPrepareResult([block, $scope.search.results[1]]) + .then(function() { + return $scope.showBlock(existingBlock); + }); + } + } + else { console.debug('[ES] [blockchain] new block #{0} received (by websocket)'.format(block.number)); - // add it to result + // Insert at index 0 $scope.search.total++; - $scope.search.results.push(block); + $scope.search.results.splice(0, 0, block); // Prepare the new block, then show it - $scope.doPrepareResult([block]) + $scope.doPrepareResult([block, $scope.search.results[1]]) .then(function() { - return showBlock(block); + return $scope.showBlock(block); }); } - else { - // Find existing block, by number - var existingBlock = _.findWhere($scope.search.results, {number: block.number}); - - // replace existing block (fork could have replaced previous block) - if (existingBlock) { - if (existingBlock.hash != block.hash) { - console.debug('[ES] [blockchain] block #{0} updated (by websocket)'.format(block.number)); - // Replace existing content - angular.copy(block, existingBlock); - // Prepare the new block, then show it - $scope.doPrepareResult([block, $scope.search.results[1]]) - .then(function() { - return showBlock(existingBlock); - }); - } - } - else { - console.debug('[ES] [blockchain] new block #{0} received (by websocket)'.format(block.number)); - // Insert at index 0 - $scope.search.total++; - $scope.search.results.splice(0, 0, block); + } + }; - // Prepare the new block, then show it - $scope.doPrepareResult([block, $scope.search.results[1]]) - .then(function() { - return showBlock(block); - }); - } - } - }); + $scope.showBlock = function(block){ + // Force rebind + $scope.$broadcast('$$rebind::rebind'); + $scope.motion.show({selector: '#block-'+block.number}); }; $scope.selectBlock = function(block) { diff --git a/www/js/controllers/network-controllers.js b/www/js/controllers/network-controllers.js index cabcf73429d85a2904ab6fd37b5c9ecf1e5057c4..a15753985bafd3c0d0fbeef2f0f2e14d310453c3 100644 --- a/www/js/controllers/network-controllers.js +++ b/www/js/controllers/network-controllers.js @@ -151,6 +151,7 @@ function NetworkLookupController($scope, $state, $ionicHistory, $ionicPopover, $scope.updateView = function(data) { console.debug("[peers] Updating UI"); + $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding $scope.search.results = data.peers; $scope.search.memberPeersCount = data.memberPeersCount; // Always tru if network not started (e.g. after leave+renter the view) @@ -158,6 +159,9 @@ function NetworkLookupController($scope, $state, $ionicHistory, $ionicPopover, if ($scope.motion && $scope.search.results && $scope.search.results.length > 0) { $scope.motion.show({selector: '.item-peer'}); } + if (!$scope.loading) { + $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding + } }; $scope.refresh = function() { @@ -370,7 +374,7 @@ function NetworkLookupPopoverController($scope, $controller) { $scope.enter(); } -function PeerInfoPopoverController($scope, csCurrency) { +function PeerInfoPopoverController($scope, csSettings, csCurrency, BMA) { 'ngInject'; $scope.loading = true; @@ -379,17 +383,32 @@ function PeerInfoPopoverController($scope, csCurrency) { $scope.enter = function() { csCurrency.blockchain.current() .then(function(block) { - $scope.formData = block; + $scope.formData = angular.copy(block); + $scope.formData.useSsl = BMA.useSsl; }) .then(function() { $scope.loading = false; + $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding }); }; // Update UI on new block csCurrency.api.data.on.newBlock($scope, function(block) { - $scope.formData = block; - console.debug("[peer info] Received a new block: ", block); + if ($scope.loading) return; + $scope.formData = angular.copy(block); + $scope.formData.useSsl = BMA.useSsl; + console.debug("[peer info] Received new block ", block); + $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding + }); + + // Update UI on settings changed + csSettings.api.data.on.changed($scope, function(data) { + if ($scope.loading) return; + if ($scope.formData.useSsl != BMA.useSsl) { + console.debug("[peer info] Peer settings changed"); + $scope.formData.useSsl = BMA.useSsl; + $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding + } }); // Enter the popover @@ -403,12 +422,11 @@ function PeerViewController($scope, $q, UIUtils, csWot, BMA) { $scope.loading = true; $scope.$on('$ionicView.enter', function(e, state) { - if (!state.stateParams || !state.stateParams.server) return; - - var useSsl = state.stateParams.ssl == "true"; - var useTor = state.stateParams.tor == "true"; + var server = state.stateParams && state.stateParams.server || BMA.server; + var useSsl = state.stateParams && state.stateParams.ssl == "true" || BMA.useSsl; + var useTor = state.stateParams.tor == "true" || BMA.useTor; - return $scope.load(state.stateParams.server, useSsl, useTor) + return $scope.load(server, useSsl, useTor) .then(function() { return $scope.$broadcast('$csExtension.enter', e, state); }) diff --git a/www/js/services/bma-services.js b/www/js/services/bma-services.js index bacb4f7aab960c05988366fd0e026f0ca6763569..3b7a2f701e4996f139825e723a31e014f9bcad48 100644 --- a/www/js/services/bma-services.js +++ b/www/js/services/bma-services.js @@ -187,8 +187,24 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. var sock = that.cache.wsByPath[path]; if (!sock) { sock = csHttp.ws(that.host, that.port, path, that.useSsl); + + // Override close methods (add a usage counter) + sock._counter = 1; + var close = sock.close; + sock.close = function() { + sock._counter--; + if (sock._counter <= 0) { + console.debug('[BMA] Stopping websocket ['+path+']'); + close(); + delete that.cache.wsByPath[path]; + } + }; + that.cache.wsByPath[path] = sock; } + else { + sock._counter++; + } return sock; }; }; diff --git a/www/js/services/currency-services.js b/www/js/services/currency-services.js index 809f64c1a5c84c672807bb2e2770c3b6d1893c5c..f156b0edb725c6fba91c614ff6f38ba714f40ecc 100644 --- a/www/js/services/currency-services.js +++ b/www/js/services/currency-services.js @@ -148,7 +148,7 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) function onBlock(json) { var block = new Block(json); - block.cleanData(); // keep only count values + block.cleanData(); // Remove unused content (arrays...) and keep items count console.debug('[currency] Received new block', block); data.currentBlock = block; diff --git a/www/js/services/network-services.js b/www/js/services/network-services.js index 50678a6cdfb2e174e46aba839e48864b0e9bd750..4bf6deea3c9c178057176601bc016826da5cf457 100644 --- a/www/js/services/network-services.js +++ b/www/js/services/network-services.js @@ -1,7 +1,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesium.http.services']) -.factory('csNetwork', function($rootScope, $q, $interval, $timeout, $window, BMA, csHttp, Api) { +.factory('csNetwork', function($rootScope, $q, $interval, $timeout, $window, BMA, csHttp, Api, csCurrency) { 'ngInject'; factory = function(id) { @@ -16,6 +16,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi data = { bma: null, + websockets: [], loading: true, peers: [], filter: { @@ -45,6 +46,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi resetData = function() { data.bma = null; + data.websockets = []; data.peers.splice(0); data.filter = { member: true, @@ -517,7 +519,9 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi startListeningOnSocket = function() { // Listen for new block - data.bma.websocket.block().on(function(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) { @@ -536,7 +540,9 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi } }); // Listen for new peer - data.bma.websocket.peer().on(function(json) { + var wsPeer = data.bma.websocket.peer(); + data.websockets.push(wsPeer); + wsPeer.on(function(json) { if (!json || data.loading) return; var newPeers = []; addOrRefreshPeerFromJson(json, newPeers) @@ -585,7 +591,10 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi close = function() { if (data.bma) { console.info('[network] Stopping'); - data.bma.websocket.close(); + + _.forEach(data.websockets, function(ws){ + ws.close(); + }); resetData(); } }, diff --git a/www/templates/network/items_peers.html b/www/templates/network/items_peers.html index e444955e12cf04cfe51cc70245e8303d150ddd4b..3e489af5a8ab1f7f78325a59113ac7f407df96ed 100644 --- a/www/templates/network/items_peers.html +++ b/www/templates/network/items_peers.html @@ -1,4 +1,5 @@ -<bind-notifier bind-notifier="{ rebind:search.results}" ng-class="::motion.ionListClass"> +<!-- bind-notifier="{ rebind:search.results}" --> +<bind-notifier ng-class="::motion.ionListClass"> <div class="item item-text-wrap no-border done in gray no-padding-top no-padding-bottom" ng-if="isHttps && expertMode"> <small><i class="icon ion-alert-circled"></i> {{'NETWORK.INFO.ONLY_SSL_PEERS'|translate}}</small> diff --git a/www/templates/network/popover_peer_info.html b/www/templates/network/popover_peer_info.html index f778fb51256ac6764e9c0ac1f088ca2e6587a32c..bf8231013b2d28f0f5e7efb3f8408e9fcb9ccff4 100644 --- a/www/templates/network/popover_peer_info.html +++ b/www/templates/network/popover_peer_info.html @@ -5,7 +5,7 @@ {{'PEER.VIEW.TITLE'|translate}} </div> </ion-header-bar> - <ion-content scroll="false"> + <ion-content scroll="false" > <div class="center" ng-if="loading"> <ion-spinner icon="android"></ion-spinner> </div> @@ -14,15 +14,15 @@ <div class="item"> <i class="ion-locked"></i> {{'NETWORK.VIEW.ENDPOINTS.BMAS'|translate}} - <div class="badge badge-balanced" ng-if="$root.settings.node.useSsl" translate>COMMON.BTN_YES</div> - <div class="badge badge-assertive" ng-if="!$root.settings.node.useSsl" translate>COMMON.BTN_NO</div> + <div class="badge badge-balanced" ng-if=":rebind:formData.useSsl" translate>COMMON.BTN_YES</div> + <div class="badge badge-assertive" ng-if=":rebind:!formData.useSsl" translate>COMMON.BTN_NO</div> </div> <div class="item"> <i class="ion-cube"></i> {{'BLOCKCHAIN.VIEW.TITLE_CURRENT'|translate}} <div class="badge badge-balanced"> - {{formData.number | formatInteger}} + {{:rebind:formData.number | formatInteger}} </div> </div> @@ -30,7 +30,7 @@ <i class="ion-clock"></i> {{'CURRENCY.VIEW.MEDIAN_TIME'|translate}} <div class="badge dark"> - {{formData.medianTime | formatDate}} + {{:rebind:formData.medianTime | formatDate}} </div> </div> @@ -38,7 +38,7 @@ <i class="ion-lock-combination"></i> {{'CURRENCY.VIEW.POW_MIN'|translate}} <div class="badge dark"> - {{formData.powMin | formatInteger}} + {{:rebind:formData.powMin | formatInteger}} </div> </div> @@ -60,9 +60,9 @@ <!-- show all --> <div class="pull-right"> <a class="positive" - ui-sref="app.network" + ui-sref="app.view_peer" ng-click="closePopover()" - translate>COMMON.NOTIFICATIONS.SHOW_ALL</a> + translate>PEER.BTN_SHOW_PEER</a> </div> </ion-footer-bar> </ion-popover-view> diff --git a/www/templates/network/view_network.html b/www/templates/network/view_network.html index baca383108299c349540862014ba28f65b35131e..1ff32b3d4060c2beda9f7010ccead5355631ddeb 100644 --- a/www/templates/network/view_network.html +++ b/www/templates/network/view_network.html @@ -48,6 +48,9 @@ <i class="icon ion-close-circled light-gray"></i> <span>{{'PEER.OFFLINE'|translate}}</span> </a> + + <!-- Allow extension here --> + <cs-extension-point name="filter-buttons"></cs-extension-point> </div> </div> </div>