From 0f720e5583f7f3f04283f4784cfd7fa45b8f295d Mon Sep 17 00:00:00 2001
From: blavenie <benoit.lavenier@e-is.pro>
Date: Sat, 11 Feb 2017 16:12:50 +0100
Subject: [PATCH] - Fix tabs (remove ion-view before ion-tabs) - refactore
 UIUtils.motion.toggleOn() and Off() - ES : better request for get
 user/profile (avatar+title) - Certifications (small device) : show fab
 buttons - fix #323 - blockchain: Fix new block refreshing - fix #322 -
 Currency (small device): Last blocks > add compact button in toolbar

---
 www/css/ionic.app.css                         |   6 +
 www/js/controllers/app-controllers.js         |  29 +----
 www/js/controllers/blockchain-controllers.js  | 111 ++++++++++--------
 www/js/controllers/currency-controllers.js    |   2 -
 www/js/controllers/network-controllers.js     |  12 +-
 www/js/controllers/wot-controllers.js         |  60 +++++++---
 www/js/entities/block.js                      |   5 +-
 www/js/services/utils-services.js             |  30 ++---
 www/plugins/es/js/services/user-services.js   |  43 ++++---
 .../templates/currency/tab_blocks_extend.html |   7 ++
 www/templates/blockchain/items_blocks.html    |  20 ++++
 www/templates/blockchain/list_blocks.html     |  20 ----
 www/templates/blockchain/view_block.html      |   6 +-
 www/templates/currency/items_network.html     |  14 +--
 www/templates/currency/tabs/tab_blocks.html   |  15 ++-
 www/templates/currency/view_currency.html     |  40 +++----
 www/templates/network/view_network.html       |  25 +++-
 .../wot/items_given_certifications.html       | 110 ++++++++---------
 .../wot/tabs/tab_given_certifications.html    |  11 +-
 .../wot/tabs/tab_received_certifications.html |  11 +-
 www/templates/wot/view_certifications.html    |  39 ++----
 21 files changed, 334 insertions(+), 282 deletions(-)
 create mode 100644 www/plugins/es/templates/currency/tab_blocks_extend.html
 create mode 100644 www/templates/blockchain/items_blocks.html

diff --git a/www/css/ionic.app.css b/www/css/ionic.app.css
index 4419ce067..a5a3c970c 100644
--- a/www/css/ionic.app.css
+++ b/www/css/ionic.app.css
@@ -15027,3 +15027,9 @@ a.underline:hover,
   font-size: 16px;
   left: 25px;
   top: -7px; }
+
+/*********
+* Tabs
+***********/
+.has-tabs-top {
+  /*top: 44px;*/ }
diff --git a/www/js/controllers/app-controllers.js b/www/js/controllers/app-controllers.js
index 7337dc915..c37bed473 100644
--- a/www/js/controllers/app-controllers.js
+++ b/www/js/controllers/app-controllers.js
@@ -365,38 +365,13 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $
   // Layout Methods
   ////////////////////////////////////////
   $scope.showFab = function(id, timeout) {
-    if (!timeout) {
-      timeout = 900;
-    }
-    $timeout(function () {
-      // Could not use 'getElementById', because it return only once element,
-      // but many fabs can have the same id (many view could be loaded at the same time)
-      var fabs = document.getElementsByClassName('button-fab');
-      _.forEach(fabs, function(fab){
-        if (fab.id == id) {
-          fab.classList.toggle('on', true);
-        }
-      });
-    }, timeout);
+    UIUtils.motion.toggleOn({selector: '#'+id + '.button-fab'}, timeout);
   };
 
   $scope.hideFab = function(id, timeout) {
-    if (!timeout) {
-      timeout = 10;
-    }
-    $timeout(function () {
-      // Could not use 'getElementById', because it return only once element,
-      // but many fabs can have the same id (many view could be loaded at the same time)
-      var fabs = document.getElementsByClassName('button-fab');
-      _.forEach(fabs, function(fab){
-        if (fab.id == id) {
-          fab.classList.toggle('on', false);
-        }
-      });
-    }, timeout);
+    UIUtils.motion.toggleOff({selector: '#'+id + '.button-fab'}, timeout);
   };
 
-
 }
 
 
diff --git a/www/js/controllers/blockchain-controllers.js b/www/js/controllers/blockchain-controllers.js
index 0f92475a7..0527a15fa 100644
--- a/www/js/controllers/blockchain-controllers.js
+++ b/www/js/controllers/blockchain-controllers.js
@@ -151,12 +151,14 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho
    */
   $scope.leave = function() {
     if ($scope.wsBlock) {
+      console.info('[block] Stopping websocket on block');
       $scope.wsBlock.close();
       delete $scope.wsBlock;
     }
   };
   $scope.$on('îoncView.leave', $scope.leave);
   $scope.$on('$ionicParentView.leave', $scope.leave);
