From 4aef3e51b651f55c4dd4cf4d5cc02e9fce8ff279 Mon Sep 17 00:00:00 2001
From: blavenie <benoit.lavenier@e-is.pro>
Date: Tue, 21 Feb 2017 21:18:29 +0100
Subject: [PATCH] - simplify code for UI motion management

---
 scss/ionic.app.scss                           |   7 +-
 www/css/ionic.app.css                         |   6 +-
 www/css/style.css                             |   8 +-
 www/js/app.js                                 |  57 ++++----
 www/js/controllers/app-controllers.js         |   6 +
 www/js/controllers/blockchain-controllers.js  |  22 +--
 www/js/controllers/network-controllers.js     |   3 +-
 www/js/controllers/settings-controllers.js    |   4 +-
 www/js/controllers/wallet-controllers.js      |  63 ++-------
 www/js/controllers/wot-controllers.js         | 106 +++++---------
 www/js/directives.js                          |  10 +-
 www/js/services/device-services.js            |  12 +-
 www/js/services/utils-services.js             | 131 ++++++++++++------
 www/js/services/wot-services.js               |   1 -
 .../es/js/controllers/common-controllers.js   |   4 +-
 .../es/js/controllers/message-controllers.js  |  16 +--
 .../controllers/notification-controllers.js   |  17 +--
 .../es/js/controllers/user-controllers.js     |  12 +-
 .../es/templates/blockchain/lookup_form.html  |   2 +-
 www/plugins/es/templates/message/list.html    |   6 +-
 .../notification/list_notification.html       |   2 +-
 .../es/templates/user/edit_profile.html       |   3 +-
 www/templates/blockchain/item_block.html      |   4 +-
 .../blockchain/item_block_empty_lg.html       |   4 +-
 www/templates/blockchain/item_block_lg.html   |   3 +-
 www/templates/blockchain/list_blocks.html     |   4 +-
 www/templates/currency/view_peer.html         |   2 +-
 www/templates/network/items_peers.html        |   5 +-
 www/templates/network/view_peer.html          |   2 +-
 www/templates/wallet/view_wallet.html         |   2 +-
 www/templates/wallet/view_wallet_tx.html      |   2 +-
 .../wallet/view_wallet_tx_error.html          |   2 +-
 .../wot/items_given_certifications.html       |   2 +-
 .../wot/items_received_certifications.html    |   2 +-
 www/templates/wot/lookup_form.html            |   3 +-
 www/templates/wot/view_certifications.html    |   8 +-
 www/templates/wot/view_identity.html          |   8 +-
 37 files changed, 247 insertions(+), 304 deletions(-)

diff --git a/scss/ionic.app.scss b/scss/ionic.app.scss
index 055f3cb5..61489aa7 100644
--- a/scss/ionic.app.scss
+++ b/scss/ionic.app.scss
@@ -1110,9 +1110,9 @@ a.underline:hover,
   }
 }
 
