diff --git a/scss/ionic.app.scss b/scss/ionic.app.scss
index 58a9f1666b64df3aba5a6df83aa92887ce5d92f7..1ea74a0f86d1717c6226aa25ee18a6f684666817 100644
--- a/scss/ionic.app.scss
+++ b/scss/ionic.app.scss
@@ -1125,6 +1125,7 @@ $ionicon-var-badge-editable: $ionicon-var-edit + "\00a0";
   padding: 0 15px;
 }
 
+
 @media screen and (max-width: $screen-xxs-max) {
   .card > .item.item-thumbnail-left,
   .item-thumbnail-left,
diff --git a/www/js/app.js b/www/js/app.js
index 3df37b1780f860dcec8f28bc7d089b88d178eeef..79680ca7e3eadc2b9e3be0d3858a1947afe05436 100644
--- a/www/js/app.js
+++ b/www/js/app.js
@@ -23,7 +23,7 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht
     };
   })
 
-  .filter('formatDecimal', function(csConfig) {
+  .filter('formatDecimal', function(csConfig, $rootScope) {
     var minValue = 1 / Math.pow(10, csConfig.decimalCount || 4);
     var format = '0,0.0' + Array(csConfig.decimalCount || 4).join('0');
 
diff --git a/www/js/controllers/app-controllers.js b/www/js/controllers/app-controllers.js
index d94843744e92615e170d63640950a55853ead469..db2c009340b7f587b3de5a9d50dc0b486afd2879 100644
--- a/www/js/controllers/app-controllers.js
+++ b/www/js/controllers/app-controllers.js
@@ -99,26 +99,17 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $
       templateUrl :'templates/common/popover_notification.html',
       scope: $scope,
       autoremove: false, // reuse popover
-      afterShow: function(popover) {
-        if (!popover.scope.markAllAsRead) {
-          popover.scope.markAllAsRead = function() {
-            $rootScope.walletData.notifications.unreadCount = 0;
-            var lastNotification = $rootScope.walletData.notifications.history[0];
-            $rootScope.walletData.notifications.readTime = lastNotification ? lastNotification.time : 0;
-            _.forEach($rootScope.walletData.notifications.history, function (item) {
-              if (item.onRead && typeof item.onRead == 'function') item.onRead();
-            });
-          };
-        }
-
-        $timeout(function() {
-          UIUtils.ink({selector: '.notification-popover .ink'});
-        }, 100);
-      },
       afterHidden: function() {
-        $rootScope.walletData.notifications.unreadCount = 0;
-        var lastNotification = $rootScope.walletData.notifications.history[0];
-        $rootScope.walletData.notifications.readTime = lastNotification ? lastNotification.time : 0;
+        csWallet.data.notifications.unreadCount = 0;
+        if (csWallet.data.notifications && csWallet.data.notifications.history.length) {
+          var lastNotification = csWallet.data.notifications.history[0];
+          var readTime = lastNotification ? lastNotification.time : 0;
+          csSettings.data.wallet = csSettings.data.wallet || {};
+          if (readTime && csSettings.data.wallet.notificationReadTime != readTime) {
+            csSettings.data.wallet.notificationReadTime = readTime;
+            csSettings.store();
+          }
+        }
       }
     })
     .then(function(item) {
@@ -357,9 +348,11 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $
   };
 
   // add listener on wallet event
-  csWallet.api.data.on.login($scope, function(walletData, resolve) {
+  csWallet.api.data.on.login($scope, function(walletData, deferred) {
+    deferred = deferred || $q.defer();
     $rootScope.login = true;
-    if (resolve) resolve();
+    deferred.resolve();
+    return deferred.promise;
   });
   csWallet.api.data.on.logout($scope, function() {
     $rootScope.login = false;
diff --git a/www/js/controllers/notification-controllers.js b/www/js/controllers/notification-controllers.js
index 2633a52d18d35c67e9253b460f56ce2b8bdfe5cf..768dadaad7308e982c073f2571a5544b3d2e4761 100644
--- a/www/js/controllers/notification-controllers.js
+++ b/www/js/controllers/notification-controllers.js
@@ -27,7 +27,7 @@ angular.module('cesium.notification.controllers', ['cesium.services'])
 
 ;
 
-function NotificationsController($scope, $rootScope, $timeout, UIUtils, $state, csWallet) {
+function NotificationsController($scope, $rootScope, $timeout, UIUtils, $state, csWallet, csSettings) {
 
   var defaultSearchLimit = 40;
 
@@ -45,16 +45,20 @@ function NotificationsController($scope, $rootScope, $timeout, UIUtils, $state,
     }
   });
 
-  $scope.load = function() {
+  $scope.load = function(from, size) {
+    from = from || 0;
+    size = size || defaultSearchLimit;
     return csWallet.refreshData({
       notifications: {
         enable: true,
-        from: 0,
-        size: $scope.search.limit
+        from: from,
+        size: size
       }
     })
-    .then(function() {
-      $scope.search.results = csWallet.data.notifications.history;
+    .then(function(data) {
+      if (from === 0) {
+        $scope.search.results = data.notifications.history;
+      }
       $scope.search.loading = false;
       $scope.search.hasMore = ($scope.search.results && $scope.search.results.length >= $scope.search.limit);
       $scope.updateView();
@@ -100,7 +104,7 @@ function NotificationsController($scope, $rootScope, $timeout, UIUtils, $state,
     }
     $scope.search.loadingMore = true;
     $scope.load(
-      $scope.search.results.length, // offset
+      $scope.search.results.length, // from
       $scope.search.limit)
     .then(function() {
       $scope.search.loadingMore = false;
@@ -110,9 +114,9 @@ function NotificationsController($scope, $rootScope, $timeout, UIUtils, $state,
 }
 
 
-function PopoverNotificationsController($scope, $rootScope, $timeout, UIUtils, $state, csWallet) {
+function PopoverNotificationsController($scope, $rootScope, $timeout, UIUtils, $state, csWallet, csSettings) {
 
-  NotificationsController.call(this, $scope, $rootScope, $timeout, UIUtils, $state, csWallet);
+  NotificationsController.call(this, $scope, $rootScope, $timeout, UIUtils, $state, csWallet, csSettings);
 
   $scope.updateView = function() {
     // Set Ink
@@ -121,7 +125,7 @@ function PopoverNotificationsController($scope, $rootScope, $timeout, UIUtils, $
     }, 100);
   };
 
-  if ($scope.search.loading) {
+  if ($scope.search.loading || !csWallet.data.notifications.history || !csWallet.data.notifications.history.length) {
     $scope.load();
   }
 
diff --git a/www/js/services/settings-services.js b/www/js/services/settings-services.js
index aef205e3f40bcf94b0d52d583c4dc53a0094fc9b..88b447eb54f857f6687dfb997e8f92a3e280d7f4 100644
--- a/www/js/services/settings-services.js
+++ b/www/js/services/settings-services.js
@@ -41,7 +41,8 @@ angular.module('cesium.settings.services', ['ngResource', 'ngApi', 'cesium.confi
         },
         wallet: {
           showPubkey: true,
-          alertIfUnusedWallet: true
+          alertIfUnusedWallet: true,
+          notificationReadTime: 0
         },
         locale: {
           id: fixLocale(csConfig.defaultLanguage || $translate.use()) // use config locale if set, or browser default
diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js
index c710a22dcc3615621b6d2c1d775fedfeaff6f236..3e8c2f6e8dafb4543c027a09ff98188a480969ca 100644
--- a/www/js/services/wallet-services.js
+++ b/www/js/services/wallet-services.js
@@ -791,6 +791,9 @@ angular.module('cesium.wallet.services', ['ngResource', 'ngApi', 'cesium.bma.ser
       })
       .then(function(){
         return api.data.raisePromise.finishLoad(data);
+      })
+      .then(function(){
+        return data;
       });
     },
 
diff --git a/www/plugins/es/i18n/locale-fr-FR.json b/www/plugins/es/i18n/locale-fr-FR.json
index ffb16db4cb95eaff32f8e725a2637920873333ef..4e5fbb2d995408f235ac55af7a77d0f6b20bd746 100644
--- a/www/plugins/es/i18n/locale-fr-FR.json
+++ b/www/plugins/es/i18n/locale-fr-FR.json
@@ -72,7 +72,8 @@
       "USER_NOT_RECIPIENT": "Vous n'etes pas le destinataire de ce message : déchiffrement impossible.",
       "NOT_AUTHENTICATED_MESSAGE": "L'authenticité du message est douteuse ou son contenu est corrompu.",
       "REMOVE_MESSAGE_FAILED": "Erreur de suppression du message",
-      "MESSAGE_CONTENT_TOO_LONG": "Valeur trop longue ({{maxLength}} caractères max)."
+      "MESSAGE_CONTENT_TOO_LONG": "Valeur trop longue ({{maxLength}} caractères max).",
+      "MARK_AS_READ_FAILED": "Impossible de marquer le message comme 'lu'."
     }
   },
   "MARKET": {
@@ -249,13 +250,15 @@
   },
   "EVENT": {
     "NODE_STARTED": "Votre noeud ES API <b>{{p0}}</b> est démarré",
-    "NODE_BMA_DOWN": "Noeud <b>{{p0}}:{{p1}}</b> injoignable (utilisé par votre ES API <b>{{p2}}</b>).<br/>Date de la dernière connection : {{p3|formatDate}}.",
-    "NODE_BMA_UP": "Noeud <b>{{p0}}:{{p1}}</b> à nouveau accessible.",
+    "NODE_BMA_DOWN": "Le noeud <b>{{p0}}:{{p1}}</b> (utilisé par votre noeud ES API) est <b>injoignable</b>.",
+    "NODE_BMA_UP": "Le noeud <b>{{p0}}:{{p1}}</b> est à nouveau accessible.",
     "MEMBER_JOIN": "Vous êtes maintenant <b>membre</b> de la monnaie <b>{{p0}}</b> !",
     "MEMBER_LEAVE": "Vous n'êtes <b>plus membre</b> de la monnaie <b>{{p0}}</b>!",
     "MEMBER_ACTIVE": "Votre renouvellement d'adhésion à la monnaie <b>{{p0}}</b> a été <b>pris en compte</b>.",
-    "TX_SENT": "Votre paiement à <b>{{p0|formatPubkey}}</b> a été effectué.",
-    "TX_RECEIVED": "Vous avez reçu un paiement de <b>{{p0|formatPubkey}}</b>.",
+    "TX_SENT": "Votre paiement à <a ui-sref=\"app.wot_view_identity({pubkey:'{{p1}}', uid:'{{p0}}'})\">{{p0}}</a> a été effectué.",
+    "TX_SENT_MULTI": "Votre paiement à <b>{{p0}}</b> a été effectué.",
+    "TX_RECEIVED": "Vous avez reçu un paiement de <a ui-sref=\"app.wot_view_identity({pubkey:'{{p1}}', uid:'{{p0}}'})\">{{p0}}</a>.",
+    "TX_RECEIVED_MULTI": "Vous avez reçu un paiement de <b>{{p0}}</b>.",
     "MARKET": {
       "NEW_COMMENT": "<b>{{p0}}</b> a commenté votre annonce: <b>{{p1}}</b>"
     },
diff --git a/www/plugins/es/js/controllers/market-controllers.js b/www/plugins/es/js/controllers/market-controllers.js
index b840dfdc09560b970be6bb6463d18f04078c598d..194d129598948c0e15e74d7820689003c8c239e1 100644
--- a/www/plugins/es/js/controllers/market-controllers.js
+++ b/www/plugins/es/js/controllers/market-controllers.js
@@ -262,18 +262,18 @@ function ESMarketLookupController($scope, $state, $focus, $timeout, $filter, $q,
     return $scope.doRequest(request, more);
   };
 
-  $scope.doGetLastRecord = function(offset, size) {
+  $scope.doGetLastRecord = function(from, size) {
     $scope.search.lastRecords = true;
 
-    offset = offset || 0;
+    from = from || 0;
     size = size || defaultSearchLimit;
-    var more = offset > 0;
+    var more = from > 0;
 
     var request = {
       sort: {
         "creationTime" : "desc"
       },
-      from: offset,
+      from: from,
       size: size,
       _source: esMarket.record.fields.commons
     };
@@ -378,9 +378,7 @@ function ESMarketLookupController($scope, $state, $focus, $timeout, $filter, $q,
           $scope.search.results = records;
         }
         else {
-          _.forEach(records, function(record) {
-            $scope.search.results.push(record);
-          });
+          $scope.search.results.splice($scope.search.results.length-1, 0, records);
         }
 
         if (records.length > 0) {
@@ -397,7 +395,7 @@ function ESMarketLookupController($scope, $state, $focus, $timeout, $filter, $q,
         }
       }
 
-      $scope.search.hasMore = $scope.search.results.length === $scope.search.limit;
+      $scope.search.hasMore = $scope.search.results.length >= $scope.search.limit;
       $scope.search.loading = false;
     })
     .catch(function(err) {
diff --git a/www/plugins/es/js/controllers/message-controllers.js b/www/plugins/es/js/controllers/message-controllers.js
index 684422e5f450428aaa9ba3aff7c52e29c5bd0e10..b7467097f642a6fc2106743984e6547704f7d05b 100644
--- a/www/plugins/es/js/controllers/message-controllers.js
+++ b/www/plugins/es/js/controllers/message-controllers.js
@@ -325,7 +325,35 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis
   $scope.$on('$ionicView.enter', function (e, state) {
     if (state.stateParams && state.stateParams.id) { // Load by id
       if ($scope.loading) { // prevent reload if same id
-        $scope.load(state.stateParams.id);
+        $scope.load(state.stateParams.id)
+          .then(function(message) {
+            $scope.loading = false;
+            UIUtils.loading.hide();
+            if (!message) return;
+
+            $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
+              });
+            });
+            // Mark as read
+            if (!message.read) {
+              $timeout(function() {
+                // Message has NOT changed
+                if ($scope.id == message.id) {
+                  esMessage.markAsRead(message)
+                    .then(function() {
+                      console.debug("[message] marked as read");
+                    })
+                    .catch(UIUtils.onError('MESSAGE.ERROR.MARK_AS_READ_FAILED'));
+                }
+              }, 2000); // 2s
+            }
+          });
       }
 
       $scope.showFab('fab-view-message-reply');
@@ -337,51 +365,26 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis
 
   $scope.load = function(id) {
 
-    $scope.loadWallet()
-      .then(function(){
-        UIUtils.loading.hide();
-
-        return esMessage.get({id: id})
-          .then(function(message) {
-
-            if (!message.valid) {
-
-              return UIUtils.alert.error(!$scope.isUserPubkey(message.recipient) ? 'MESSAGE.ERROR.USER_NOT_RECIPIENT' : 'MESSAGE.ERROR.NOT_AUTHENTICATED_MESSAGE',
-                'MESSAGE.ERROR.MESSAGE_NOT_READABLE')
-                .then(function () {
-                  $state.go('app.user_message');
-                });
-            }
-
-            $scope.formData = message;
-            $scope.canDelete = true;
-            $scope.loading = false;
-
-            // Load avatar and name (and uid)
-            return esUser.profile.fillAvatars([{pubkey: $scope.formData.issuer}])
-              .then(function (idties) {
-                return idties[0];
-              });
-          })
-          .then(function(member) {
-            $scope.issuer = member;
-
-            // Set Motion (only direct children, to exclude .lazy-load children)
-            $timeout(function () {
-              UIUtils.motion.fadeSlideIn({
-                startVelocity: 3000
-              });
-            }, 10);
-          })
-          .catch(UIUtils.onError('MESSAGE.ERROR.LOAD_MESSAGE_FAILED'));
+    return $scope.loadWallet()
+      .then(function() {
+        return esMessage.get({id: id});
       })
-      .catch(function(err){
-        if (err === 'CANCELLED') {
-          $ionicHistory.nextViewOptions({
-            historyRoot: true
-          });
-          $state.go('app.user_message');
+      .catch(UIUtils.onError('MESSAGE.ERROR.LOAD_MESSAGE_FAILED'))
+      .then(function(message) {
+        if (!message.valid) {
+          return UIUtils.alert.error(!$scope.isUserPubkey(message.recipient) ? 'MESSAGE.ERROR.USER_NOT_RECIPIENT' : 'MESSAGE.ERROR.NOT_AUTHENTICATED_MESSAGE',
+            'MESSAGE.ERROR.MESSAGE_NOT_READABLE')
+            .then(function () {
+              $state.go('app.user_message');
+            });
         }
+
+        // Load avatar and name (and uid)
+        return esUser.profile.fillAvatars([{pubkey: message.issuer}])
+          .then(function (idties) {
+            $scope.issuer = idties[0];
+            return message;
+          });
       });
   };
 
diff --git a/www/plugins/es/js/entities/notification.js b/www/plugins/es/js/entities/notification.js
index a628e7593f10f5bcfb6569f3f468949510a25b3b..8d0636a993ede26cfca0d48b50fdb490be4a8bee 100644
--- a/www/plugins/es/js/entities/notification.js
+++ b/www/plugins/es/js/entities/notification.js
@@ -32,6 +32,16 @@ function Notification(json, onReadCallback) {
   // TX
   if (json.code.startsWith('TX_')) {
     that.icon = 'ion-card';
+    var pubkeys = json.params.length > 1 ? json.params[1] : null;
+    if (pubkeys && pubkeys.indexOf(',') == -1) {
+      /*that.state = 'app.wot_view_identity';
+      that.stateParams = {
+        pubkey: pubkeys,
+        uid: json.params[0]
+      };*/
+      that.pubkey = pubkeys;
+      that.name = json.params[0];
+    }
   }
 
   // member
@@ -87,6 +97,6 @@ function Notification(json, onReadCallback) {
   }
   // error message
   else if (json.type == 'ERROR') {
-    that.icon = 'ion-alert';
+    that.icon = 'ion-alert-circled assertive';
   }
 }
diff --git a/www/plugins/es/js/services/message-services.js b/www/plugins/es/js/services/message-services.js
index 668384fc15a558d6cb8680a47f467b203efbcc88..4063c9e097c88084fca46f5265f07ede359ed2c7 100644
--- a/www/plugins/es/js/services/message-services.js
+++ b/www/plugins/es/js/services/message-services.js
@@ -34,7 +34,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', '
 
     function onWalletInit(data) {
       data.messages = data.messages || {};
-      data.messages.count = null;
+      data.messages.unreadCount = null;
     }
 
     function onWalletReset(data) {
@@ -54,25 +54,21 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', '
         return deferred.promise;
       }
 
-      var lastMessageTime = csSettings.data && csSettings.data.plugins && csSettings.data.plugins.es ?
-        csSettings.data.plugins.es.lastMessageTime :
-        undefined;
-
-      // Count new messages
-      countNewMessages(data.pubkey, lastMessageTime)
-        .then(function(count){
+      // Count unread messages
+      countUnreadMessages(data.pubkey)
+        .then(function(unreadCount){
           data.messages = data.messages || {};
-          data.messages.count = count;
-          console.debug('[ES] [message] Detecting ' + count + (lastMessageTime ? ' unread' : '') + ' messages');
+          data.messages.unreadCount = unreadCount;
+          console.debug('[ES] [message] Detecting ' + unreadCount + ' unread messages');
           deferred.resolve(data);
         })
         .catch(function(err){
+          console.error('Error chile counting message: ' + (err.message ? err.message : err));
           deferred.resolve(data);
         });
       return deferred.promise;
     }
 
-
     function getBoxKeypair(keypair) {
       keypair = keypair || (csWallet.isLogin() ? csWallet.data.keypair : keypair);
       if (!keypair) {
@@ -88,25 +84,26 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', '
       return csWallet.data.keypair;
     }
 
-    function countNewMessages(pubkey, fromTime) {
+    function countUnreadMessages(pubkey) {
       pubkey = pubkey || (csWallet.isLogin() ? csWallet.data.pubkey : pubkey);
       if (!pubkey) {
         throw new Error('no pubkey, and user not connected.');
       }
 
       var request = {
-        size: 0,
-        query: {constant_score: {filter: [{term: {recipient: pubkey}}]}}
+        query: {
+          bool: {
+            must: [
+              {term: {recipient: pubkey}},
+              {missing: { field : "read_signature" }}
+            ]
+          }
+        }
       };
 
-      // Add time filter
-      if (fromTime) {
-        request.query.constant_score.filter.push({range: {time: {gt: fromTime}}});
-      }
-
-      return esHttp.post(host, port, '/message/record/_search')(request)
+      return esHttp.post(host, port, '/message/record/_count')(request)
         .then(function(res) {
-          return res.hits ? res.hits.total : 0;
+          return res.count;
         });
     }
 
@@ -195,6 +192,9 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', '
             msg.id = hit._id;
             msg.pubkey = msg.issuer !== walletPubkey ? msg.issuer : msg.recipient;
 
+            msg.read = !!msg.read_signature;
+            delete msg.read_signature;
+
             // Get uid (if member)
             return BMA.wot.member.get(msg.pubkey)
               .then(function(user) {
@@ -269,6 +269,22 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', '
         });
     }
 
+    // Mark a message as read
+    function markMessageAsRead(message) {
+      if (message.read) {
+        var deferred = $q.defer();
+        deferred.resolve();
+        return deferred.promise;
+      }
+      message.read = true;
+      csWallet.data.messages = csWallet.data.messages || {};
+      csWallet.data.messages.unreadCount = csWallet.data.messages.unreadCount ? csWallet.data.messages.unreadCount-1 : 0;
+      return CryptoUtils.sign(message.hash, csWallet.data.keypair)
+        .then(function(signature){
+          return esHttp.post(host, port, '/message/record/:id/_read')(signature, {id:message.id})
+        });
+    }
+
     function removeListeners() {
       console.debug("[ES] Disable message extension");
 
@@ -326,6 +342,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', '
       get: getAndDecrypt,
       send: sendMessage,
       remove: removeMessage,
+      markAsRead: markMessageAsRead,
       fields: {
         commons: fields.commons
       }
diff --git a/www/plugins/es/js/services/user-services.js b/www/plugins/es/js/services/user-services.js
index 6726be9482481404c1373b3451895e9e5e307cb8..b81f8876d89c79a4e13b28daaafaba700f0a5612 100644
--- a/www/plugins/es/js/services/user-services.js
+++ b/www/plugins/es/js/services/user-services.js
@@ -160,7 +160,7 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se
     }
 
     // Load unread notifications count
-    function loadUnreadNotificationsCount(pubkey) {
+    function loadUnreadNotificationsCount(pubkey, readTime) {
       var request = {
         query: {
           bool: {
@@ -172,6 +172,7 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se
         }
       };
 
+      // Filter codes
       var excludesCodes = [];
       if (!csSettings.getByPath('plugins.es.notifications.txSent', false)) {
         excludesCodes.push('TX_SENT');
@@ -183,6 +184,11 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se
         request.query.bool.must_not = {terms: { code: excludesCodes}};
       }
 
+      // Filter time
+      if (readTime) {
+        request.query.bool.must.push({range: {time: {gte: readTime}}});
+      }
+
       return esHttp.post(host, port, '/user/event/_count')(request)
         .then(function(res) {
           return res.count;
@@ -204,13 +210,13 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se
         sort : [
           { "time" : {"order" : "desc"}}
         ],
-        from:from,
+        from: from,
         size: size,
         _source: ["type", "code", "params", "reference", "recipient", "time", "hash", "read_signature"]
       };
 
+      // Filter codes
       var excludesCodes = [];
-
       if (!csSettings.getByPath('plugins.es.notifications.txSent', false)) {
         excludesCodes.push('TX_SENT');
       }
@@ -224,21 +230,14 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se
       return esHttp.post(host, port, '/user/event/_search')(request)
         .then(function(res) {
           if (!res.hits || !res.hits.total) return;
-          var unreadCount = 0;
-          var history = res.hits.hits.reduce(function(res, hit) {
+          return res.hits.hits.reduce(function(res, hit) {
             var item = new Notification(hit._source, markNotificationAsRead);
             item.id = hit._id;
-            unreadCount = item.read ? unreadCount : unreadCount+1;
             return res.concat(item)
           }, []);
-          return {
-            history: history,
-            unreadCount: unreadCount
-          };
         });
     }
 
-
     // Mark a notification as read
     function markNotificationAsRead(notification) {
       return CryptoUtils.sign(notification.hash, csWallet.data.keypair)
@@ -274,7 +273,6 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se
       }
 
       console.debug('[ES] [user] Loading user data from ES node...');
-
       $q.all([
         // Load settings
         loadSettings(data.pubkey, data.keypair)
@@ -290,9 +288,12 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se
           }),
 
         // Load unread notifications count
-        loadUnreadNotificationsCount(data.pubkey)
+        loadUnreadNotificationsCount(
+            data.pubkey,
+            csSettings.data.wallet ? csSettings.data.wallet.notificationReadTime : 0)
           .then(function(unreadCount) {
             data.notifications.unreadCount = unreadCount;
+            data.notifications.history = null; // remove list (usefull when settings changed)
           }),
 
         // Load profile avatar and name
@@ -340,16 +341,24 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se
       }
 
       // Load user notifications
-      loadNotifications(data.pubkey, options.notifications.from, options.notifications.size)
-        .then(function(notifications) {
-          data.notifications.history = notifications.history;
-          data.notifications.unreadCount = notifications.unreadCount;
-          deferred.resolve(data);
-        })
-        .catch(function(err) {
-          deferred.reject(err);
-        })
-      ;
+      loadNotifications(data.pubkey,
+        options.notifications.from,
+        options.notifications.size)
+      .then(function(notifications) {
+        if (!notifications || !notifications.length || !options.notifications.from) {
+          data.notifications.history = notifications;
+        }
+        else {
+          // Concat (but keep original array - for data binding)
+          _.forEach(notifications, function(notification){
+            data.notifications.history.push(notification);
+          });
+        }
+        deferred.resolve(data);
+      })
+      .catch(function(err) {
+        deferred.reject(err);
+      });
 
       return deferred.promise;
     }
@@ -542,6 +551,8 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se
         .then(function() {
           // Change settings version
           csSettings.data.time = record.time;
+          // Force notifications reload
+          csWallet.data.notifications.history = [];
           restoringSettings = true;
           csSettings.store();
           console.debug('[ES] [user] User settings saved in ES');
diff --git a/www/plugins/es/templates/menu_extend.html b/www/plugins/es/templates/menu_extend.html
index 3dca9306de2f8a284563d59a77ab551d3d99449d..2364449407345ffa3b2e50addba9da510ac53233 100644
--- a/www/plugins/es/templates/menu_extend.html
+++ b/www/plugins/es/templates/menu_extend.html
@@ -9,8 +9,8 @@
           active-link-path-prefix="#/app/user/message"
           ng-click="loginAndGo('app.user_message')">
     <span
-      ng-if="$root.walletData.messages.count"
-      class="badge badge-button badge-positive">{{$root.walletData.messages.count}}</span>
+      ng-if="$root.walletData.messages.unreadCount"
+      class="badge badge-button badge-positive">{{$root.walletData.messages.unreadCount}}</span>
   </button>
 </ng-if>
 
diff --git a/www/plugins/es/templates/message/view_message.html b/www/plugins/es/templates/message/view_message.html
index 78d32205b1daddb0969c6142b019dce303f54a73..47feda00d4103d98e191c9058cf6b53ea306c5ee 100644
--- a/www/plugins/es/templates/message/view_message.html
+++ b/www/plugins/es/templates/message/view_message.html
@@ -1,4 +1,4 @@
-<ion-view left-buttons="leftButtons">
+<ion-view left-buttons="leftButtons" class="view-message">
   <ion-nav-title>
     <span translate>MESSAGE.VIEW.TITLE</span>
   </ion-nav-title>
diff --git a/www/templates/common/item_notification.html b/www/templates/common/item_notification.html
index 66057637d7d20e777dc8ae3b9f85466819293fc6..51a524da251b6b1450b53be4f64b86b0b6d808fd 100644
--- a/www/templates/common/item_notification.html
+++ b/www/templates/common/item_notification.html
@@ -3,7 +3,7 @@
      ng-class="{'unread': !notification.read}">
     <img ng-src="{{::notification.thumbnail.src}}" ng-if="notification.thumbnail"></img>
     <i class="item-image {{::notification.icon}}" ng-if="!notification.thumbnail"></i>
-    <span ng-bind-html="notification.message|translate:notification.messageParams"></span>
+    <span trust-as-html="notification.message | translate:notification.messageParams"></span>
     <h4>
       <span class="dark"><i class="icon ion-clock"></i>&nbsp;{{notification.time|formatFromNow}}</span>
       <span class="gray">| {{notification.time|formatDate}}</span>
diff --git a/www/templates/common/popover_notification.html b/www/templates/common/popover_notification.html
index a41caab952bbad7bf1e56b64e589a4879ca2c7b0..87eef3b81dddf2dbefd99628d6c6782e6cd3f729 100644
--- a/www/templates/common/popover_notification.html
+++ b/www/templates/common/popover_notification.html
@@ -16,11 +16,11 @@
       COMMON.NOTIFICATIONS.NO_RESULT
     </div>
     <ion-list>
-      <a ng-repeat="notification in search.results"
+      <div ng-repeat="notification in search.results"
          ng-click="closePopover(notification)">
 
         <ng-include src="'templates/common/item_notification.html'"></ng-include>
-      </a>
+      </div>
     </ion-list>
   </ion-content>
 
diff --git a/www/templates/common/view_notifications.html b/www/templates/common/view_notifications.html
index 39d44589eacb20799ca0bf87bd5e2c67e7ae1bdb..527deffab5ad1f82883ad3a9bfd3085004c70e6c 100644
--- a/www/templates/common/view_notifications.html
+++ b/www/templates/common/view_notifications.html
@@ -1,4 +1,11 @@
-<ion-view view-title="{{'COMMON.NOTIFICATIONS.TITLE' | translate}}" id="notification">
+<ion-view left-buttons="leftButtons"
+          class="pane"
+          cache-view="false"
+          id="notification">
+  <ion-nav-title>
+    {{'COMMON.NOTIFICATIONS.TITLE' | translate}}
+  </ion-nav-title>
+
   <ion-content class="padding no-padding-xs" scroll="true">
 
     <!-- Buttons bar-->
@@ -25,10 +32,10 @@
 
         <div class="list animate-fade-slide-in-right">
 
-          <a ng-repeat="notification in search.results"
+          <div ng-repeat="notification in search.results"
                ng-click="onSelect(notification)">
             <ng-include src="'templates/common/item_notification.html'"></ng-include>
-          </a>
+          </div>
 
           <!-- show more items -->
           <div class="item padding done in" ng-if="search.loadingMore">
diff --git a/www/templates/menu.html b/www/templates/menu.html
index 695c4064b0bcafb4d4b12c4883f7ee27255a0254..15bfe78d00f46ee1d4708a6a063f11abadfceb85 100644
--- a/www/templates/menu.html
+++ b/www/templates/menu.html
@@ -17,6 +17,7 @@
         <button class="button button-clear  hidden-xs hidden-sm icon ion-android-notifications"
                 ng-if="$root.login"
                 active-link="gray"
+                href="#/app/notifications"
                 ng-click="showNotificationsPopover($event)">
           <span
             ng-if="$root.walletData.notifications.unreadCount"