+  $scope.$on('$destroy', $scope.leave);
 
   $scope.doSearchLast = function() {
     $scope.search.type = 'last';
@@ -199,19 +201,26 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho
     // process blocks
     return promise
       .then(function(blocks) {
+        // If no result
         if (!blocks || !blocks.length) {
           $scope.doDisplayResult([], from, 0);
           $scope.search.loading = false;
           return;
         }
+
+        // Transform to entities
         blocks = blocks.reduce(function(res, json){
           var block = new Block(json);
           block.cleanData(); // release arrays content
           return res.concat(block);
         }, []);
+
+        // Order by number (desc)
         blocks = _.sortBy(blocks, function(b) {
           return -1 * b.number;
         });
+
+        // Prepare then display results
         var total = ((from===0) ? blocks[0].number: $scope.search.results[0].number) + 1;
         return $scope.doPrepareResult(blocks, from)
           .then(function() {
@@ -306,71 +315,75 @@ 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();
     }
 
+    var showBlock = function(block){
+      // Force rebind
+      $scope.$broadcast('$$rebind::rebind');
+
+      return $timeout(function () {
+        UIUtils.motion.ripple({
+          startVelocity: 3000,
+          selector: '#block-'+block.number
+        });
+        // Set Ink
+        UIUtils.ink({
+          selector: '#block-'+block.number
+        });
+      }, 100);
+    };
+
     $scope.wsBlock.on(function(json) {
-      // TODO : skip if sort on some field
-      if ($scope.search.loading || !json || $scope.search.type != 'last' || !$scope.search.sort) return; // skip
+      // 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
 
       var block = new Block(json);
       block.cleanData(); // release arrays content
-      csWot.extendAll([block], 'issuer')
-        .then(function() {
-          $scope.search.results = $scope.search.results || [];
 
-          var needRefresh = false;
+      // Make sure results is init
+      $scope.search.results = $scope.search.results || [];
 
-          if (!$scope.search.results.length) {
-            // Prepare the new block, then add it to result
-            $scope.doPrepareResult([block]);
+      if (!$scope.search.results.length) {
+        // Prepare the new block, then add it to result
+        $scope.doPrepareResult([block])
+          .then(function() {
             console.debug('[ES] [blockchain] new block #{0} received (by websocket)'.format(block.number));
             $scope.search.total++;
             $scope.search.results.push(block);
-            needRefresh = true;
-          }
-          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));
-                // Prepare the new block, and refresh the previous latest block (could be compacted)
-                $scope.doPrepareResult([block, $scope.search.results[0]]);
+            return showBlock(existingBlock);
+          });
+      }
+      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));
+            // Prepare the new block, and refresh the previous latest block (could be compacted)
+            $scope.doPrepareResult([block, $scope.search.results[0]])
+              .then(function() {
                 angular.copy(block, existingBlock);
-                needRefresh = true;
-
-              }
-            }
-            else {
-              console.debug('[ES] [blockchain] new block #{0} received (by websocket)'.format(block.number));
-              // Prepare the new block, and refresh the previous latest block (could be compacted)
-              $scope.doPrepareResult([block, $scope.search.results[0]]);
+                return showBlock(existingBlock);
+              });
+          }
+        }
+        else {
+          console.debug('[ES] [blockchain] new block #{0} received (by websocket)'.format(block.number));
+          // Prepare the new block, and refresh the previous latest block (could be compacted)
+          $scope.doPrepareResult([block, $scope.search.results[0]])
+            .then(function() {
               // Insert at index 0
               $scope.search.total++;
               $scope.search.results.splice(0, 0, block);
-              needRefresh = true;
-            }
-          }
-
-          if (needRefresh) {
-            // Force rebind
-            $scope.$broadcast('$$rebind::rebind');
-
-            $timeout(function () {
-              UIUtils.motion.ripple({
-                startVelocity: 3000,
-                selector: '#block-'+block.number
-              });
-              // Set Ink
-              UIUtils.ink({
-                selector: '#block-'+block.number
-              });
-            }, 100);
-          }
-        });
+              return showBlock(existingBlock);
+            });
+        }
+      }
     });
   };
 