-/**********
-   Motion
-**********/
+/************************
+   Additional motions
+*************************/
 
 .fade-in {
   opacity: 0;
@@ -1131,7 +1131,6 @@ a.underline:hover,
    Item > Avatar
 **********/
 
-
 .item-avatar {
   min-height: 80px !important;
 }
diff --git a/www/css/ionic.app.css b/www/css/ionic.app.css
index 5586b792..aecf0b62 100644
--- a/www/css/ionic.app.css
+++ b/www/css/ionic.app.css
@@ -14535,9 +14535,9 @@ a.underline:hover,
   .lookupForm .list .item-avatar .img {
     left: 16px !important; }
 
-/**********
-   Motion
-**********/
+/************************
+   Additional motions
+*************************/
 .fade-in {
   opacity: 0;
   filter: alpha(opacity=0);
diff --git a/www/css/style.css b/www/css/style.css
index 8018bac8..bfee1d68 100644
--- a/www/css/style.css
+++ b/www/css/style.css
@@ -138,18 +138,18 @@
     display:none;
 }
 
-.peer-item {
+.item-peer {
     padding-top: 9px;
     padding-bottom: 3px;
 }
 
-.peer-item .badge {
+.item-peer .badge {
     top: 14px;
     right: 6%;
 }
 
-.peer-item:hover .badge.badge-energized,
-.peer-item:hover .badge.badge-balanced
+.item-peer:hover .badge.badge-energized,
+.item-peer:hover .badge.badge-balanced
 {
     color: #fff !important;
 }
diff --git a/www/js/app.js b/www/js/app.js
index 4edcf83f..bfe47746 100644
--- a/www/js/app.js
+++ b/www/js/app.js
@@ -312,7 +312,6 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht
   $rootScope.walletData = csWallet.data;
   $rootScope.device = Device;
 
-
   // removeIf(device)
   // Automatic redirection to large state (if define)
   $rootScope.$on('$stateChangeStart', function (event, next, nextParams, fromState) {
@@ -323,8 +322,6 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht
         $state.go(next.data.large, nextParams);
       }
     }
-
-
   });
   // endRemoveIf(device)
 
@@ -381,36 +378,34 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht
 
   // We use 'Device.ready()' instead of '$ionicPlatform.ready()', because this one is callable many times
   Device.ready()
-  .then(function() {
-
-    // Keyboard
-    if (window.cordova && window.cordova.plugins.Keyboard) {
-      // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
-      // for form inputs)
-      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
-
-      // iOS: do not push header up when opening keyboard
-      // (see http://ionicframework.com/docs/api/page/keyboard/)
-      if (ionic.Platform.isIOS()) {
-        cordova.plugins.Keyboard.disableScroll(true);
+    .then(function() {
+
+      // Keyboard
+      if (window.cordova && window.cordova.plugins.Keyboard) {
+        // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
+        // for form inputs)
+        cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
+
+        // iOS: do not push header up when opening keyboard
+        // (see http://ionicframework.com/docs/api/page/keyboard/)
+        if (ionic.Platform.isIOS()) {
+          cordova.plugins.Keyboard.disableScroll(true);
+        }
       }
-    }
 
-    // Ionic Platform Grade is not A, disabling views transitions
-    if (ionic.Platform.grade.toLowerCase()!='a') {
-      console.log('Disable UI effects - plateform\'s grade is not [a] but [' + ionic.Platform.grade + ']');
-      $ionicConfig.views.transition('none');
-      // FIXME: some effect appears anyway...
-      // UIUtils.disableEffects();
-    }
-  })
-  // Status bar style
-  .then(function() {
-    if (window.StatusBar) {
-      // org.apache.cordova.statusbar required
-      StatusBar.styleDefault();
-    }
-  });
+      // Ionic Platform Grade is not A, disabling views transitions
+      if (ionic.Platform.grade.toLowerCase()!='a') {
+        console.log('Disable UI effects - plateform\'s grade is not [a] but [' + ionic.Platform.grade + ']');
+        UIUtils.setEffects(false);
+      }
+    })
+    // Status bar style
+    .then(function() {
+      if (window.StatusBar) {
+        // org.apache.cordova.statusbar required
+        StatusBar.styleDefault();
+      }
+    });
 
   var onLanguageChange = function() {
     var lang = $translate.use();
diff --git a/www/js/controllers/app-controllers.js b/www/js/controllers/app-controllers.js
index d30b3a67..d3ccebc9 100644
--- a/www/js/controllers/app-controllers.js
+++ b/www/js/controllers/app-controllers.js
@@ -89,6 +89,7 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $
 
   $scope.search = {};
   $scope.login = csWallet.isLogin();
+  $scope.motion = UIUtils.motion.default;
 
   $scope.showHome = function() {
     $ionicHistory.nextViewOptions({
@@ -413,6 +414,11 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $
     UIUtils.motion.toggleOff({selector: '#'+id + '.button-fab'}, timeout);
   };
 
+  // Could be override by subclass
+  $scope.doMotion = function(options) {
+    return $scope.motion.show(options);
+  };
+
 }
 
 
diff --git a/www/js/controllers/blockchain-controllers.js b/www/js/controllers/blockchain-controllers.js
index 9974631e..8e427f00 100644
--- a/www/js/controllers/blockchain-controllers.js
+++ b/www/js/controllers/blockchain-controllers.js
@@ -281,15 +281,7 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho
 
     // Set Motion
     if (res.length > 0) {
-      $timeout(function () {
-        UIUtils.motion.ripple({
-          startVelocity: 3000
-        });
-        // Set Ink
-        UIUtils.ink({
-          selector: '.item.ink'
-        });
-      }, 10);
+      $scope.motion.show({selector: '.list-blocks .item-block'});
     }
 
     $scope.$broadcast('$$rebind::rebind'); // notify binder
@@ -322,17 +314,7 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho
     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
-        });
-      });
+      $scope.motion.show({selector: '#block-'+block.number});
     };
 
     $scope.wsBlock.on(function(json) {
diff --git a/www/js/controllers/network-controllers.js b/www/js/controllers/network-controllers.js
index cc86c584..68c5c5d9 100644
--- a/www/js/controllers/network-controllers.js
+++ b/www/js/controllers/network-controllers.js
@@ -43,7 +43,7 @@ angular.module('cesium.network.controllers', ['cesium.services'])
 
 ;
 
-function NetworkLookupController($scope, $timeout, $state, $ionicHistory, $ionicPopover, BMA, UIUtils, csSettings, csCurrency, csNetwork, csWot) {
+function NetworkLookupController($scope,  $state, $ionicHistory, $ionicPopover, BMA, UIUtils, csSettings, csCurrency, csNetwork, csWot) {
   'ngInject';
 
   $scope.networkStarted = false;
@@ -153,6 +153,7 @@ function NetworkLookupController($scope, $timeout, $state, $ionicHistory, $ionic
     $scope.search.memberPeersCount = data.memberPeersCount;
     // Always tru if network not started (e.g. after leave+renter the view)
     $scope.search.loading = !$scope.networkStarted || csNetwork.isBusy();
+    $scope.motion.show({selector: '.item-peer'});
   };
 
   $scope.refresh = function() {
diff --git a/www/js/controllers/settings-controllers.js b/www/js/controllers/settings-controllers.js
index d7bab5a6..1c4b32be 100644
--- a/www/js/controllers/settings-controllers.js
+++ b/www/js/controllers/settings-controllers.js
@@ -162,10 +162,12 @@ function SettingsController($scope, $q, $ionicPopup, $timeout, $translate, csHtt
     };
 
   $scope.save = function() {
-    if ($scope.loading) return $q.when();
+    if ($scope.loading || $scope.pendingSaving) return $q.when();
     if ($scope.saving) {
+      $scope.pendingSaving = true;
       // Retry later
       return $timeout(function() {
+        $scope.pendingSaving = false;
         return $scope.save();
       }, 500);
     }
diff --git a/www/js/controllers/wallet-controllers.js b/www/js/controllers/wallet-controllers.js
index c936943d..2b3f0b1f 100644
--- a/www/js/controllers/wallet-controllers.js
+++ b/www/js/controllers/wallet-controllers.js
@@ -73,17 +73,8 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state,
       });
   });
 
-  // Update view
   $scope.updateView = function() {
-    // Set Motion
-    $timeout(function() {
-      UIUtils.motion.fadeSlideInRight({
-        selector: '#wallet .animate-fade-slide-in-right .item',
-        startVelocity: 3000
-      });
-      // Set Ink
-      UIUtils.ink({selector: '#wallet .animate-fade-slide-in-right .item'});
-    });
+    $scope.motion.show({selector: '#wallet .item'});
   };
 
   $scope.setRegisterForm = function(registerForm) {
@@ -369,16 +360,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state,
         if (done) {
           UIUtils.toast.show('INFO.TRANSFER_SENT');
           $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance
-
-          // Set Motion
-          $timeout(function() {
-            UIUtils.motion.ripple({
-              selector: '.item-pending',
-              startVelocity: 3000
-            });
-            // Set Ink
-            UIUtils.ink({selector: '.item-pending'});
-          }, 10);
+          $scope.motion.show({selector: '.item-pending'});
         }
       });
   };
@@ -512,11 +494,15 @@ function WalletTxController($scope, $rootScope, $timeout, $filter, UIUtils, csWa
       });
   });
 
-  $scope.onSettingsChanged = function() {
+  $scope.updateUnit = function() {
     if (!$scope.formData || $scope.loading) return;
     $scope.unit = $filter('currencySymbol')($scope.formData.currency, csSettings.data.useRelative);
     $scope.secondaryUnit = $filter('currencySymbol')($scope.formData.currency, !csSettings.data.useRelative);
   };
+
+  $scope.onSettingsChanged = function() {
+    $scope.updateUnit();
+  };
   $scope.$watch('settings.useRelative', $scope.onSettingsChanged);
 
   // Reload if show UD changed
@@ -528,14 +514,8 @@ function WalletTxController($scope, $rootScope, $timeout, $filter, UIUtils, csWa
   // Update view
   $scope.updateView = function() {
     $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance
-
-    $scope.onSettingsChanged();
-    // Set Motion
-    $timeout(function() {
-      UIUtils.motion.fadeSlideInRight({selector: '#wallet-tx .animate-fade-slide-in-right .item'});
-      // Set Ink
-      UIUtils.ink({selector: '#wallet-tx .animate-fade-slide-in-right .item'});
-    }, 10);
+    $scope.updateUnit();
+    $scope.motion.show({selector: '#wallet-tx .list .item'});
   };
 
   // Updating wallet data
@@ -568,16 +548,7 @@ function WalletTxController($scope, $rootScope, $timeout, $filter, UIUtils, csWa
         if (done) {
           UIUtils.toast.show('INFO.TRANSFER_SENT');
           $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance
-
-          // Set Motion
-          $timeout(function() {
-            UIUtils.motion.ripple({
-              selector: '.item-pending',
-              startVelocity: 3000
-            });
-            // Set Ink
-            UIUtils.ink({selector: '.item-pending'});
-          }, 10);
+          $scope.motion.show({selector: '.item-pending'});
         }
       });
   };