diff --git a/www/js/controllers/currency-controllers.js b/www/js/controllers/currency-controllers.js
index 4bf334daf..4ac0a9d3a 100644
--- a/www/js/controllers/currency-controllers.js
+++ b/www/js/controllers/currency-controllers.js
@@ -62,7 +62,6 @@ angular.module('cesium.currency.controllers', ['cesium.services'])
 
     .state('app.currency.tab_network', {
       url: "/network",
-      cache: false,
       views: {
         'tab-network': {
           templateUrl: "templates/currency/tabs/tab_network.html",
@@ -73,7 +72,6 @@ angular.module('cesium.currency.controllers', ['cesium.services'])
 
     .state('app.currency.tab_blocks', {
       url: "/blocks",
-      cache: false,
       views: {
         'tab-blocks': {
           templateUrl: "templates/currency/tabs/tab_blocks.html",
diff --git a/www/js/controllers/network-controllers.js b/www/js/controllers/network-controllers.js
index 5afa8b66e..8b4b03f4d 100644
--- a/www/js/controllers/network-controllers.js
+++ b/www/js/controllers/network-controllers.js
@@ -59,6 +59,7 @@ function NetworkLookupController($scope, $timeout, $state, $ionicHistory, $ionic
   $scope.enter = function(e, state) {
     if ($scope.networkStarted) return;
     $scope.networkStarted = true;
+    $scope.search.loading = true;
     csCurrency.default()
       .then(function (currency) {
         if (currency) {
@@ -81,7 +82,7 @@ function NetworkLookupController($scope, $timeout, $state, $ionicHistory, $ionic
       });
 
   };
-  $scope.$on('$ionicView.enter', $scope.enter);
+  //$scope.$on('$ionicView.enter', $scope.enter);
   $scope.$on('$ionicParentView.enter', $scope.enter);
 
   /**
@@ -95,6 +96,7 @@ function NetworkLookupController($scope, $timeout, $state, $ionicHistory, $ionic
   };
   $scope.$on('$ionicView.beforeLeave', $scope.leave);
   $scope.$on('$ionicParentView.beforeLeave', $scope.leave);
+  $scope.$on('$destroy', $scope.leave);
 
   $scope.computeOptions = function() {
     var options = {
@@ -125,7 +127,10 @@ function NetworkLookupController($scope, $timeout, $state, $ionicHistory, $ionic
           $scope.refreshing = true;
           csWot.extendAll(data.peers)
             .then(function() {
-              $scope.updateView(data);
+              // Avoid to refresh if view has been leaving
+              if ($scope.search.loading) {
+                $scope.updateView(data);
+              }
               $scope.refreshing = false;
             });
         }
@@ -140,7 +145,8 @@ function NetworkLookupController($scope, $timeout, $state, $ionicHistory, $ionic
     console.debug("[peers] Updating UI");
     $scope.search.results = data.peers;
     $scope.search.memberPeersCount = data.memberPeersCount;
-    $scope.search.loading = csNetwork.isBusy();
+    // Always tru if network not started (e.g. after leave+renter the view)
+    $scope.search.loading = !$scope.networkStarted || csNetwork.isBusy();
   };
 
   $scope.refresh = function() {
diff --git a/www/js/controllers/wot-controllers.js b/www/js/controllers/wot-controllers.js
index 3f95c04d2..6ce6cf480 100644
--- a/www/js/controllers/wot-controllers.js
+++ b/www/js/controllers/wot-controllers.js
@@ -677,7 +677,7 @@ function WotIdentityAbstractController($scope, $rootScope, $state, $timeout, $tr
 /**
  * Identity view controller - should extend WotIdentityAbstractCtrl
  */
-function WotIdentityViewController($scope, $controller, $timeout, UIUtils) {
+function WotIdentityViewController($scope, $controller, $timeout, UIUtils, csWallet) {
   'ngInject';
   // Initialize the super class and extend it.
   angular.extend(this, $controller('WotIdentityAbstractCtrl', {$scope: $scope}));
@@ -723,7 +723,7 @@ function WotIdentityViewController($scope, $controller, $timeout, UIUtils) {
 }
 
 /**
- * Certifications controller - should extend WotIdentityAbstractCtrl
+ * Certifications controller - extend WotIdentityAbstractCtrl
  */
 function WotCertificationsViewController($scope, $rootScope, $controller, $timeout, csSettings, csWallet, UIUtils) {
   'ngInject';
@@ -749,6 +749,9 @@ function WotCertificationsViewController($scope, $rootScope, $controller, $timeo
             $scope.showHelpTip();
           });
       }
+      else {
+        $scope.doMotion();
+      }
     }
 
     // Load from wallet pubkey
@@ -760,6 +763,9 @@ function WotCertificationsViewController($scope, $rootScope, $controller, $timeo
             $scope.showHelpTip();
           });
       }
+      else {
+        $scope.doMotion();
+      }
     }
 
     // Redirect to home
@@ -777,32 +783,43 @@ function WotCertificationsViewController($scope, $rootScope, $controller, $timeo
       });
   };
 
-  $scope.doMotion = function() {
-    // Effects
-    $scope.doMotionReceivedCertifications(100);
+  $scope.doMotion = function(skipItems) {
+    // Motions received certifications part
+    $scope.doMotionReceivedCertifications(0, skipItems);
+
+    // Motion on avatar part
     if ($scope.motions.avatar) {
       // Effects
       $timeout(function () {
-        UIUtils.motion.toggleOn({selector: '.col-avatar .motion'});
+        UIUtils.motion.toggleOn({
+          selector: '.col-avatar .motion'
+        });
       }, 300);
     }
-    $scope.doMotionGivenCertifications($scope.motions.receivedCertifications ? 900 : 100);
+
+    // Motion on given certification part
+    $scope.doMotionGivenCertifications($scope.motions.receivedCertifications ? 800 : 10, skipItems);
   };
 
   // Effects on received certifcations
-  $scope.doMotionReceivedCertifications = function(timeout) {
+  $scope.doMotionReceivedCertifications = function(timeout, skipItems) {
     if ($scope.motions.receivedCertifications) {
-      // Effects
-      $timeout(function() {
-        UIUtils.motion.fadeSlideInRight({selector: '.list.certifications .item'});
-        UIUtils.ink({selector: '.list.certifications .ink'});
-      }, timeout || 10);
+      if (!skipItems) {
+        // List items
+        $timeout(function () {
+          UIUtils.motion.fadeSlideInRight({selector: '.list.certifications .item'});
+          UIUtils.ink({selector: '.list.certifications .ink'});
+        }, timeout || 10);
+      }
+
+      // Fab button
       if ($scope.canCertify || $rootScope.tour) {
-        $scope.showFab('fab-certify');
+        $scope.showFab('fab-certify', timeout);
       }
     }
     // If not enable, make sure to hide fab button
     else {
+      // Hide fab button
       if ($scope.canCertify || $rootScope.tour) {
         $scope.hideFab('fab-certify', 0);
       }
@@ -810,13 +827,17 @@ function WotCertificationsViewController($scope, $rootScope, $controller, $timeo
   };
 
   // Effects on given certifcations
-  $scope.doMotionGivenCertifications = function(timeout) {
+  $scope.doMotionGivenCertifications = function(timeout, skipItems) {
 
     if ($scope.motions.givenCertifications) {
-      $timeout(function() {
-        UIUtils.motion.fadeSlideInRight({selector: '.list.given-certifications .item'});
-        UIUtils.ink({selector: '.list.given-certifications .ink'});
-      }, timeout || 10);
+      if (!skipItems) {
+        // List items
+        $timeout(function() {
+          UIUtils.motion.fadeSlideInRight({selector: '.list.given-certifications .item'});
+          UIUtils.ink({selector: '.list.given-certifications .ink'});
+        }, timeout || 10);
+      }
+      // Fab button
       if ($scope.canSelectAndCertify || $rootScope.tour) {
         $scope.showFab('fab-select-certify');
       }
@@ -824,6 +845,7 @@ function WotCertificationsViewController($scope, $rootScope, $controller, $timeo
 
     // If not enable, make sure to hide fab button
     else {
+      // Hide fab button
       if ($scope.canSelectAndCertify || $rootScope.tour) {
         $scope.hideFab('fab-select-certify', 0);
       }
diff --git a/www/js/entities/block.js b/www/js/entities/block.js
index 3462230d3..b5589ebb3 100644
--- a/www/js/entities/block.js
+++ b/www/js/entities/block.js
@@ -30,13 +30,12 @@ Block.prototype.isEmpty = function(){
   return !this.transactionsCount &&
     !this.certificationsCount &&
     !this.joinersCount &&
+    !this.dividend &&
     !this.activesCount &&
     !this.identitiesCount &&
     !this.leaversCount &&
     !this.excludedCount &&
-    !this.revokedCount &&
-    !this.dividend
-    ;
+    !this.revokedCount;
 };
 
 Block.prototype.parseData = function() {
diff --git a/www/js/services/utils-services.js b/www/js/services/utils-services.js
index ef3ec5969..20d946883 100644
--- a/www/js/services/utils-services.js
+++ b/www/js/services/utils-services.js
@@ -542,21 +542,16 @@ angular.module('cesium.utils.services', ['ngResource'])
     var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === '';
 
     if (isInvalidSelector) {
-      console.log('invalid toggleOn selector');
+      console.error('invalid toggleOn selector');
       return false;
     }
 
-    if (!timeout) {
-      timeout = 900;
-    }
     $timeout(function () {
-      var items = document.querySelectorAll(options.selector);
-      var itemsCount = items.length;
-      for (var i = 0; i < itemsCount; i++) {
-        var element = items[i];
+      var elements = document.querySelectorAll(options.selector);
+      elements && _.forEach(elements, function(element){
         element.classList.toggle('on', true);
-      }
-    }, timeout);
+      });
+    }, timeout || 100);
   };
 
   ionicMaterialMotion.toggleOff = function(options, timeout) {
@@ -571,21 +566,16 @@ angular.module('cesium.utils.services', ['ngResource'])
     var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === '';
 
     if (isInvalidSelector) {
-      console.log('invalid toggleOff selector');
+      console.error('invalid toggleOff selector');
       return false;
     }
 
-    if (!timeout) {
-      timeout = 900;
-    }
     $timeout(function () {
-      var items = document.querySelectorAll(options.selector);
-      var itemsCount = items.length;
-      for (var i = 0; i < itemsCount; i++) {
-        var element = items[i];
+      var elements = document.querySelectorAll(options.selector);
+      elements && _.forEach(elements, function(element){
         element.classList.toggle('on', false);
-      }
-    }, timeout);
+      });
+    }, timeout || 900);
   };
 
   return {
diff --git a/www/plugins/es/js/services/user-services.js b/www/plugins/es/js/services/user-services.js
index f1986836a..be39ffbb6 100644
--- a/www/plugins/es/js/services/user-services.js
+++ b/www/plugins/es/js/services/user-services.js
@@ -262,8 +262,7 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se
 
       pubkeyAtributeName = pubkeyAtributeName || 'pubkey';
       text = text ? text.toLowerCase().trim() : text;
-      var dataByPubkey = {};
-
+      var dataByPubkey;
       var request = {
         query: {},
         highlight: {fields : {title : {}}},
@@ -273,34 +272,44 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se
       };
 
       if (datas.length > 0) {
-        // collect pubkeys
+        // collect pubkeys and fill values map
+        dataByPubkey = {};
         _.forEach(datas, function(data) {
           var pubkey = data[pubkeyAtributeName];
           if (pubkey) {
             var values = dataByPubkey[pubkey];
             if (!values) {
-              values = [];
+              values = [data];
               dataByPubkey[pubkey] = values;
             }
-            values.push(data);
+            else {
+              values.push(data);
+            }
           }
         });
         var pubkeys = _.keys(dataByPubkey);
-        request.query.constant_score = {
-           filter: {
-             bool: {should: [{terms : {_id : pubkeys}}]}
-           }
-        };
-        request.size = request.length;
+        // Make sure all results will be return
+        request.size = (pubkeys.length <= request.size) ? request.size : pubkeys.length;
         if (!text) {
           delete request.highlight; // highlight not need
+          request.query.constant_score = {
+            filter: {
+              terms : {_id : pubkeys}
+            }
+          };
         }
         else {
-          request.query.constant_score.filter.bool.should.push(
-            {bool: {must: [
-                {match: {title: text}},
-                {prefix: {title: text}}
-              ]}});
+          request.query.constant_score = {
+            filter: {bool: {should: [
+                {terms : {_id : pubkeys}},
+                {bool: {
+                    must: [
+                      {match: {title: text}},
+                      {prefix: {title: text}}
+                    ]}
+                }
+            ]}}
+          };
         }
       }
       else if (text){
@@ -332,7 +341,7 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se
       .then(function() {
         if (hits.total > 0) {
           _.forEach(hits.hits, function(hit) {
-            var values = dataByPubkey[hit._id];
+            var values = dataByPubkey && dataByPubkey[hit._id];
             if (!values) {
               var value = {};
               value[pubkeyAtributeName] = hit._id;
diff --git a/www/plugins/es/templates/currency/tab_blocks_extend.html b/www/plugins/es/templates/currency/tab_blocks_extend.html
new file mode 100644
index 000000000..dd79451ff
--- /dev/null
+++ b/www/plugins/es/templates/currency/tab_blocks_extend.html
@@ -0,0 +1,7 @@
+<!-- Buttons section -->
+<ng-if ng-if="enable && extensionPoint === 'nav-buttons'">
+  <button class="button button-icon button-clear visible-xs visible-sm"
+          ui-sref="app.blockchain_search">
+    <i class="icon ion-android-search"></i>
+  </button>
+</ng-if>
diff --git a/www/templates/blockchain/items_blocks.html b/www/templates/blockchain/items_blocks.html
new file mode 100644
index 000000000..30852b68d
--- /dev/null
+++ b/www/templates/blockchain/items_blocks.html
@@ -0,0 +1,20 @@
+  <div class="text-center" ng-if="search.loading">
+    <ion-spinner icon="android"></ion-spinner>
+  </div>
+
+  <ion-list class="animate-ripple padding padding-xs">
+    <div class="padding gray" ng-if="!search.loading && !search.results.length" translate>
+      BLOCKCHAIN.LOOKUP.NO_BLOCK
+    </div>
+    <!-- blocks -->
+    <ng-repeat ng-repeat="block in :rebind:search.results track by block.number"
+               ng-include="'templates/blockchain/item_block.html'">
+    </ng-repeat>
+  </ion-list>
+
+  <ion-infinite-scroll
+    ng-if="search.hasMore"
+    icon="android"
+    on-infinite="showMore()"
+    distance="1%">
+  </ion-infinite-scroll>
diff --git a/www/templates/blockchain/list_blocks.html b/www/templates/blockchain/list_blocks.html
index 90c719651..90bc71d5e 100644
--- a/www/templates/blockchain/list_blocks.html
+++ b/www/templates/blockchain/list_blocks.html
@@ -1,23 +1,3 @@
-  <div class="padding padding-xs" style="display: block; height: 100px;">
-    <h4 translate>BLOCKCHAIN.LOOKUP.LAST_BLOCKS</h4>
-
-    <div class="pull-right">
-      <a class="button button-text button-small ink"
-         ng-class="{'button-text-positive': compactMode, 'button-text-stable': !compactMode}"
-         ng-click="toggleCompactMode()" >
-        <i class="icon ion-navicon"></i>
-        <b class="ion-arrow-down-b" style="position: absolute; top: -2px; left: 4px; font-size: 8px;"></b>
-        <b class="ion-arrow-up-b" style="position: absolute; top: 10px; left: 4px; font-size: 8px;"></b>
-        <span>{{'BLOCKCHAIN.LOOKUP.BTN_COMPACT'|translate}}</span>
-      </a>
-
-      <!-- Allow extension here -->
-      <cs-extension-point name="buttons"></cs-extension-point>
-
-    </div>
-
-
-  </div>
 
   <div class="text-center" ng-if="search.loading">
     <ion-spinner icon="android"></ion-spinner>
diff --git a/www/templates/blockchain/view_block.html b/www/templates/blockchain/view_block.html
index d20164d7b..47f176318 100644
--- a/www/templates/blockchain/view_block.html
+++ b/www/templates/blockchain/view_block.html
@@ -119,8 +119,10 @@
           <ion-item ng-if="!compactMode || formData.dividend"
                     class="item-icon-left item-text-wrap" copy-on-click="{{::formData.dividend/100}}">
             <i class="icon ion-arrow-up-c"></i>
-            {{'COMMON.UNIVERSAL_DIVIDEND'|translate}}
-            <h4 class="gray">{{'BLOCKCHAIN.VIEW.UNIVERSAL_DIVIDEND_HELP'|translate: {membersCount: formData.membersCount} }}</h4>
+            <div class="col col-60">
+              {{'COMMON.UNIVERSAL_DIVIDEND'|translate}}
+              <h4 class="gray">{{'BLOCKCHAIN.VIEW.UNIVERSAL_DIVIDEND_HELP'|translate: {membersCount: formData.membersCount} }}</h4>
+            </div>
             <span class="badge badge-balanced" ng-if="formData.dividend">
               +1 <span ng-bind-html="formData.currency|currencySymbol: {useRelative: true} "></span> / {{'COMMON.MEMBER'|translate|lowercase}}
             </span>
diff --git a/www/templates/currency/items_network.html b/www/templates/currency/items_network.html
index f32a769b6..8c7e34c02 100644
--- a/www/templates/currency/items_network.html
+++ b/www/templates/currency/items_network.html
@@ -2,14 +2,14 @@
   <ion-item id="helptip-network-blockchain"
             class="item-icon-left item-text-wrap">
     <i class="icon ion-clock"></i>
-    <span translate>CURRENCY.VIEW.MEDIAN_TIME</span>
-    <span class="item-note dark">{{formData.medianTime | formatDate}}</span>
+    <span class="col col-60" translate>CURRENCY.VIEW.MEDIAN_TIME</span>
+    <span class="badge badge-stable">{{formData.medianTime | formatDate}}</span>
   </ion-item>
 
 
   <ion-item class="item-icon-left item-text-wrap">
     <i class="icon ion-lock-combination"></i>
-    <span translate>CURRENCY.VIEW.POW_MIN</span>
+    <span class="col col-75" translate>CURRENCY.VIEW.POW_MIN</span>
     <span class="badge badge-stable">{{formData.difficulty | formatInteger}}</span>
   </ion-item>
 
@@ -19,11 +19,11 @@
 
   <ion-item class="item-icon-left item-text-wrap">
     <i class="icon ion-clock" style="position: absolute; font-size: 20px; left: 16px; margin-top: 11px"></i>
-    <b class="ion-lock-combination" style="position: absolute; font-size: 16px; left: 14px; margin-top: -4px;"></b>
-    <b class="ion-arrow-right-c" style="position: absolute; font-size: 12px; left: 28px; margin-top: -4px;"></b>
-    <b class="ion-lock-combination" style="position: absolute; font-size: 16px; left: 38px; margin-top: -4px;"></b>
+    <b class="icon-secondary ion-lock-combination" style="left: 14px; margin-top: -4px;"></b>
+    <b class="icon-secondary ion-arrow-right-c" style="font-size: 12px; left: 28px; margin-top: -4px;"></b>
+    <b class="icon-secondary ion-lock-combination" style="left: 38px; margin-top: -4px;"></b>
 
-    <span translate>CURRENCY.VIEW.AVG_GEN_TIME</span>
+    <span class="col col-75" translate>CURRENCY.VIEW.AVG_GEN_TIME</span>
     <span class="badge badge-stable">{{formData.avgGenTime | formatDuration}}</span>
   </ion-item>
 
diff --git a/www/templates/currency/tabs/tab_blocks.html b/www/templates/currency/tabs/tab_blocks.html
index fe844d1e1..d1f7802f8 100644
--- a/www/templates/currency/tabs/tab_blocks.html
+++ b/www/templates/currency/tabs/tab_blocks.html
@@ -1,10 +1,15 @@
 <ion-view>
   <ion-nav-buttons side="secondary">
 
-    <button class="button button-icon button-clear visible-xs visible-sm" ng-click="toggleCompactMode()">
+    <button class="button button-icon button-clear visible-xs visible-sm"
+            ng-click="toggleCompactMode()">
       <i class="icon ion-navicon"></i>
-      <b class="ion-arrow-down-b" style="position: absolute; top: -2px; left: 4px; font-size: 8px;"></b>
-      <b class="ion-arrow-up-b" style="position: absolute; top: 10px; left: 4px; font-size: 8px;"></b>
+      <b class="icon-secondary"
+         ng-class="{'ion-arrow-down-b': !compactMode, 'ion-arrow-up-b': compactMode}"
+         style="top: -9px; left: 9px; font-size: 8px;"></b>
+      <b class="icon-secondary"
+         ng-class="{'ion-arrow-up-b': !compactMode,'ion-arrow-down-b': compactMode}"
+         style="top: 9px; left: 9px; font-size: 8px;"></b>
     </button>
 
     <!-- Allow extension here -->
@@ -12,6 +17,8 @@
   </ion-nav-buttons>
 
   <ion-content>
-    <ng-include src="'templates/blockchain/list_blocks.html'"></ng-include>
+    <div class="item item-divider" translate>BLOCKCHAIN.LOOKUP.LAST_BLOCKS</div>
+
+    <ng-include src="'templates/blockchain/list_blocks.html'"
   </ion-content>
 </ion-view>
diff --git a/www/templates/currency/view_currency.html b/www/templates/currency/view_currency.html
index 1cc471329..bbd7ed3cf 100644
--- a/www/templates/currency/view_currency.html
+++ b/www/templates/currency/view_currency.html
@@ -6,30 +6,28 @@
     {{currency}}
   </ion-nav-title>
 
-  <ion-content class="no-header">
-    <ion-tabs class="tabs-positive tabs-icon-top">
+  <ion-tabs class="tabs-positive tabs-icon-top">
 
-      <ion-tab title="{{'CURRENCY.VIEW.TAB_CURRENCY'|translate}}" icon="ion-stats-bars"
-        ui-sref="app.currency.tab_parameters">
-        <ion-nav-view name="tab-parameters"></ion-nav-view>
-      </ion-tab>
+    <ion-tab title="{{'CURRENCY.VIEW.TAB_CURRENCY'|translate}}" icon="ion-stats-bars"
+      ui-sref="app.currency.tab_parameters">
+      <ion-nav-view name="tab-parameters"></ion-nav-view>
+    </ion-tab>
 
-      <ion-tab title="{{'CURRENCY.VIEW.TAB_WOT'|translate}}" icon="ion-person-stalker"
-               ui-sref="app.currency.tab_wot">
-        <ion-nav-view name="tab-wot"></ion-nav-view>
-      </ion-tab>
+    <ion-tab title="{{'CURRENCY.VIEW.TAB_WOT'|translate}}" icon="ion-person-stalker"
+             ui-sref="app.currency.tab_wot">
+      <ion-nav-view name="tab-wot"></ion-nav-view>
+    </ion-tab>
 
-      <ion-tab id="helptip-currency-tab-peers"
-               title="{{'CURRENCY.VIEW.TAB_NETWORK'|translate}}" icon="ion-cloud"
-               ui-sref="app.currency.tab_network">
-        <ion-nav-view name="tab-network"></ion-nav-view>
-      </ion-tab>
+    <ion-tab id="helptip-currency-tab-peers"
+             title="{{'CURRENCY.VIEW.TAB_NETWORK'|translate}}" icon="ion-cloud"
+             ui-sref="app.currency.tab_network">
+      <ion-nav-view name="tab-network"></ion-nav-view>
+    </ion-tab>
 
-      <ion-tab title="{{'CURRENCY.VIEW.TAB_BLOCKS'|translate}}" icon="ion-lock-combination"
-               ui-sref="app.currency.tab_blocks">
-        <ion-nav-view name="tab-blocks"></ion-nav-view>
-      </ion-tab>
+    <ion-tab title="{{'CURRENCY.VIEW.TAB_BLOCKS'|translate}}" icon="ion-lock-combination"
+             ui-sref="app.currency.tab_blocks">
+      <ion-nav-view name="tab-blocks"></ion-nav-view>
+    </ion-tab>
 
-    </ion-tabs>
-  </ion-content>
+  </ion-tabs>
 </ion-view>
diff --git a/www/templates/network/view_network.html b/www/templates/network/view_network.html
index a28fe3688..baca38310 100644
--- a/www/templates/network/view_network.html
+++ b/www/templates/network/view_network.html
@@ -58,9 +58,28 @@
         <ng-include src="'templates/network/items_peers.html'"></ng-include>
       </div>
 
-      <div class="col col-33"
-           ng-include="'templates/blockchain/list_blocks.html'"
-           ng-controller="BlockLookupCtrl">
+      <div class="col col-33" ng-controller="BlockLookupCtrl">
+
+        <div class="padding padding-xs" style="display: block; height: 100px;">
+          <h4 translate>BLOCKCHAIN.LOOKUP.LAST_BLOCKS</h4>
+
+          <div class="pull-right hidden-xs hidden-sm">
+            <a class="button button-text button-small ink"
+               ng-class="{'button-text-positive': compactMode, 'button-text-stable': !compactMode}"
+               ng-click="toggleCompactMode()" >
+              <i class="icon ion-navicon"></i>
+              <b class="icon-secondary ion-arrow-down-b" style="top: -8px; left: 5px; font-size: 8px;"></b>
+              <b class="icon-secondary ion-arrow-up-b" style="top: 4px; left: 5px; font-size: 8px;"></b>
+              <span>{{'BLOCKCHAIN.LOOKUP.BTN_COMPACT'|translate}}</span>
+            </a>
+
+            <!-- Allow extension here -->
+            <cs-extension-point name="buttons"></cs-extension-point>
+
+          </div>
+        </div>
+
+        <ng-include src="'templates/blockchain/list_blocks.html'"></ng-include>
       </div>
     </div>
   </ion-content>
diff --git a/www/templates/wot/items_given_certifications.html b/www/templates/wot/items_given_certifications.html
index e31105536..311ace011 100644
--- a/www/templates/wot/items_given_certifications.html
+++ b/www/templates/wot/items_given_certifications.html
@@ -1,65 +1,65 @@
 
-        <div class="list animate-fade-slide-in-right given-certifications">
-          <span class="item item-divider hidden-xs">
-            <span translate>WOT.GIVEN_CERTIFICATIONS.SUMMARY</span>
-          </span>
+<div class="list animate-fade-slide-in-right given-certifications">
+  <span class="item item-divider hidden-xs">
+    <span translate>WOT.GIVEN_CERTIFICATIONS.SUMMARY</span>
+  </span>
 
-          <!-- Signature stock -->
-          <div id="helptip-certs-stock"
-               class="item item-icon-left item-text-wrap ink">
-            <i class="icon ion-ribbon-a"></i>
-            <span translate>WOT.GIVEN_CERTIFICATIONS.SENT</span>
+  <!-- Signature stock -->
+  <div id="helptip-certs-stock"
+       class="item item-icon-left item-text-wrap ink">
+    <i class="icon ion-ribbon-a"></i>
+    <span translate>WOT.GIVEN_CERTIFICATIONS.SENT</span>
 
-            <span class="badge"
-                  ng-class="{'badge-calm': formData.given_cert.length < formData.sigStock, 'badge-assertive': formData.given_cert.length >= formData.sigStock}">
-              <span>
-                <i ng-if="formData.given_cert.length" class="ion-android-done"></i>
-                {{formData.given_cert.length}}
-              </span>
-              <span ng-if="formData.given_cert_pending.length">
-                (<ng-if ng-if="formData.given_cert.length">+ </ng-if>
-                <i class="ion-clock"></i>
-                {{formData.given_cert_pending.length}})
-              </span>
-              <small>/ {{formData.sigStock}}</small>
-            </span>
-          </div>
+    <span class="badge"
+          ng-class="{'badge-calm': formData.given_cert.length < formData.sigStock, 'badge-assertive': formData.given_cert.length >= formData.sigStock}">
+      <span>
+        <i ng-if="formData.given_cert.length" class="ion-android-done"></i>
+        {{formData.given_cert.length}}
+      </span>
+      <span ng-if="formData.given_cert_pending.length">
+        (<ng-if ng-if="formData.given_cert.length">+ </ng-if>
+        <i class="ion-clock"></i>
+        {{formData.given_cert_pending.length}})
+      </span>
+      <small>/ {{formData.sigStock}}</small>
+    </span>
+  </div>
 
-          <!-- Error certifications count -->
-          <div class="item item-icon-left item-text-wrap ink" ng-if="formData.given_cert_error.length">
-            <i class="icon ion-alert-circled"></i>
-            <span translate>WOT.GIVEN_CERTIFICATIONS.ERROR</span>
+  <!-- Error certifications count -->
+  <div class="item item-icon-left item-text-wrap ink" ng-if="formData.given_cert_error.length">
+    <i class="icon ion-alert-circled"></i>
+    <span translate>WOT.GIVEN_CERTIFICATIONS.ERROR</span>
 
-            <span class="badge badge-assertive" >
-              {{formData.given_cert_error.length}}
-            </span>
-          </div>
+    <span class="badge badge-assertive" >
+      {{formData.given_cert_error.length}}
+    </span>
+  </div>
 
-          <!-- pending given certifications -->
-          <span class="item item-divider" ng-if="formData.given_cert_pending.length">
-            <span translate>WOT.GIVEN_CERTIFICATIONS.PENDING_LIST</span>
-            <div class="badge item-note" style="text-align: right !important;" translate>WOT.NOT_WRITTEN_EXPIRE_IN</div>
-          </span>
+  <!-- pending given certifications -->
+  <span class="item item-divider" ng-if="formData.given_cert_pending.length">
+    <span translate>WOT.GIVEN_CERTIFICATIONS.PENDING_LIST</span>
+    <div class="badge item-note" style="text-align: right !important;" translate>WOT.NOT_WRITTEN_EXPIRE_IN</div>
+  </span>
 
-          <a class="item item-avatar ink"
-             ng-repeat="cert in formData.given_cert_pending"
-             ui-sref="app.wot_identity({pubkey:cert.pubkey, uid:cert.uid})"
-             ng-include="'templates/wot/item_certification.html'">
-          </a>
+  <a class="item item-avatar ink"
+     ng-repeat="cert in formData.given_cert_pending"
+     ui-sref="app.wot_identity({pubkey:cert.pubkey, uid:cert.uid})"
+     ng-include="'templates/wot/item_certification.html'">
+  </a>
 
-          <!-- validated given certifications -->
-          <span class="item item-divider">
-            <span translate>WOT.GIVEN_CERTIFICATIONS.LIST</span>
-            <div class="badge item-note" translate>WOT.EXPIRE_IN</div>
-          </span>
+  <!-- validated given certifications -->
+  <span class="item item-divider">
+    <span translate>WOT.GIVEN_CERTIFICATIONS.LIST</span>
+    <div class="badge item-note" translate>WOT.EXPIRE_IN</div>
+  </span>
 
-          <span class="item gray" ng-if="!formData.given_cert.length" translate>
-            WOT.NO_GIVEN_CERTIFICATION
-          </span>
+  <span class="item gray" ng-if="!formData.given_cert.length" translate>
+    WOT.NO_GIVEN_CERTIFICATION
+  </span>
 
-          <a class="item item-avatar ink"
-                ng-repeat="cert in formData.given_cert"
-                ui-sref="app.wot_identity({pubkey:cert.pubkey, uid:cert.uid})"
-                ng-include="'templates/wot/item_certification.html'">
-          </a>
-        </div>
+  <a class="item item-avatar ink"
+        ng-repeat="cert in formData.given_cert"
+        ui-sref="app.wot_identity({pubkey:cert.pubkey, uid:cert.uid})"
+        ng-include="'templates/wot/item_certification.html'">
+  </a>
+</div>
diff --git a/www/templates/wot/tabs/tab_given_certifications.html b/www/templates/wot/tabs/tab_given_certifications.html
index ee8df2206..5a5c54319 100644
--- a/www/templates/wot/tabs/tab_given_certifications.html
+++ b/www/templates/wot/tabs/tab_given_certifications.html
@@ -4,11 +4,20 @@
     </button>
   </ion-nav-buttons>
 
-  <ion-content ng-init="motions.receivedCertifications=false">
+  <ion-content ng-init="motions.receivedCertifications=false; motions.avatar=false">
     <div class="center padding" ng-if="loading">
       <ion-spinner icon="android"></ion-spinner>
     </div>
 
     <ng-include src="'templates/wot/items_given_certifications.html'"></ng-include>
   </ion-content>
+
+  <!-- fab button -->
+  <div class="visible-xs visible-sm">
+    <button id="fab-select-certify" class="button button-fab button-fab-bottom-right button-energized-900 spin"
+            ng-if="canSelectAndCertify || $root.tour"
+            ng-click="selectAndCertify()">
+      <i class="icon ion-plus"></i>
+    </button>
+  </div>
 </ion-view>
diff --git a/www/templates/wot/tabs/tab_received_certifications.html b/www/templates/wot/tabs/tab_received_certifications.html
index 1537ba3b0..d553b658d 100644
--- a/www/templates/wot/tabs/tab_received_certifications.html
+++ b/www/templates/wot/tabs/tab_received_certifications.html
@@ -4,11 +4,20 @@
     </button>
   </ion-nav-buttons>
 
-  <ion-content ng-init="motions.givenCertifications=false">
+  <ion-content ng-init="motions.givenCertifications=false; motions.avatar=false;" class="has-header">
     <div class="center padding" ng-if="loading">
       <ion-spinner icon="android"></ion-spinner>
     </div>
 
     <ng-include src="'templates/wot/items_received_certifications.html'"></ng-include>
   </ion-content>
+
+  <!-- fab button -->
+  <div class="visible-xs visible-sm">
+    <button id="fab-certify" class="button button-fab button-fab-bottom-right button-energized-900 spin"
+            ng-click="certify()"
+            ng-if="(formData.hasSelf && canCertify && !alreadyCertified) || $root.tour">
+      <i class="icon ion-ribbon-b"></i>
+    </button>
+  </div>
 </ion-view>
diff --git a/www/templates/wot/view_certifications.html b/www/templates/wot/view_certifications.html
index 85137aab9..59131dc3a 100644
--- a/www/templates/wot/view_certifications.html
+++ b/www/templates/wot/view_certifications.html
@@ -1,38 +1,21 @@
-<ion-view left-buttons="leftButtons"
-          cache-view="false">
+<ion-view left-buttons="leftButtons">
   <ion-nav-title>
     <span class="visible-xs visible-sm">{{::formData.uid}}</span>
     <span class="hidden-xs hidden-sm" translate="WOT.CERTIFICATIONS.TITLE" translate-values="{uid: formData.uid}"></span>
   </ion-nav-title>
 
-  <ion-content class="certifications no-header">
-    <ion-tabs class="tabs-positive tabs-icon-top">
+  <ion-tabs class="tabs-positive tabs-icon-top certifications">
 
-      <ion-tab title="{{'WOT.CERTIFICATIONS.SUMMARY'|translate}}" icon="ion-ribbon-b"
-               ui-sref="app.wot_cert.received({pubkey: formData.pubkey, uid: formData.uid})">
-        <ion-nav-view name="tab-received-cert"></ion-nav-view>
-      </ion-tab>
+    <ion-tab title="{{'WOT.CERTIFICATIONS.SUMMARY'|translate}}" icon="ion-ribbon-b"
+             ui-sref="app.wot_cert.received({pubkey: formData.pubkey, uid: formData.uid})">
+      <ion-nav-view name="tab-received-cert"></ion-nav-view>
+    </ion-tab>
 
-      <ion-tab title="{{'WOT.GIVEN_CERTIFICATIONS.SUMMARY'|translate}}" icon="ion-ribbon-a"
-               ui-sref="app.wot_cert.given({pubkey: formData.pubkey, uid: formData.uid})">
-        <ion-nav-view name="tab-given-cert"></ion-nav-view>
-      </ion-tab>
+    <ion-tab title="{{'WOT.GIVEN_CERTIFICATIONS.SUMMARY'|translate}}" icon="ion-ribbon-a"
+             ui-sref="app.wot_cert.given({pubkey: formData.pubkey, uid: formData.uid})">
+      <ion-nav-view name="tab-given-cert"></ion-nav-view>
+    </ion-tab>
 
-    </ion-tabs>
-  </ion-content>
-
-  <!-- fab button -->
-  <div class="visible-xs visible-sm">{{$root.tour}}
-    <button id="fab-certify" class="button button-fab button-fab-bottom-right button-energized-900 spin"
-            ng-click="certify()"
-            ng-if="(formData.hasSelf && canCertify && !alreadyCertified) || $root.tour">
-      <i class="icon ion-ribbon-b"></i>
-    </button>
-    <button id="fab-select-certify" class="button button-fab button-fab-bottom-right button-energized-900 spin"
-            ng-if="canSelectAndCertify || $root.tour"
-            ng-click="selectAndCertify()">
-      <i class="icon ion-plus"></i>
-    </button>
-  </div>
+  </ion-tabs>
 
 </ion-view>
-- 
GitLab