@@ -613,28 +584,18 @@ function WalletTxController($scope, $rootScope, $timeout, $filter, UIUtils, csWa
 
 }
 
-function WalletTxErrorController($scope, $timeout, UIUtils, csWallet) {
+function WalletTxErrorController($scope, UIUtils, csWallet) {
   'ngInject';
 
   $scope.$on('$ionicView.enter', function(e) {
     $scope.loadWallet()
       .then(function() {
-        $scope.updateView();
+        $scope.doMotion();
         $scope.showFab('fab-redo-transfer');
         UIUtils.loading.hide();
       });
   });
 
-  // Update view
-  $scope.updateView = function() {
-    // Set Motion
-    $timeout(function() {
-      UIUtils.motion.fadeSlideInRight();
-      // Set Ink
-      UIUtils.ink({selector: '.item'});
-    }, 10);
-  };
-
   // Updating wallet data
   $scope.doUpdate = function() {
     UIUtils.loading.show();
diff --git a/www/js/controllers/wot-controllers.js b/www/js/controllers/wot-controllers.js
index 92291501..f7b5fbd2 100644
--- a/www/js/controllers/wot-controllers.js
+++ b/www/js/controllers/wot-controllers.js
@@ -233,7 +233,12 @@ function WotLookupController($scope, $state, $timeout, $focus, $ionicPopover, $i
     $scope.search.loading = (offset === 0);
     $scope.search.type = 'newcomers';
 
-    csWot.newcomers(offset, size)
+    // Update location href
+    if (!offset) {
+      $scope.doRefreshLocationHref();
+    }
+
+    return csWot.newcomers(offset, size)
       .then(function(idties){
         if ($scope.search.type != 'newcomers') return false; // could have change
         $scope.doDisplayResult(idties, offset, size);
@@ -245,9 +250,6 @@ function WotLookupController($scope, $state, $timeout, $focus, $ionicPopover, $i
         $scope.search.hasMore = false;
         UIUtils.onError('ERROR.LOAD_NEWCOMERS_FAILED')(err);
       });
-
-    // Update location href
-    $scope.doRefreshLocationHref();
   };
 
   $scope.doGetPending = function(offset, size) {
@@ -263,7 +265,12 @@ function WotLookupController($scope, $state, $timeout, $focus, $ionicPopover, $i
       csWot.all :
       csWot.pending;
 
-    searchFunction(offset, size)
+    // Update location href
+    if (!offset) {
+      $scope.doRefreshLocationHref();
+    }
+
+    return searchFunction(offset, size)
       .then(function(idties){
         if ($scope.search.type != 'pending') return false; // could have change
         $scope.doDisplayResult(idties, offset, size);
@@ -277,9 +284,6 @@ function WotLookupController($scope, $state, $timeout, $focus, $ionicPopover, $i
         $scope.search.hasMore = false;
         UIUtils.onError('ERROR.LOAD_PENDING_FAILED')(err);
       });
-
-    // Update location href
-    $scope.doRefreshLocationHref();
   };
 
   $scope.showMore = function() {
@@ -378,17 +382,9 @@ function WotLookupController($scope, $state, $timeout, $focus, $ionicPopover, $i
 
     if (!$scope.search.results.length) return;
 
-    // Set Motion
+    // Motion
     if (res.length > 0) {
-      $timeout(function () {
-        UIUtils.motion.ripple({
-          startVelocity: 3000
-        });
-        // Set Ink
-        UIUtils.ink({
-          selector: '.item.ink'
-        });
-      }, 10);
+      $scope.motion.show({selector: '.lookupForm .item.ink'});
     }
   };
 
@@ -525,7 +521,6 @@ function WotIdentityAbstractController($scope, $rootScope, $state, $timeout, $tr
           return;
         }
 
-
         UIUtils.alert.confirm('CONFIRM.CERTIFY_RULES')
           .then(function(confirm){
             if (!confirm) {
@@ -658,14 +653,6 @@ function WotIdentityAbstractController($scope, $rootScope, $state, $timeout, $tr
     cert.name = csWallet.data.name;
   };
 
-  // Could be override by subclass
-  $scope.doMotion = function() {
-    $timeout(function() {
-      UIUtils.motion.fadeSlideInRight();
-      UIUtils.ink();
-    }, 10);
-  };
-
   /* -- open screens -- */
 
   $scope.showCertifications = function() {
@@ -719,11 +706,13 @@ function WotIdentityAbstractController($scope, $rootScope, $state, $timeout, $tr
 /**
  * Identity view controller - should extend WotIdentityAbstractCtrl
  */
-function WotIdentityViewController($scope, $controller, $timeout, UIUtils, csWallet) {
+function WotIdentityViewController($scope, $controller, UIUtils, csWallet) {
   'ngInject';
   // Initialize the super class and extend it.
   angular.extend(this, $controller('WotIdentityAbstractCtrl', {$scope: $scope}));
 
+  $scope.motion = UIUtils.motion.fadeSlideInRight;
+
   $scope.$on('$ionicView.enter', function(e, state) {
 
     if (state.stateParams &&
@@ -731,9 +720,7 @@ function WotIdentityViewController($scope, $controller, $timeout, UIUtils, csWal
       state.stateParams.pubkey.trim().length > 0) {
       if ($scope.loading) { // load once
         return $scope.load(state.stateParams.pubkey.trim(), true /*withCache*/, state.stateParams.uid)
-          .then(function() {
-            $scope.doMotion();
-          });
+          .then($scope.doMotion);
       }
     }
 
@@ -742,9 +729,7 @@ function WotIdentityViewController($scope, $controller, $timeout, UIUtils, csWal
       state.stateParams.uid.trim().length > 0) {
       if ($scope.loading) { // load once
         return $scope.load(null, true /*withCache*/, state.stateParams.uid)
-          .then(function() {
-            $scope.doMotion();
-          });
+          .then($scope.doMotion);
       }
     }
 
@@ -753,9 +738,7 @@ function WotIdentityViewController($scope, $controller, $timeout, UIUtils, csWal
 
       if ($scope.loading) {
         return $scope.load(csWallet.data.pubkey, true /*withCache*/, csWallet.data.uid)
-          .then(function() {
-            $scope.doMotion();
-          });
+          .then($scope.doMotion);
       }
     }
 
@@ -766,12 +749,7 @@ function WotIdentityViewController($scope, $controller, $timeout, UIUtils, csWal
   });
 
   $scope.doMotion = function() {
-    // Effects
-    $timeout(function () {
-      UIUtils.motion.fadeSlideInRight({startVelocity: 3000});
-      UIUtils.ink();
-    });
-
+    $scope.motion.show({selector: '.view-identity .list .item'});
     $scope.showFab('fab-transfer');
   };
 }
@@ -786,16 +764,19 @@ function WotCertificationsViewController($scope, $rootScope, $controller, $timeo
 
   // Values overwritten in tab controller (for small screen)
   $scope.motions = {
-    receivedCertifications: true,
-    givenCertifications: true,
-    avatar: true
+    receivedCertifications: angular.copy(UIUtils.motion.fadeSlideIn),
+    givenCertifications: angular.copy(UIUtils.motion.fadeSlideInRight),
+    avatar: angular.copy(UIUtils.motion.fadeIn),
   };
+  $scope.motions.receivedCertifications.enable = true;
+  $scope.motions.givenCertifications.enable = true;
+  $scope.motions.avatar.enable = true;
 
   $scope.$on('$ionicView.enter', function(e, state) {
     if (state.stateParams && state.stateParams.type) {
-      $scope.motions.receivedCertifications = (state.stateParams.type != 'given');
-      $scope.motions.givenCertifications = (state.stateParams.type == 'given');
-      $scope.motions.avatar= false;
+      $scope.motions.receivedCertifications.enable = (state.stateParams.type != 'given');
+      $scope.motions.givenCertifications.enable = (state.stateParams.type == 'given');
+      $scope.motions.avatar.enable = false;
     }
 
     if (state.stateParams &&
@@ -852,28 +833,19 @@ function WotCertificationsViewController($scope, $rootScope, $controller, $timeo
     $scope.doMotionReceivedCertifications(0, skipItems);
 
     // Motion on avatar part
-    if ($scope.motions.avatar) {
-      // Effects
-      $timeout(function () {
-        UIUtils.motion.toggleOn({
-          selector: '.col-avatar .motion'
-        });
-      }, 300);
+    if ($scope.motions.avatar.enable) {
+      $scope.motions.avatar.show({selector: '.col-avatar .' + $scope.motions.avatar.ionListClass});
     }
 
     // Motion on given certification part
-    $scope.doMotionGivenCertifications($scope.motions.receivedCertifications ? 800 : 10, skipItems);
+    $scope.doMotionGivenCertifications($scope.motions.receivedCertifications.enable ? 100 : 10, skipItems);
   };
 
   // Effects on received certifcations
   $scope.doMotionReceivedCertifications = function(timeout, skipItems) {
-    if ($scope.motions.receivedCertifications) {
+    if ($scope.motions.receivedCertifications.enable) {
       if (!skipItems) {
-        // List items
-        $timeout(function () {
-          UIUtils.motion.fadeSlideInRight({selector: '.list.certifications .item', startVelocity: 3000});
-          UIUtils.ink({selector: '.list.certifications .ink'});
-        }, timeout || 10);
+        $scope.motions.receivedCertifications.show({selector: '.list.certifications .item', timeout: timeout});
       }
 
       // Fab button
@@ -893,13 +865,9 @@ function WotCertificationsViewController($scope, $rootScope, $controller, $timeo
   // Effects on given certifcations
   $scope.doMotionGivenCertifications = function(timeout, skipItems) {
 
-    if ($scope.motions.givenCertifications) {
+    if ($scope.motions.givenCertifications.enable) {
       if (!skipItems) {
-        // List items
-        $timeout(function() {
-          UIUtils.motion.fadeSlideInRight({selector: '.list.given-certifications .item', startVelocity: 3000});
-          UIUtils.ink({selector: '.list.given-certifications .ink'});
-        }, timeout || 10);
+        $scope.motions.givenCertifications.show({selector: '.list.given-certifications .item', timeout: timeout});
       }
       // Fab button
       if ($scope.canSelectAndCertify || $rootScope.tour) {
diff --git a/www/js/directives.js b/www/js/directives.js
index 558ccea8..9e73c85b 100644
--- a/www/js/directives.js
+++ b/www/js/directives.js
@@ -48,16 +48,20 @@ angular.module('cesium')
   })
 
   // Add a copy-on-click directive
-  .directive('copyOnClick', function ($window, $document, Device, UIUtils, $ionicPopover, $timeout) {
+  .directive('copyOnClick', function ($window, $document, Device, UIUtils) {
     'ngInject';
     return {
       restrict: 'A',
       link: function (scope, element, attrs) {
-        //var childScope;
         var showCopyPopover = function (event) {
           var value = attrs.copyOnClick;
           if (value && Device.clipboard.enable) {
-            Device.clipboard.copy(value); // copy to clipboard
+            // copy to clipboard
+            Device.clipboard.copy(value)
+              .then(function(){
+                UIUtils.toast.show('INFO.COPY_TO_CLIPBOARD_DONE');
+              })
+              .catch(UIUtils.onError('ERROR.COPY_CLIPBOARD'));
           }
           else if (value) {
             var rows = value && value.indexOf('\n') >= 0 ? value.split('\n').length : 1;
diff --git a/www/js/services/device-services.js b/www/js/services/device-services.js
index ac0a4164..64456c56 100644
--- a/www/js/services/device-services.js
+++ b/www/js/services/device-services.js
@@ -2,7 +2,7 @@
 angular.module('cesium.device.services', ['ngResource', 'cesium.utils.services'])
 
   .factory('Device',
-    function(UIUtils, $translate, $ionicPopup, $q,
+    function($translate, $ionicPopup, $q,
       // removeIf(no-device)
       $cordovaClipboard, $cordovaBarcodeScanner, $cordovaCamera,
       // endRemoveIf(no-device)
@@ -110,8 +110,9 @@ angular.module('cesium.device.services', ['ngResource', 'cesium.utils.services']
 
       function copy(text, callback) {
         if (!exports.enable) {
-          return; // do nothing if not available
+          return $q.reject('Device disabled');
         }
+        var deferred = $q.defer();
         $cordovaClipboard
           .copy(text)
           .then(function () {
@@ -119,13 +120,12 @@ angular.module('cesium.device.services', ['ngResource', 'cesium.utils.services']
             if (callback) {
               callback();
             }
-            else {
-              UIUtils.toast.show('INFO.COPY_TO_CLIPBOARD_DONE');
-            }
+            deferred.resolve();
           }, function () {
             // error
-            UIUtils.alert.error('ERROR.COPY_CLIPBOARD');
+            deferred.reject({message: 'ERROR.COPY_CLIPBOARD'});
           });
+        return deferred.promise;
       }
 
       // On platform ready: check if device could be used
diff --git a/www/js/services/utils-services.js b/www/js/services/utils-services.js
index b20098ff..a1e6c162 100644
--- a/www/js/services/utils-services.js
+++ b/www/js/services/utils-services.js
@@ -1,7 +1,7 @@
 angular.module('cesium.utils.services', ['ngResource'])
 
-.factory('UIUtils', function($ionicLoading, $ionicPopup, $translate, $q, ionicMaterialInk, ionicMaterialMotion, $window, $timeout,
-           $ionicPopover, $state, $rootScope, screenmatch) {
+.factory('UIUtils', function($ionicLoading, $ionicPopup, $ionicConfig, $translate, $q, ionicMaterialInk, ionicMaterialMotion, $window, $timeout,
+           $ionicPopover, $state, $rootScope, screenmatch, csSettings) {
   'ngInject';
 
 
@@ -15,7 +15,9 @@ angular.module('cesium.utils.services', ['ngResource'])
     },
     data = {
       smallscreen: screenmatch.bind('xs, sm', $rootScope)
-    }
+    },
+    exports,
+    raw = {}
   ;
 
   function alertError(err, subtitle) {
@@ -465,37 +467,6 @@ angular.module('cesium.utils.services', ['ngResource'])
     return deferred.promise;
   }
 
-  function disableEffects() {
-    this.ink = function(){};
-
-    function disableMotion(baseSelector) {
-      return function(options) {
-        if (!options || !options.selector) {
-          options = {
-              selector: (baseSelector + ' .item')
-            };
-        }
-        var parentsInDom = document.querySelectorAll(baseSelector);
-        for (var i = 0; i < parentsInDom.length; i++) {
-            var parent = parentsInDom[i];
-            parent.className = parent.className.replace(/\banimate-[a-z- ]+\b/,'');
-        }
-
-        var itemsInDom = document.querySelectorAll(options.selector);
-        for (var j = 0; j < itemsInDom.length; j++) {
-            var child = itemsInDom[j];
-            child.style.webkitTransitionDelay = "0s";
-            child.style.transitionDelay = "0s";
-            child.className += ' in done';
-        }
-      };
-    }
-
-    this.motion.fadeSlideIn= disableMotion('.animate-fade-slide-in');
-    this.motion.fadeSlideInRight = disableMotion('.animate-fade-slide-in-right');
-    this.motion.ripple = disableMotion('.animate-ripple');
-  }
-
   function showFab(id, timeout) {
     if (!timeout) {
       timeout = 900;
@@ -528,7 +499,76 @@ angular.module('cesium.utils.services', ['ngResource'])
     }, timeout);
   }
 
-  ionicMaterialMotion.toggleOn = function(options, timeout) {
+  function motionDelegate(callback, ionListClass) {
+    var motionTimeout = isSmallScreen() ? 100 : 10;
+    return {
+      ionListClass: ionListClass,
+      show: function(options) {
+        options = options || {};
+        options.ink = angular.isDefined(options.ink) ? options.ink : true;
+        options.startVelocity = options.startVelocity || (isSmallScreen() ? 1100 : 3000);
+        return $timeout(function(){
+          if (options.ink) {
+            ionicMaterialInk.displayEffect({selector: options.selector});
+          }
+          callback(options);
+        }, options.timeout ||motionTimeout );
+      }
+    };
+  }
+
+  function setEffects(enable) {
+    if (exports.motion.enable === enable) return; // same
+    console.debug('[UI] [effects] ' + (enable ? 'Enable' : 'Disable'));
+
+    if (enable) {
+      $ionicConfig.views.transition('platform');
+      exports.motion = raw.motion;
+    }
+    else {
+      $ionicConfig.views.transition('none');
+      var nothing = {
+        class: undefined,
+        show: function(){}
+      };
+      exports.motion = {
+        enable : false,
+        default: nothing,
+        fadeSlideIn: nothing,
+        fadeSlideInRight: nothing,
+        panInLeft: nothing,
+        pushDown: nothing,
+        ripple: nothing,
+        slideUp: nothing,
+        fadeIn: nothing,
+        toggleOn: toggleOn,
+        toggleOff: toggleOff
+      };
+    }
+  }
+
+  raw.motion = {
+    enable: true,
+    default: motionDelegate(function(options){
+      ionicMaterialMotion.ripple(options);
+      ionicMaterialInk.displayEffect(options);
+    }, 'animate-ripple'),
+    blinds: motionDelegate(ionicMaterialMotion.blinds, 'animate-blinds'),
+    fadeSlideIn: motionDelegate(ionicMaterialMotion.fadeSlideIn, 'animate-fade-slide-in'),
+    fadeSlideInRight: motionDelegate(ionicMaterialMotion.fadeSlideInRight, 'animate-fade-slide-in-right'),
+    panInLeft: motionDelegate(ionicMaterialMotion.panInLeft, 'animate-pan-in-left'),
+    pushDown: motionDelegate(ionicMaterialMotion.pushDown, 'push-down'),
+    ripple: motionDelegate(ionicMaterialMotion.ripple, 'animate-ripple'),
+    slideUp: motionDelegate(ionicMaterialMotion.slideUp, 'slide-up'),
+    fadeIn: motionDelegate(function(options) {
+        toggleOn(options);
+      }, 'fade-in'),
+    toggleOn: toggleOn,
+    toggleOff: toggleOff
+  };
+
+
+  function toggleOn(options, timeout) {
     // We have a single option, so it may be passed as a string or property
     if (typeof options === 'string') {
       options = {
@@ -550,9 +590,9 @@ angular.module('cesium.utils.services', ['ngResource'])
         element.classList.toggle('on', true);
       });
     }, timeout || 100);
-  };
+  }
 
-  ionicMaterialMotion.toggleOff = function(options, timeout) {
+  function toggleOff(options, timeout) {
     // We have a single option, so it may be passed as a string or property
     if (typeof options === 'string') {
       options = {
@@ -574,9 +614,13 @@ angular.module('cesium.utils.services', ['ngResource'])
         element.classList.toggle('on', false);
       });
     }, timeout || 900);
-  };
+  }
 
-  return {
+  csSettings.api.data.on.changed($rootScope, function(data) {
+   setEffects(data.uiEffects);
+  });
+
+  exports = {
     alert: {
       error: alertError,
       info: alertInfo,
@@ -594,7 +638,8 @@ angular.module('cesium.utils.services', ['ngResource'])
       isSmall: isSmallScreen
     },
     ink: ionicMaterialInk.displayEffect,
-    motion: ionicMaterialMotion,
+    motion: raw.motion,
+    setEffects: setEffects,
     fab: {
       show: showFab,
       hide: hideFab
@@ -604,7 +649,6 @@ angular.module('cesium.utils.services', ['ngResource'])
       share: showSharePopover,
       helptip: showHelptip
     },
-    disableEffects: disableEffects,
     selection: {
       select: selectElementText,
       get: getSelectionText
@@ -612,8 +656,11 @@ angular.module('cesium.utils.services', ['ngResource'])
     image: {
       resizeFile: resizeImageFromFile,
       resizeSrc: resizeImageFromSrc
-    }
+    },
+    raw: raw
   };
+
+  return exports;
 })
 
 
diff --git a/www/js/services/wot-services.js b/www/js/services/wot-services.js
index d41ac686..13f266ab 100644
--- a/www/js/services/wot-services.js
+++ b/www/js/services/wot-services.js
@@ -166,7 +166,6 @@ angular.module('cesium.wot.services', ['ngResource', 'ngApi', 'cesium.bma.servic
               });
             }
             var identity = identities[0];
-            console.log(identity);
 
             identity.hasSelf = !!(identity.uid && identity.timestamp && identity.sig);
             identity.lookup = {};
diff --git a/www/plugins/es/js/controllers/common-controllers.js b/www/plugins/es/js/controllers/common-controllers.js
index 71cd3aff..cc033672 100644
--- a/www/plugins/es/js/controllers/common-controllers.js
+++ b/www/plugins/es/js/controllers/common-controllers.js
@@ -164,9 +164,7 @@ function ESCommentsController($scope, $timeout, $filter, $state, $focus, UIUtils
         // Set Motion
         $timeout(function() {
           UIUtils.motion.fadeSlideIn({
-            selector: '.comments .item',
-            startVelocity: 3000
-          });
+            selector: '.comments .item'});
         });
       });
   };
diff --git a/www/plugins/es/js/controllers/message-controllers.js b/www/plugins/es/js/controllers/message-controllers.js
index a0c8f4f5..4e7e04c9 100644
--- a/www/plugins/es/js/controllers/message-controllers.js
+++ b/www/plugins/es/js/controllers/message-controllers.js
@@ -96,14 +96,7 @@ function ESMessageListController($scope, $rootScope, $state, $timeout, $translat
         $scope.loading = false;
 
         if (messages.length > 0) {
-          // Set Motion
-          $timeout(function() {
-            UIUtils.motion.ripple({
-              startVelocity: 3000
-            });
-            // Set Ink
-            UIUtils.ink();
-          });
+          $scope.motion.show({selector: '.view-messages .list .item'});
         }
       })
       .catch(function(err) {
@@ -393,12 +386,7 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis
             $scope.id = message.id;
             $scope.formData = message;
             $scope.canDelete = true;
-            $timeout(function () {
-              UIUtils.motion.fadeSlideIn({
-                selector: '.view-message .animate-fade-slide-in .item',
-                startVelocity: 3000
-              });
-            });
+            $scope.motion.show({selector: '.view-message .list .item'});
             // Mark as read
             if (!message.read) {
               $timeout(function() {
diff --git a/www/plugins/es/js/controllers/notification-controllers.js b/www/plugins/es/js/controllers/notification-controllers.js
index 618b138f..fb73cb71 100644
--- a/www/plugins/es/js/controllers/notification-controllers.js
+++ b/www/plugins/es/js/controllers/notification-controllers.js
@@ -27,11 +27,13 @@ angular.module('cesium.es.notification.controllers', ['cesium.es.services'])
 
 ;
 
-function NotificationsController($scope, $rootScope, $timeout, UIUtils, $state, csWallet, esNotification, csSettings) {
+function NotificationsController($scope, $rootScope, $timeout, UIUtils, $state, csWallet, esNotification) {
   'ngInject';
 
   var defaultSearchLimit = 40;
 
+  var excludedCodes = esNotification.constants.MESSAGE_CODES.concat(esNotification.constants.GROUP_CODES);
+
   $scope.search = {
     loading : true,
     results: null,
@@ -40,7 +42,7 @@ function NotificationsController($scope, $rootScope, $timeout, UIUtils, $state,
     limit: defaultSearchLimit,
     options: {
       codes: {
-        excludes: ['MESSAGE_RECEIVED']
+        excludes: excludedCodes
       }
     }
   };
@@ -80,13 +82,8 @@ function NotificationsController($scope, $rootScope, $timeout, UIUtils, $state,
   };
 
   $scope.updateView = function() {
-
-    // Set Motion and Ink
-    if ($scope.ionListClass) {
-      $timeout(function() {
-        UIUtils.motion.ripple({selector: '.view-notification .item'});
-        UIUtils.ink({selector: '.view-notification .item.ink'});
-      }, 100);
+    if ($scope.motion && $scope.motion.ionListClass) {
+      $scope.motion.show({selector: '.view-notification .item'});
     }
   };
 
@@ -154,7 +151,7 @@ function PopoverNotificationsController($scope, $timeout, $controller, UIUtils,
   angular.extend(this, $controller('NotificationsCtrl', {$scope: $scope}));
 
   // Disable list effects
-  $scope.ionListClass = null;
+  $scope.motion = null;
 
   $scope.$on('popover.shown', function() {
     if ($scope.search.loading) {
diff --git a/www/plugins/es/js/controllers/user-controllers.js b/www/plugins/es/js/controllers/user-controllers.js
index 11defbf9..22546d01 100644
--- a/www/plugins/es/js/controllers/user-controllers.js
+++ b/www/plugins/es/js/controllers/user-controllers.js
@@ -120,16 +120,10 @@ function ProfileController($scope, $rootScope, $timeout, $state, $focus, $transl
     if (profile.avatar) {
       $scope.avatarStyle={'background-image':'url("'+$scope.avatar.src+'")'};
     }
-    // Set Motion
-    $timeout(function() {
-      UIUtils.motion.ripple();
-      // Set Ink
-      UIUtils.ink({selector: 'ion-list > .item.ink'});
-    }, 10);
-
-    // Update loading var
-    // Should be done with a delay, to avoid trigger onFormDataChanged()
+    $scope.motion.show();
     UIUtils.loading.hide();
+
+    // Update loading - done with a delay, to avoid trigger onFormDataChanged()
     $timeout(function() {
       $scope.loading = false;
     }, 1000);
diff --git a/www/plugins/es/templates/blockchain/lookup_form.html b/www/plugins/es/templates/blockchain/lookup_form.html
index 5c294594..835b9828 100644
--- a/www/plugins/es/templates/blockchain/lookup_form.html
+++ b/www/plugins/es/templates/blockchain/lookup_form.html
@@ -61,7 +61,7 @@
     </div>
   </div>
 
-  <ion-list class="list animate-ripple">
+  <ion-list class="list list-blocks" ng-class="::motion.ionListClass">
 
     <ng-include src="'plugins/es/templates/blockchain/items_blocks.html'"></ng-include>
 
diff --git a/www/plugins/es/templates/message/list.html b/www/plugins/es/templates/message/list.html
index 1805c437..9d55d9c1 100644
--- a/www/plugins/es/templates/message/list.html
+++ b/www/plugins/es/templates/message/list.html
@@ -17,7 +17,7 @@
   <ion-content class="padding no-padding-xs">
 
     <!-- Buttons bar-->
-    <ion-list  >
+    <ion-list>
       <div class="item large-button-bar hidden-xs hidden-sm">
 
         <button class="button button-calm icon ion-compose"
@@ -53,9 +53,9 @@
       </div>
     </ion-list>
 
-    <ion-list class="animate-ripple"
+    <ion-list class="{{::motion.ionListClass}}"
               can-swipe="$root.device.enable"
-              ng-if="!loading">
+              ng-hide="loading">
 
       <div class="padding gray" ng-if="!messages.length">
         <span ng-if="type=='inbox'" translate>MESSAGE.NO_MESSAGE_INBOX</span>
diff --git a/www/plugins/es/templates/notification/list_notification.html b/www/plugins/es/templates/notification/list_notification.html
index 47f7e63e..95e49b6a 100644
--- a/www/plugins/es/templates/notification/list_notification.html
+++ b/www/plugins/es/templates/notification/list_notification.html
@@ -1,4 +1,4 @@
-<ion-list class="{{::ionListClass}}">
+<ion-list class="{{::motion.ionListClass}}">
 
   <ion-item
     ng-repeat="notification in search.results"
diff --git a/www/plugins/es/templates/user/edit_profile.html b/www/plugins/es/templates/user/edit_profile.html
index d8ad9ded..d4ca4669 100644
--- a/www/plugins/es/templates/user/edit_profile.html
+++ b/www/plugins/es/templates/user/edit_profile.html
@@ -43,7 +43,8 @@
       <div class="col">
         <form name="profileForm" novalidate="" ng-submit="saveAndClose()">
 
-          <ion-list class="animate-ripple item-text-wrap" ng-init="setForm(profileForm)">
+          <ion-list class="item-text-wrap {{::motion.ionListClass}}"
+                    ng-init="setForm(profileForm)">
 
             <!-- Public info -->
             <div class="item item-icon-left item-text-wrap">
diff --git a/www/templates/blockchain/item_block.html b/www/templates/blockchain/item_block.html
index 6f8c8831..8d7a1172 100644
--- a/www/templates/blockchain/item_block.html
+++ b/www/templates/blockchain/item_block.html
@@ -1,7 +1,7 @@
 <a name="block-{{:rebind:block.number}}"></a>
 <ion-item id="block-{{:rebind:block.number}}"
-          class="item item-icon-left item-block {{ionItemClass}}"
-          ng-class="{'item-block-empty': block.empty, 'compacted': block.compacted && compactMode}"
+          class="item item-icon-left item-block ink"
+          ng-class="{'item-block-empty': block.empty, 'compacted': block.compacted && compactMode, ionItemClass: true}"
           ng-click="selectBlock(block)">
 
   <i class="icon ion-cube stable" ng-if=":rebind:(!block.empty && !block.avatar)"></i>
diff --git a/www/templates/blockchain/item_block_empty_lg.html b/www/templates/blockchain/item_block_empty_lg.html
index 667c52c2..0301fa17 100644
--- a/www/templates/blockchain/item_block_empty_lg.html
+++ b/www/templates/blockchain/item_block_empty_lg.html
@@ -1,8 +1,8 @@
 <a name="block-{{::block.number}}"></a>
 <ion-item id="block-{{::block.number}}"
           ng-if="!block.hide"
-          class="item item-block item-icon-left {{ionItemClass}} item-block-empty"
-          ng-class="{'compacted': block.compacted && compactMode}"
+          class="item item-block item-icon-left item-block-empty"
+          ng-class="{'compacted': block.compacted && compactMode, ionItemClass: true}"
           ng-click="selectBlock(block)"
           >
   <div class="row no-padding" ng-if="!block.compacted || !compactMode">
diff --git a/www/templates/blockchain/item_block_lg.html b/www/templates/blockchain/item_block_lg.html
index ea6158a4..70234a36 100644
--- a/www/templates/blockchain/item_block_lg.html
+++ b/www/templates/blockchain/item_block_lg.html
@@ -1,5 +1,6 @@
 <ion-item id="block-{{::block.number}}"
-          class="item item-block item-icon-left {{::ionItemClass}}"
+          class="item item-block item-icon-left ink"
+          ng-class="::ionItemClass"
           ng-click="selectBlock(block)">
 
   <i class="icon ion-cube stable" ng-if=":rebind:!block.avatar"></i>
diff --git a/www/templates/blockchain/list_blocks.html b/www/templates/blockchain/list_blocks.html
index 90bc71d5..7a660c82 100644
--- a/www/templates/blockchain/list_blocks.html
+++ b/www/templates/blockchain/list_blocks.html
@@ -3,7 +3,7 @@
     <ion-spinner icon="android"></ion-spinner>
   </div>
 
-  <ion-list class="animate-ripple padding padding-xs">
+  <ion-list class="padding padding-xs list-blocks" ng-class="::motion.ionListClass">
     <div class="padding gray" ng-if="!search.loading && !search.results.length" translate>
       BLOCKCHAIN.LOOKUP.NO_BLOCK
     </div>
@@ -15,7 +15,7 @@
 
   <ion-infinite-scroll
     ng-if="search.hasMore"
-    icon="android"
+    spinner="android"
     on-infinite="showMore()"
     distance="1%">
   </ion-infinite-scroll>
diff --git a/www/templates/currency/view_peer.html b/www/templates/currency/view_peer.html
index 918789c0..49c765ae 100644
--- a/www/templates/currency/view_peer.html
+++ b/www/templates/currency/view_peer.html
@@ -14,7 +14,7 @@
                 <ion-spinner class="icon" icon="android"></ion-spinner>
             </div>
 
-            <a class="peer-item item item-icon-left"
+            <a class="item-peer item item-icon-left"
                collection-repeat="peer in peers"
                ng-class="{ assertive: !peer.online, balanced: peer.online }"
                target="_blank"
diff --git a/www/templates/network/items_peers.html b/www/templates/network/items_peers.html
index 7b7b63d8..36262e69 100644
--- a/www/templates/network/items_peers.html
+++ b/www/templates/network/items_peers.html
@@ -1,4 +1,4 @@
-<bind-notifier bind-notifier="{ rebind:search.results}">
+<bind-notifier bind-notifier="{ rebind:search.results}" ng-class="::motion.ionListClass">
 
   <div class="item row row-header hidden-xs hidden-sm" ng-if="expertMode">
     <a class="col col-header no-padding dark" ng-click="toggleSort('uid')">
@@ -22,7 +22,8 @@
   </div>
 
   <div ng-repeat="peer in :rebind:search.results track by peer.id"
-       class="item peer-item item-icon-left {{::ionItemClass}}"
+       class="item item-peer item-icon-left ink"
+       ng-class="::ionItemClass"
        id="helptip-network-peer-{{$index}}"
        ng-click="selectPeer(peer)">
 
diff --git a/www/templates/network/view_peer.html b/www/templates/network/view_peer.html
index 753d540c..658c3a8f 100644
--- a/www/templates/network/view_peer.html
+++ b/www/templates/network/view_peer.html
@@ -14,7 +14,7 @@
           <ion-spinner class="icon" icon="android"></ion-spinner>
       </div>
 
-      <a class="peer-item item item-icon-left"
+      <a class="item-peer item item-icon-left"
          collection-repeat="peer in peers"
          ng-class="{ assertive: !peer.online, balanced: peer.online }"
          target="_blank"
diff --git a/www/templates/wallet/view_wallet.html b/www/templates/wallet/view_wallet.html
index 73633e11..81dc4aac 100644
--- a/www/templates/wallet/view_wallet.html
+++ b/www/templates/wallet/view_wallet.html
@@ -84,7 +84,7 @@
 
       <div class="col">
 
-        <div class="list animate-fade-slide-in-right">
+        <div class="list" ng-class="::motion.ionListClass" ng-hide="loading">
 
           <!-- Certifications -->
           <a id="helptip-wallet-certifications"
diff --git a/www/templates/wallet/view_wallet_tx.html b/www/templates/wallet/view_wallet_tx.html
index e948cd9d..c19a2bad 100644
--- a/www/templates/wallet/view_wallet_tx.html
+++ b/www/templates/wallet/view_wallet_tx.html
@@ -53,7 +53,7 @@
 
       <div class="col">
 
-        <div class="list animate-fade-slide-in-right">
+        <div class="list" ng-class="::motion.ionListClass">
 
           <!-- Errors transactions-->
           <a class="item item-icon-left item-icon-right ink" ng-if="formData.tx.errors && formData.tx.errors.length" ui-sref="app.view_wallet_tx_errors">
diff --git a/www/templates/wallet/view_wallet_tx_error.html b/www/templates/wallet/view_wallet_tx_error.html
index b9cb3d70..3e749350 100644
--- a/www/templates/wallet/view_wallet_tx_error.html
+++ b/www/templates/wallet/view_wallet_tx_error.html
@@ -28,7 +28,7 @@
       <div class="col col-20 hidden-xs hidden-sm">&nbsp;
       </div>
 
-      <div class="col list animate-fade-slide-in-right">
+      <div class="col list" ng-class="::motion.ionListClass">
 
         <!-- Transactions in error -->
         <span class="item item-divider">
diff --git a/www/templates/wot/items_given_certifications.html b/www/templates/wot/items_given_certifications.html
index a24310b4..b009bd55 100644
--- a/www/templates/wot/items_given_certifications.html
+++ b/www/templates/wot/items_given_certifications.html
@@ -1,5 +1,5 @@
 
-<div class="list animate-fade-slide-in-right given-certifications">
+<div class="list given-certifications" ng-class="::motions.givenCertifications.ionListClass">
   <span class="item item-divider hidden-xs">
     <span translate>WOT.GIVEN_CERTIFICATIONS.SUMMARY</span>
   </span>
diff --git a/www/templates/wot/items_received_certifications.html b/www/templates/wot/items_received_certifications.html
index 06007965..2bcbc83a 100644
--- a/www/templates/wot/items_received_certifications.html
+++ b/www/templates/wot/items_received_certifications.html
@@ -1,4 +1,4 @@
-        <div class="list animate-fade-slide-in-right certifications">
+        <div class="list certifications" ng-class="::motions.receivedCertifications.ionListClass">
           <span class="item item-divider hidden-xs">
             <span translate>WOT.CERTIFICATIONS.SUMMARY</span>
           </span>
diff --git a/www/templates/wot/lookup_form.html b/www/templates/wot/lookup_form.html
index e9ad273e..6ca0f97e 100644
--- a/www/templates/wot/lookup_form.html
+++ b/www/templates/wot/lookup_form.html
@@ -68,8 +68,7 @@
       <span ng-if="search.type=='newcomers'" translate>WOT.LOOKUP.NO_NEWCOMERS</span>
     </div>
 
-    <ion-list
-      class="animate-ripple"
+    <ion-list class="{{::motion.ionListClass}}"
       can-swipe="$root.device.enable">
 
       <ion-item
diff --git a/www/templates/wot/view_certifications.html b/www/templates/wot/view_certifications.html
index a598ed0e..c3767f6b 100644
--- a/www/templates/wot/view_certifications.html
+++ b/www/templates/wot/view_certifications.html
@@ -42,14 +42,14 @@
       <!-- certifications tables -->
       <div class="row responsive-sm responsive-md responsive-lg">
         <!-- Received certifications -->
-        <div class="col no-padding" ng-if="motions.receivedCertifications">
+        <div class="col no-padding" ng-if="motions.receivedCertifications.enable">
           <ng-include src="'templates/wot/items_received_certifications.html'"></ng-include>
         </div>
 
         <!-- Avatar -->
         <div class="col col-20 col-avatar hidden-xs hidden-sm hidden-md no-padding" style="margin-top: 100px;"
-             ng-if="motions.avatar">
-          <div class="row no-padding motion fade-in">
+             ng-if="motions.avatar.enable">
+          <div class="row no-padding " ng-class="::motions.avatar.ionListClass">
             <div class="col text-center no-padding gray" style="margin-top: 30px;">
               <i class="icon ion-arrow-right-a" style="font-size:30px"></i>
             </div>
@@ -79,7 +79,7 @@
         </div>
 
         <!-- Given certifications -->
-        <div class="col no-padding" ng-if="motions.givenCertifications">
+        <div class="col no-padding" ng-if="motions.givenCertifications.enable">
           <ng-include src="'templates/wot/items_given_certifications.html'"></ng-include>
         </div>
       </div>
diff --git a/www/templates/wot/view_identity.html b/www/templates/wot/view_identity.html
index 24513b80..fb7c5ec5 100644
--- a/www/templates/wot/view_identity.html
+++ b/www/templates/wot/view_identity.html
@@ -1,4 +1,4 @@
-<ion-view left-buttons="leftButtons">
+<ion-view left-buttons="leftButtons" class="view-identity">
   <ion-nav-title>
   </ion-nav-title>
 
@@ -47,10 +47,10 @@
       </button>
     </div>
 
-    <div class="row no-padding">
+    <div class="row no-padding" >
       <div class="col col-20 hidden-xs hidden-sm">&nbsp;</div>
 
-      <div class="col list animate-fade-slide-in-right">
+      <div class="col list" ng-class="::motion.ionListClass">
 
         <span class="item item-divider" translate>WOT.GENERAL_DIVIDER</span>
 
@@ -122,7 +122,7 @@
   </ion-content>
 
   <!-- fab button -->
-  <div class="visible-xs visible-sm">
+  <div class="visible-xs visible-sm" ng-hide="loading">
     <button id="fab-transfer" class="button button-fab button-fab-bottom-right button-assertive expanded button-energized-900 drop"
             ng-click="showTransferModal({pubkey:formData.pubkey, uid: formData.uid})">
       <i class="icon ion-android-send"></i>
-- 
GitLab